Agent Mentor Learn
状態管理と永続化: 長いタスクを中断から生き延びさせる · 第 1 回 / 全 6 回

レッスン1: メモリの先にある「状態」

学習目標:

  • 「メモリ」(モデルに与えるコンテキスト)と「実行状態」(ハーネスが抱えている実行中の場面)を一文で区別し、それぞれの例を挙げる
  • 「長時間タスクにとってクラッシュがとりわけ致命的である」根拠を最低3つ具体的に挙げ、それぞれが実行のどの部分を指しているかを言う
  • 実行中のハーネスが抱えているものの一覧を与えられたとき、それぞれがメモリか、実行状態か、ディスク出力かを判定し、プロセスが落ちても残るかどうかを判定する

前提: このシリーズの前のコースを終えていて、"Agent Harness Fundamentals: Loops and Control" のstop_reason駆動のハーネスループと、"Context Engineering: Spending Finite Attention Where It Counts" のコンテキスト管理を理解していること | 次: レッスン2 >>

23ターン目でプロセスが落ちる

"Agent Harness Fundamentals: Loops and Control" で書いたハーネスが、40ターンかかる長時間タスクを実行しているところを想像してください。ファイルをまとめて読み込み、1つずつ分析し、結論をレポートに追記していく、という作業です。23ターン目で、プロセスが落ちました。デプロイの更新かもしれませんし、サーバーの電源が落ちたのかもしれませんし、Ctrl+Cを押し間違えたのかもしれません。

ディスクを確認します。最初の22ターン分のレポートファイルはすべて残っています。NOTES.md("Context Engineering: Spending Finite Attention Where It Counts" で用意したタスク進捗の要約)にも「どのファイルまで分析したか、その結論は何だったか」がまだ記録されています。大した損失はなさそうに見えます。プロセスを再起動して、止まったところから続ければいいだけに思えます。

ところが再起動してみると、runAgentmessages配列は空です。[{ role: "user", content: userInput }]から組み立て直すしかありません。turnsカウンタはゼロに戻っています。tokensUsedもゼロに戻っています。そしてもしクラッシュが23ターン目の「モデルがツールを指名した」と「ツールの結果がmessagesに押し戻された」のちょうど間で起きていたなら、そのツール呼び出しは、実行が始まったばかりだったのか、すでに完了していたのかにかかわらず、痕跡を何ひとつ残していません。

タスクは23ターン目からは再開されません。1ターン目からやり直しです。ディスク上のファイルはすべて残っているのに、ハーネス自身の「どこまで進んだか」という記録は、何ひとつ残らなかったのです。

メモリとは何か、状態とは何か

本コースが本題を教えるためには、その前に、混同しやすい概念との間に線を引いておく必要があります。

メモリとは、モデルに与えるコンテキストのことです。コース5「エージェントメモリと状態」はそれをセッションをまたいで永続化する方法を扱い、コース8 "Context Engineering: Spending Finite Attention Where It Counts" は毎ターン何をモデルに見せるのかを正確に扱います。メモリが答える問いは「モデルは何を見てきたか?」です。NOTES.mdはメモリの運搬手段のひとつです。すでにディスクに書かれていて、次のターンや次のセッションが読み戻してプロンプトに入れることができます。

実行状態とは、ハーネスのプロセス自身が抱えている実行中の場面のことです。messages配列、turnstokensUsedといったカウンタ、まだ記録されていないツール呼び出しがこれにあたります。実行状態が答える問いは「ハーネスはどこまで進んだかを覚えているか?」です。

この2つの決定的な違いは「中身が何か」ではなく「いま現在どこに置かれているか」です。メモリはすでにディスク上にあるかもしれません(NOTES.mdはファイルシステムの中にあり、プロセスが生きていようが死んでいようが、そこに在り続けることは変わりません)。一方の実行状態は、デフォルトではプロセスのメモリ上にしか存在しません。let messages = [...]という行が作り出したものは、誰かが意図的にディスクへ書き出さないかぎり、プロセスが終了した瞬間にメモリごと回収されます。前節に出てきたもの——messagesturnstokensUsed、宙ぶらりんのツール呼び出し——は、どれひとつとして自動的にディスクに書かれることはありません。

このstateこそが、本コースがディスクに書き出して復元できるようにする方法を教えていく対象です。

長時間タスクではこれが死活問題になる理由

まず勘定を合わせましょう。"Agents can run for long periods of time, maintaining state across many tool calls."1(エージェントは長時間動き続け、多数のツール呼び出しをまたいで状態を保持しうる)。23ターン目のmessages配列が膨らみ続けるのは、まさにこのためです。しかしそれは同時に、"Agents are stateful and errors compound."1(エージェントはステートフルであり、エラーは複合していく)ということでもあります。状態が積み上がるほど、鎖のどこかが壊れた瞬間のコストは線形ではなく、積み重なっていきます。

もうひとつ加えましょう。"Without effective mitigations, minor system failures can be catastrophic for agents."1(有効な緩和策がなければ、軽微なシステム障害がエージェントにとって致命的になりうる)。「軽微」と「致命的」を並べて置いたこの一文は、まさに23ターン目の状況を言い当てています。プロセスが落ちること自体はごくありふれた運用上の出来事ですが、それが22ターン分の実行状態を一撃で消し去るからこそ、コストが増幅されるのです。

エラーが起きたあとについてはこうです。"When errors occur, we can't just restart from the beginning: restarts are expensive and frustrating for users."1(エラーが起きたとき、単に最初からやり直すことはできない。再実行はコストが高く、ユーザーにとって苛立たしい)。だから作るべきなのは、"Instead, we built systems that can resume from where the agent was when the errors occurred."1(代わりに私たちは、エラーが起きた地点のエージェントの状態から再開できるシステムを構築した)というシステムです。「メモリの先に状態がある」というのが学術的な区別ではなく、長時間タスクが中断を生き延びられるかどうかの土台である理由が、ここにあります。

タスクが長いほど、この請求書は重くなります。"The LLM will potentially operate for many turns, and you must have some level of trust in its decision-making."2(LLMは多数のターンにわたって動作しうるため、その意思決定にある程度の信頼を置かざるをえない)。そして "The autonomous nature of agents means higher costs, and the potential for compounding errors."2(エージェントの自律性は、より高いコストと、エラーが複合する可能性を意味する)。ターン数が増えるほど、積み上がる実行状態は厚くなり、たった一度の中断が消し去るものも大きくなります。

クラッシュは珍しくない

23ターン目の「プロセスが落ちた」は確率の低い事故のように聞こえますが、数十ターン走る長時間タスクにとって、途中で中断されることはまったく珍しくありません。もっともありふれたデプロイの更新ですら、動作中のエージェントとぶつかりえます。だからこそチームは意図的に "use rainbow deployments to avoid disrupting running agents, by gradually shifting traffic from old to new versions"1(実行中のエージェントを妨げないよう、トラフィックを旧バージョンから新バージョンへ段階的に移すレインボーデプロイを用いる)のであり、その理由は "whenever we deploy updates, agents might be anywhere in their process."1(更新をデプロイするとき、エージェントは処理のどの地点にいてもおかしくない)だからです。

言い換えれば、運用を回している当人たちですら「エージェントはいつ中断されてもおかしくない」を起こりうる前提として扱い、それを避けるための仕組みをわざわざ設計しているということです。あなたのハーネスだけが幸運だと考える理由はありません。

処方箋の予告: 本コースのロードマップ

23ターン目で失われた実行状態には、5段階の処方箋があります。それはそのまま、以降5レッスンの順番でもあります。

  1. チェックポイント(レッスン2)— messagesturnstokensUsed、宙ぶらりんのツール呼び出しといった実行状態を、定期的にシリアライズしてディスク上のチェックポイントファイルに書き出します。
  2. チェックポイントからの再開(レッスン3)— プロセス再起動後、その状態をチェックポイントファイルから読み戻し、messagesを再構築し、1ターン目からやり直すのではなく、壊れた地点からループを続けさせます。
  3. 副作用と冪等性(レッスン4)— 再開のいちばん難しい部分は「状態が消えたこと」ではなく、「一部のツール呼び出しは実際にもう実行済みかもしれないこと」です。どのツールなら再実行しても安全で、どのツールは二重実行を防がなければならないのかを扱います。
  4. 巻き戻しとフォーク(レッスン5)— チェックポイントは災害復旧のためだけのものではありません。以前の場面に巻き戻してやり直したり、あるノードから別の試行を分岐させたりすることもできます。
  5. 実践(レッスン6)— これまでのレッスンの仕組みを、"Agent Harness Fundamentals: Loops and Control" のハーネスに組み込み、長時間タスクを「途中で落とし、再起動し、最後まで走り切らせる」まで自分の手で通します。

「ハーネスエンジニアリング」を軸に据えたコミュニティのオープンソースロードマップは、これを一行にまとめています。"Checkpoint state every node so you can resume, rewind, fork."3(再開・巻き戻し・フォークができるよう、あらゆるノードで状態をチェックポイントせよ)。これは永続化コンポーネントが何を担うのかについてのコミュニティ文書の枠づけであって、本コースがそのまま写し取る仕様ではありませんが、それが指し示す順序は上の5段階と一致しています。

見合うかどうか: すべてのタスクに必要なわけではない

すべてのエージェントがチェックポイントの仕組みを背負う必要はありません。複雑さの追加についてはこう言われています。"you should consider adding complexity only when it demonstrably improves outcomes."2(複雑さを加えるのは、それが結果を明確に改善すると示せるときだけにすべきである)。数ターンのツール呼び出しで終わるタスクならmessagesのエントリは数えるほどしかなく、プロセスが落ちたら実行し直せば済みます。そのコストはもう一度尋ねることであって、保存と復元の仕組みをまるごと設計するほどのものではありません。

本コースの仕組みが実際に必要になるのは、冒頭の23ターン目のような場面です。数十ターン走り、数分から数時間かかることもあり、その過程で永続化されていない実行状態を大量に積み上げていくタスクです。チェックポイントを導入すべきかを判断するには、まず自分にこう問いかけてください。いまこの瞬間に落とされたとして、実行し直すコストを受け入れられますか? 受け入れられないなら、そこからが以降のレッスンの出番です。

まとめ

  • エージェントは長時間動き続け、多数のツール呼び出しをまたいで状態を保持しうる。そしてまさにそれゆえに、エージェントはステートフルであり、エラーは複合していく1。状態が積み上がるほど、一度の障害が消し去るものは大きくなる。
  • 有効な緩和策がなければ、軽微なシステム障害がエージェントにとって致命的になりうる1。エラーのあとに最初からやり直すことはできない。再実行はコストが高くユーザーにとって苛立たしいからであり、だからこそエラーが起きた地点から再開するシステムを構築する1
  • クラッシュは珍しくない。ありふれたデプロイの更新ですら、実行中のエージェントを妨げないためにレインボーデプロイを必要とする。デプロイ時点で、エージェントは処理のどの地点にいてもおかしくないからだ1
  • 自律的な動作には、本質的により高いコストとエラーが複合するリスクが伴う2。タスクが長いほどこの請求書は重くなり、中断を生き延びる仕組みがより必要になる。
  • すべてのタスクがこの仕組みを背負う必要はない。複雑さを加えるのは、それが結果を明確に改善すると示せるときだけにすべきであり2、数ターンで終わるタスクなら実行し直すコストはたいてい受け入れられる。
  • メモリ(モデルに与えるコンテキスト)と実行状態(ハーネスが抱えている実行中の場面)は別物である。メモリはすでに永続化されているかもしれないが、実行状態はデフォルトではプロセスメモリ上にしか存在しない。以降のレッスンは、その実行状態もまたディスクに書き出して復元できるものへと変えていく話である。

>> レッスン2: チェックポイント: 実行中の場面をディスクに書き出す

Footnotes

  1. How we built our multi-agent research system — Anthropic Engineering — https://www.anthropic.com/engineering/multi-agent-research-system 2 3 4 5 6 7 8 9 10 11

  2. Building Effective AI Agents — Anthropic Engineering — https://www.anthropic.com/engineering/building-effective-agents 2 3 4 5

  3. The 2026 Agent Engineering Roadmap — GitHub (codejunkie99/agent-roadmap-2026) — https://github.com/codejunkie99/agent-roadmap-2026

練習

01

以下は、実行中のハーネスに関わる6つの「もの」です。それぞれを「メモリ」「実行状態」「ディスク出力」のいずれかに仕分けし、いまこの瞬間にプロセスが落ちたとして、それがまだ残っているかどうかを答えてください。

レベル1: 実行中の6つの「もの」を分類する
  1. すでにNOTES.mdに書き込まれたタスク進捗の要約("Context Engineering: Spending Finite Attention Where It Counts" で用意したもの)
  2. メモリ上のmessages配列
  3. すでにディスクに書き出されたレポートファイルreport.md
  4. turnsカウンタ(何ターン目か)
  5. モデルがこのターンに生成した応答テキストの中にある、プロジェクト構造についての分析のひとくだり。まだNOTES.mdには書き込まれていない
  6. モデルが指名したtool_useブロックで、そのツールはまだ実行を終えておらず、結果もmessagesに押し戻されていないもの
完了基準 · ローカルでチェック
02

冒頭の場面に戻ります。"Agent Harness Fundamentals: Loops and Control" のrunAgent(messages、turns、tokensUsedという変数をstop_reasonループで回すもの)が40ターンのタスクを実行していて、23ターン目でプロセスが落ちました。しかもクラッシュは「モデルがツールを指名した」と「ツールの結果がmessagesに押し戻された」のちょうど間で起きています。コードを書かずに、言葉で次の2つをやってください。

レベル2: "Agent Harness Fundamentals" のハーネスにクラッシュ損失の棚卸しを書く
  1. クラッシュ損失の棚卸し: このクラッシュは正確に何を失いましたか? 影響を受けずに残っているものは何ですか?
  2. チェックポイントが持つべきもの: このハーネスにチェックポイントの仕組みがあったとして、この損失をできるだけ小さくするために、チェックポイントファイルは最低限どのフィールドを保持する必要があると思いますか? フィールド名を挙げ、それぞれをなぜ保存しなければならないかを述べてください。
完了基準 · ローカルでチェック