エージェント状態完全ガイド|自律型AIの状態管理・記憶・再開・永続化を正しく設計する方法
自律型AIを単純な「質問を入力して回答を返す仕組み」から、複数の手順を実行し、外部ツールを呼び出し、途中で人間の承認を待ち、失敗した処理を再開できるシステムへ発展させると、モデルそのものよりも重要になるのが状態管理です。エージェントは、現在どの作業を行っているのか、何をすでに確認したのか、どのツールを実行したのか、次に何をすべきなのか、利用者からどの権限を与えられているのかを保持できなければ、長い処理を一貫して進められません。
現在のエージェント基盤でも、会話履歴を継続的に保存する仕組み、実行中だけ利用する局所的な文脈、停止した実行を再開するための状態保存などは明確に区別されています。OpenAI Agents SDKでは、局所文脈はプログラムから利用できる実行時情報であり、そのまま言語モデルへ送られる情報とは別に扱われます。またセッションは複数回のエージェント実行をまたいで会話履歴を保持する永続的な記憶層として提供されています。
さらにLangGraphでは、状態を持つ長時間実行型エージェントを中心的な設計対象とし、チェックポイントによる短期記憶と保存領域による長期記憶を分けています。つまりエージェント状態は「過去の会話を保存するだけの箱」ではありません。現在の作業位置、途中結果、外部世界との同期状態、権限、失敗情報、再開地点まで含めて、エージェントが時間をまたいで一貫した行動を続けるための実行基盤として設計する必要があります。
1. エージェント状態が自律型AIの行動をつなぐ
エージェント状態は、一回のモデル呼び出しを超えて処理を継続させるための中心的な情報です。状態が曖昧なシステムでは、モデルが高性能でも同じツールを繰り返し実行したり、すでに完了した作業を再び始めたり、利用者が承認していない操作へ進んだりします。そのため、まず「現在の実行を成立させるために何を覚えておく必要があるか」を明確にする必要があります。 実装時には、承認の有無だけでなく、誰が何に対して承認したのか、承認後に対象内容が変更されていないかまで確認できる形にすると安全です。さらに、実行直前にも状態を検証すれば、古い承認や別操作への誤用を防ぎやすくなり、監査時にも判断根拠を追跡できます。
1.1 現在の作業地点を状態として保持する
複数段階のタスクでは、「まだ開始していない」「情報収集中」「候補を比較中」「利用者の承認待ち」「実行済み」「失敗して再試行待ち」といった作業段階を区別する必要があります。会話履歴だけから毎回この段階を推測すると、モデルの判断が揺れ、同じ入力でも異なる処理地点へ進む可能性があります。 この種の情報はモデルへの自然言語指示だけに依存させず、アプリケーション側の検証条件として持たせることが重要です。承認記録と実行対象を識別子で結び付けておけば、再開や再試行が発生しても、許可された操作だけを確実に進められます。
そのため、現在段階を明示的な状態値として保存します。例えば旅行予約エージェントなら、目的地確認済み、日程確認済み、航空券候補取得済み、購入承認待ちといった値を持たせます。自然言語の履歴から推測させる情報と、プログラムが確実に保持すべき状態を分離することで、長い処理でも行動を安定させられます。 実装時には、承認の有無だけでなく、誰が何に対して承認したのか、承認後に対象内容が変更されていないかまで確認できる形にすると安全です。さらに、実行直前にも状態を検証すれば、古い承認や別操作への誤用を防ぎやすくなり、監査時にも判断根拠を追跡できます。
1.2 完了済み作業を状態へ記録する
エージェントが一度取得した情報や完了した処理を記録しなければ、次の判断で同じツールを再度呼び出す可能性があります。検索済みのページを何度も検索したり、すでに送信した通知を再送したりすると、処理費用だけでなく外部システム側の副作用も発生します。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
完了済み作業は単なる文章メモではなく、識別子、完了時刻、入力条件、結果、再実行可否などを構造化して残す方が安全です。これにより「この作業は終わったか」という判断を言語モデルへ任せず、アプリケーション側で確実に判定できます。 実装では、この情報を誰が更新し、どの時点で確定し、いつ無効になるのかまで決めておくと、後続処理の判断が安定します。さらに状態変更の理由と関連する入力を記録しておけば、予期しない挙動が起きた際にも、会話だけを読み直さず原因を追跡できます。
1.3 次に実行する候補を状態として表現する
エージェントが計画を作る場合、計画文を長い自然言語として保存するだけでは、どこまで実行済みなのか追跡しにくくなります。特に途中で計画が変更されると、古い計画と新しい計画が会話履歴の中に同時に残り、どちらを使用すべきか曖昧になります。 モデルへ渡す情報量を増やせば判断が必ず良くなるわけではなく、不要な履歴が増えるほど重要な制約が埋もれ、費用と遅延も大きくなります。そのため、保存用状態から推論に必要な項目だけを抽出する文脈生成層を設け、必須情報、参考情報、監査用履歴を分離して扱う方が安定します。
そこで、各作業を識別子付きの項目として管理し、未着手、実行中、完了、失敗、保留などの状態を付けます。次の候補をこの構造から決めるようにすれば、モデルは「何をするか」の判断に集中でき、実行管理そのものは決定的なプログラムで扱えます。 再試行を設計するときは、回数だけでなく失敗分類、最終失敗時刻、次回実行可能時刻、同じ操作を繰り返して安全かどうかも記録すると実用的です。これにより、一時障害には自動回復を試みつつ、認証失敗や入力不備のように人間の介入が必要な問題を無限に繰り返すことを防げます。
1.4 外部ツールの結果を状態へ結び付ける
ツール実行結果は、単に会話へ追加するだけでは不十分な場合があります。例えば商品検索結果の価格、在庫確認時刻、予約番号などは、その後の処理で正確に再利用する必要があります。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
結果を構造化された状態へ保存すれば、後続処理は文章を再解析せず値を直接参照できます。また情報の取得時刻も記録しておけば、古くなった価格や在庫をそのまま利用せず、必要に応じて再取得する判断が可能になります。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
1.5 利用者との約束や制約を状態へ残す
利用者が「5000円以内」「購入前に必ず確認」「この取引先には連絡しない」と指定した場合、その条件は一つの発話だけに閉じた情報ではなく、後続作業全体へ影響します。 この種の情報はモデルへの自然言語指示だけに依存させず、アプリケーション側の検証条件として持たせることが重要です。承認記録と実行対象を識別子で結び付けておけば、再開や再試行が発生しても、許可された操作だけを確実に進められます。
制約は会話本文だけではなく、実行制約として別に保存します。特に費用上限、禁止操作、承認条件などはモデルへの指示だけに頼らず、ツール実行直前にもプログラム側で検査すると、状態と実行制御を一貫させやすくなります。 実装時には、承認の有無だけでなく、誰が何に対して承認したのか、承認後に対象内容が変更されていないかまで確認できる形にすると安全です。さらに、実行直前にも状態を検証すれば、古い承認や別操作への誤用を防ぎやすくなり、監査時にも判断根拠を追跡できます。
2. 状態へ含める情報を役割ごとに分ける
一つの巨大な辞書にすべての情報を入れると、初期段階では簡単でも、機能追加とともに依存関係が分からなくなります。会話、作業、ツール、権限、障害などを役割別に分けることで、どの情報をモデルへ見せ、どの情報をプログラム内部だけで利用するかを制御しやすくなります。 この種の情報はモデルへの自然言語指示だけに依存させず、アプリケーション側の検証条件として持たせることが重要です。承認記録と実行対象を識別子で結び付けておけば、再開や再試行が発生しても、許可された操作だけを確実に進められます。
2.1 会話状態には現在の対話に必要な情報を置く
会話状態には、直近の利用者発話、モデル応答、会話要約、現在の話題などを保持します。すべての過去発話を永久に追加し続けるのではなく、現在の対話判断に必要な情報を中心に構成します。 文脈圧縮では単にトークン数を減らすのではなく、目的、禁止条件、承認条件、未完了作業など、次の判断に必要な情報が維持されているかを評価する必要があります。入力サイズとタスク成功率を同時に測れば、過度な要約による品質低下を発見しやすくなります。
OpenAI Agents SDKのセッションは特定セッションの会話履歴を保存し、複数のエージェント実行間で文脈を維持するために利用できます。(OpenAI GitHub) ただし会話履歴と業務状態は同一ではないため、「利用者が何を話したか」と「業務処理がどこまで進んだか」を別フィールドにした方が後から追跡しやすくなります。 モデルへ渡す情報量を増やせば判断が必ず良くなるわけではなく、不要な履歴が増えるほど重要な制約が埋もれ、費用と遅延も大きくなります。そのため、保存用状態から推論に必要な項目だけを抽出する文脈生成層を設け、必須情報、参考情報、監査用履歴を分離して扱う方が安定します。
2.2 作業状態には目的と進行状況を置く
作業状態では、現在の目的、作業項目、完了済み項目、失敗項目、依存関係、期限などを管理します。利用者との雑談が増えても、作業進行状態が不必要に変化しない構造にします。 失敗を一つの例外として捨てるのではなく、次の行動を決める入力として状態へ残すと、再開処理の精度が上がります。副作用を伴う操作では冪等性や操作識別子も組み合わせ、再試行が新しい事故を生まないことまで確認する必要があります。
長時間タスクでは、会話そのものより作業状態の方が重要になる場面があります。例えば100件の資料を分析する処理では、何件まで完了したのか、失敗した資料はどれか、再試行対象はどれかを構造的に保持しなければ、途中再開が困難になります。 再試行を設計するときは、回数だけでなく失敗分類、最終失敗時刻、次回実行可能時刻、同じ操作を繰り返して安全かどうかも記録すると実用的です。これにより、一時障害には自動回復を試みつつ、認証失敗や入力不備のように人間の介入が必要な問題を無限に繰り返すことを防げます。
2.3 ツール状態には外部処理の事実を保存する
ツール状態には呼び出したツール名、入力、結果識別子、実行時刻、成功・失敗、再試行回数などを保存します。特に外部副作用を持つツールでは実行済みかどうかが重要です。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
メール送信や購入処理のような操作を、モデルの「たぶんまだ実行していない」という推測に任せるべきではありません。外部システムから得た取引識別子を状態へ保存し、それを使って重複実行を防止します。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
2.4 権限状態には何を実行してよいかを置く
エージェントが外部操作を行う場合、現在与えられている権限も状態として扱います。閲覧のみ、下書き作成まで、送信可能、一定金額以下の購入可能など、操作範囲を明示します。 実装時には、承認の有無だけでなく、誰が何に対して承認したのか、承認後に対象内容が変更されていないかまで確認できる形にすると安全です。さらに、実行直前にも状態を検証すれば、古い承認や別操作への誤用を防ぎやすくなり、監査時にも判断根拠を追跡できます。
人間承認を含む仕組みでは、承認対象、承認者、承認時刻、承認済みの具体的操作を紐付けます。OpenAI Agents SDKでは、承認が必要な実行を状態として保持し、後から承認・拒否して再開できる仕組みが提供されています。(OpenAI GitHub) この種の情報はモデルへの自然言語指示だけに依存させず、アプリケーション側の検証条件として持たせることが重要です。承認記録と実行対象を識別子で結び付けておけば、再開や再試行が発生しても、許可された操作だけを確実に進められます。
2.5 実行管理状態には技術的な情報を置く
実行番号、試行回数、開始時刻、期限、処理中ノード、エラー情報など、利用者へ直接見せる必要のない情報は実行管理領域へ分離します。 失敗を一つの例外として捨てるのではなく、次の行動を決める入力として状態へ残すと、再開処理の精度が上がります。副作用を伴う操作では冪等性や操作識別子も組み合わせ、再試行が新しい事故を生まないことまで確認する必要があります。
この情報を会話履歴へ混ぜると、モデル入力が不必要に増えるだけでなく、内部情報が利用者向け回答へ漏れる可能性があります。アプリケーション内部だけで利用する状態と、モデルへ渡す状態の境界を明確にします。 文脈圧縮では単にトークン数を減らすのではなく、目的、禁止条件、承認条件、未完了作業など、次の判断に必要な情報が維持されているかを評価する必要があります。入力サイズとタスク成功率を同時に測れば、過度な要約による品質低下を発見しやすくなります。
3. 実行中の短期状態を扱う
短期状態は、一つの作業や会話スレッドの中で必要となる情報です。長期保存する価値がない途中情報まで永続的な記憶へ入れると、後の会話で不要な情報が大量に検索されるため、寿命を意識して設計する必要があります。 長期的に残す情報には、出典、更新時刻、信頼度、失効条件を持たせると、後から内容が変わった場合にも安全に訂正できます。また、保存する価値がある情報と現在の作業だけで必要な一時情報を分けることで、将来の検索精度と状態の見通しを両立できます。
3.1 現在の実行だけで必要な値を分離する
現在の処理中にだけ必要となる一時ファイルの場所、候補一覧、途中計算結果などは、長期記憶ではなく実行状態へ置きます。作業が完了した後には削除または要約できる設計にします。 記憶は追加することよりも、何を残さないか、いつ更新・削除するかを決める方が重要です。将来の別タスクでも再利用する価値がある情報だけを選別し、現在の実行にしか意味のない値は短期状態へ残すことで、古い情報の混入を抑えられます。
OpenAI Agents SDKの局所文脈も、ツールや実行時処理から利用できるアプリケーション側の情報として扱われ、言語モデルへ自動送信される情報とは区別されています。(OpenAI GitHub) こうした分離は、内部依存情報をモデル文脈へ無制限に流し込まないためにも有効です。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
3.2 会話スレッド単位で状態を隔離する
同じ利用者が複数の作業を同時に行う場合、一つの巨大な状態へまとめると内容が混ざります。旅行計画と請求書処理を同じ会話状態で管理すれば、一方の制約がもう一方へ誤って適用される可能性があります。 一時情報には寿命を持たせ、作業完了時に削除・要約・確定状態への昇格を明示的に行うと、古い値が次の判断へ混入するのを防げます。大きなデータは状態へ直接埋め込まず参照情報だけを保持すれば、保存や転送の負荷を抑えながら必要時には原データへ戻れます。
短期状態はスレッドや作業識別子で隔離し、利用者識別子だけを共有キーにしない方が安全です。LangGraphの短期記憶もスレッドに結び付けて管理され、長期記憶とは異なる寿命を持つ設計です。(Docs by LangChain) 長期的に残す情報には、出典、更新時刻、信頼度、失効条件を持たせると、後から内容が変わった場合にも安全に訂正できます。また、保存する価値がある情報と現在の作業だけで必要な一時情報を分けることで、将来の検索精度と状態の見通しを両立できます。
3.3 一時状態には有効期限を設定する
検索候補、在庫情報、外部APIの応答などは時間とともに古くなります。状態へ保存した瞬間から永久に正しいと扱うと、数時間後や数日後に誤った判断へ利用される可能性があります。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
値そのものだけでなく取得時刻と有効期限を持たせます。利用時に期限を超えていれば再取得することで、状態保存による高速化と情報鮮度を両立できます。 短期状態は便利ですが、残し続けると状態肥大化と鮮度低下の原因になります。取得時刻、有効期限、作業識別子を持たせ、期限切れや作業終了時に整理する規則を用意すると、長時間タスクでも状態の意味を保ちやすくなります。
3.4 大きな途中結果は参照だけ保存する
PDF全文、巨大な画像、数十MBのツール出力を状態オブジェクトへ直接入れると、チェックポイント保存や状態転送が非常に重くなります。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
大きなデータは外部保存領域へ置き、状態には識別子、場所、内容要約、検証値だけを保存します。これにより状態自体を軽く保ちながら、必要なときだけ原データを取得できます。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
3.5 作業完了時に短期状態を整理する
実行中には必要だった候補一覧や一時変数も、作業終了後には不要になります。そのまま残し続けると次の処理で古い情報を誤って参照する危険があります。 一時情報には寿命を持たせ、作業完了時に削除・要約・確定状態への昇格を明示的に行うと、古い値が次の判断へ混入するのを防げます。大きなデータは状態へ直接埋め込まず参照情報だけを保持すれば、保存や転送の負荷を抑えながら必要時には原データへ戻れます。
完了処理の中で、一時状態を削除し、必要な結果だけを確定状態へ移します。「実行中」と「確定済み」の情報を分離しておけば、再開処理でもどの情報を信用してよいか判断しやすくなります。 再開可能性を高めるには、保存された状態だけでなく、その状態がどの版のスキーマで作られ、どの外部情報を前提にしていたかも追跡できるようにします。再開時には古い外部情報を必要に応じて更新し、チェックポイントをそのまま現実世界の最新状態として扱わないことが重要です。
4. 長期記憶とエージェント状態を分けて設計する
長期記憶は複数の会話や作業をまたいで再利用する情報であり、現在実行中の状態とは寿命も更新規則も異なります。すべてを「記憶」という一つの仕組みに統合すると、古い途中情報が将来の作業へ混入しやすくなります。 記憶は追加することよりも、何を残さないか、いつ更新・削除するかを決める方が重要です。将来の別タスクでも再利用する価値がある情報だけを選別し、現在の実行にしか意味のない値は短期状態へ残すことで、古い情報の混入を抑えられます。
4.1 利用者の安定した設定だけ長期保存する
言語、出力形式、継続的な業務設定など、将来の複数セッションでも価値を持つ情報は長期記憶の候補になります。一方、一回だけ指定された検索条件や一時的な予算は作業状態へ置く方が自然です。 長期的に残す情報には、出典、更新時刻、信頼度、失効条件を持たせると、後から内容が変わった場合にも安全に訂正できます。また、保存する価値がある情報と現在の作業だけで必要な一時情報を分けることで、将来の検索精度と状態の見通しを両立できます。
LangGraphの長期記憶はスレッドを越えて情報を保持し、名前空間とキーで保存する仕組みを持ちます。(Docs by LangChain) つまり「現在の作業に必要だから覚える」と「将来の別作業でも再利用するために覚える」を明確に分ける必要があります。 記憶は追加することよりも、何を残さないか、いつ更新・削除するかを決める方が重要です。将来の別タスクでも再利用する価値がある情報だけを選別し、現在の実行にしか意味のない値は短期状態へ残すことで、古い情報の混入を抑えられます。
4.2 長期記憶へ書き込む条件を限定する
モデルが会話中に出てきた情報を何でも長期保存すると、誤解、冗談、仮定、古い情報まで永続化されます。 この考え方を本番へ持ち込むときは、モデルに推測させる情報とプログラムが確定的に管理する情報を分けることが重要です。境界を明確にするほど、再開、監査、テストが容易になり、長いタスクでも同じ条件から同じ行動を再現しやすくなります。
長期記憶へ保存する前に、重要性、将来再利用性、確信度、利用者の明示性などを確認します。必要に応じて「この情報を今後も覚えるか」という確認手順を入れ、無制限な自動保存を避けます。 長期的に残す情報には、出典、更新時刻、信頼度、失効条件を持たせると、後から内容が変わった場合にも安全に訂正できます。また、保存する価値がある情報と現在の作業だけで必要な一時情報を分けることで、将来の検索精度と状態の見通しを両立できます。
4.3 長期記憶には出典と更新時刻を持たせる
「利用者はXを好む」という情報だけ保存すると、いつ、どの会話から取得したのか分かりません。後から条件が変わったときにも古い値を使い続ける可能性があります。 実装では、この情報を誰が更新し、どの時点で確定し、いつ無効になるのかまで決めておくと、後続処理の判断が安定します。さらに状態変更の理由と関連する入力を記録しておけば、予期しない挙動が起きた際にも、会話だけを読み直さず原因を追跡できます。
記憶値、取得元、作成時刻、最終確認時刻、信頼度を保存し、更新可能な情報として扱います。特に利用者設定や業務ルールは、古い記憶を上書きする規則を明確にします。 記憶は追加することよりも、何を残さないか、いつ更新・削除するかを決める方が重要です。将来の別タスクでも再利用する価値がある情報だけを選別し、現在の実行にしか意味のない値は短期状態へ残すことで、古い情報の混入を抑えられます。
4.4 検索して使う記憶と常時状態を分ける
長期記憶をすべて毎回モデルへ渡すと入力が巨大になります。関連する記憶だけを検索して現在状態へ一時的に読み込む構成が効率的です。 長期的に残す情報には、出典、更新時刻、信頼度、失効条件を持たせると、後から内容が変わった場合にも安全に訂正できます。また、保存する価値がある情報と現在の作業だけで必要な一時情報を分けることで、将来の検索精度と状態の見通しを両立できます。
この場合、長期記憶は保管庫、現在状態は作業机のような役割になります。必要なものだけ作業机へ出し、作業終了後に必要な変更だけ保管庫へ戻す設計にすると、状態サイズを制御しやすくなります。 記憶は追加することよりも、何を残さないか、いつ更新・削除するかを決める方が重要です。将来の別タスクでも再利用する価値がある情報だけを選別し、現在の実行にしか意味のない値は短期状態へ残すことで、古い情報の混入を抑えられます。
4.5 長期記憶の削除・訂正を前提にする
一度保存した記憶を不変として扱うと、利用者の希望変更や業務ルール変更へ対応できません。
追加だけでなく訂正、失効、削除を状態設計へ含めます。特に個人情報を扱う場合、どこに何が保存されているか追跡できなければ、削除要求へ正確に対応できません。 長期的に残す情報には、出典、更新時刻、信頼度、失効条件を持たせると、後から内容が変わった場合にも安全に訂正できます。また、保存する価値がある情報と現在の作業だけで必要な一時情報を分けることで、将来の検索精度と状態の見通しを両立できます。
5. ツール実行と外部世界の状態を同期する
エージェントは内部状態だけで完結するとは限りません。カレンダー、データベース、メール、決済、ファイルなど外部世界を変更すると、内部状態と外部状態の不一致が重大な問題になります。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
5.1 ツール実行前と実行後を区別する
「送信予定」と「送信済み」は完全に異なる状態です。モデルが「メールを送ります」と文章で述べただけでは送信済みにはなりません。 この考え方を本番へ持ち込むときは、モデルに推測させる情報とプログラムが確定的に管理する情報を分けることが重要です。境界を明確にするほど、再開、監査、テストが容易になり、長いタスクでも同じ条件から同じ行動を再現しやすくなります。
操作前は予定状態、外部APIから成功応答と識別子を受け取った後にだけ完了状態へ遷移させます。この境界を明確にすることで、言語生成と実際の副作用を混同しません。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
5.2 外部識別子を必ず状態へ保存する
予約番号、メッセージ識別子、取引番号、作成ファイル識別子などは、後から操作を確認・取消・更新するために必要です。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
モデルが自然言語で「予約しました」と記憶するだけではなく、外部システムが返した識別子を構造化して保存します。再開後も同じ対象を確実に参照できます。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
5.3 重複実行を防ぐ識別子を使う
通信エラーによって「外部処理は成功したが応答だけ失われた」状態が発生すると、単純再試行で同じ購入を二回実行する可能性があります。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
実行ごとに一意な操作識別子を割り当て、外部側でも同じ識別子の二重処理を防げる設計にします。状態には「要求送信済み・結果未確認」という中間状態も必要です。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
5.4 外部状態を再確認する処理を持つ
内部状態では予約済みでも、利用者が外部アプリから直接キャンセルする可能性があります。その場合、内部情報だけを信用すると現実世界とのずれが生じます。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
重要な操作前には外部システムから最新状態を取得し、内部状態と照合します。保存状態は事実の写しであって、常に最新の現実そのものではないという前提を持つことが重要です。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
5.5 部分成功を一つの失敗へまとめない
複数ツールを連続実行する場合、三つのうち二つだけ成功することがあります。全体を単純に「失敗」と保存すると、再試行時に成功済み処理まで繰り返します。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
各操作を独立した状態として保存し、成功済みは保持、失敗分だけ再試行します。長い業務処理ではこの部分成功管理が、状態設計の重要な役割になります。 再試行を設計するときは、回数だけでなく失敗分類、最終失敗時刻、次回実行可能時刻、同じ操作を繰り返して安全かどうかも記録すると実用的です。これにより、一時障害には自動回復を試みつつ、認証失敗や入力不備のように人間の介入が必要な問題を無限に繰り返すことを防げます。
6. エージェント状態と似た仕組みの違い
エージェント開発では、文脈、記憶、セッション、チェックポイント、設定といった言葉が近い意味で使われることがあります。しかし、それぞれの寿命、利用者、保存範囲が異なります。これらをすべて「状態」として一括管理すると、モデルへ見せる必要のない内部情報まで入力へ混ざったり、短期情報を長期保存したりする原因になります。 チェックポイントは単なるバックアップではなく、安全に処理を続けるための再開契約として設計すると理解しやすくなります。保存境界、状態版、外部副作用の確認方法まで定義しておけば、プロセス停止や人間承認待ちを挟んでも同じ地点から一貫して処理を継続できます。
6.1 エージェント状態とモデル文脈の違い
エージェント状態は、アプリケーションが保持する現在の実行情報全体を指せます。一方モデル文脈は、その中から実際に言語モデルへ入力される情報です。OpenAI Agents SDKも局所文脈とモデルが見る文脈を区別しています。(OpenAI GitHub) モデルへ渡す情報量を増やせば判断が必ず良くなるわけではなく、不要な履歴が増えるほど重要な制約が埋もれ、費用と遅延も大きくなります。そのため、保存用状態から推論に必要な項目だけを抽出する文脈生成層を設け、必須情報、参考情報、監査用履歴を分離して扱う方が安定します。
| 比較項目エージェント状態モデル文脈 | ||
|---|---|---|
| 主な利用者 | アプリケーション全体 | 言語モデル |
| 内部識別子 | 保持可能 | 通常は不要 |
| 秘密情報 | 原則慎重に管理 | 原則送らない |
| サイズ制約 | 保存方式次第 | 入力上限の影響を受ける |
| 主目的 | 実行を継続する | 次の推論を行う |
すべての状態をモデル文脈へ変換する必要はありません。例えばデータベース接続、内部監視値、秘密鍵などはエージェント実行には必要でもモデルが知る必要はありません。 文脈圧縮では単にトークン数を減らすのではなく、目的、禁止条件、承認条件、未完了作業など、次の判断に必要な情報が維持されているかを評価する必要があります。入力サイズとタスク成功率を同時に測れば、過度な要約による品質低下を発見しやすくなります。
6.2 エージェント状態と記憶の違い
記憶は過去の情報を将来再利用する仕組みであり、状態は現在の実行を成立させる情報を含むより広い概念として扱えます。 記憶は追加することよりも、何を残さないか、いつ更新・削除するかを決める方が重要です。将来の別タスクでも再利用する価値がある情報だけを選別し、現在の実行にしか意味のない値は短期状態へ残すことで、古い情報の混入を抑えられます。
| 比較項目エージェント状態記憶 | ||
| 主な時間軸 | 現在の実行 | 過去から将来 |
| 作業段階 | 含む | 通常は中心ではない |
| 一時値 | 多く含む | 原則選別する |
| 保存期間 | 短期から長期まで | 中長期が中心 |
| 目的 | 現在行動の一貫性 | 過去情報の再利用 |
LangGraphも短期記憶を状態の一部として扱いつつ、セッションをまたぐ長期記憶を別の保存領域で扱っています。(Docs by LangChain) 長期的に残す情報には、出典、更新時刻、信頼度、失効条件を持たせると、後から内容が変わった場合にも安全に訂正できます。また、保存する価値がある情報と現在の作業だけで必要な一時情報を分けることで、将来の検索精度と状態の見通しを両立できます。
6.3 エージェント状態とセッションの違い
セッションは、一連の会話や実行をまとめる境界です。状態は、その境界の中や外で管理される具体的な情報です。 実装では、この情報を誰が更新し、どの時点で確定し、いつ無効になるのかまで決めておくと、後続処理の判断が安定します。さらに状態変更の理由と関連する入力を記録しておけば、予期しない挙動が起きた際にも、会話だけを読み直さず原因を追跡できます。
| 比較項目エージェント状態セッション | ||
| 役割 | 実データを保持 | 会話・実行範囲を識別 |
| 会話履歴 | 一部として含められる | 主に保持対象 |
| 作業状態 | 含められる | 実装次第 |
| 複数セッション共有 | 一部可能 | 通常は分離 |
| 主キー | 作業・実行など複数 | セッション識別子 |
OpenAI Agents SDKのセッションは会話履歴を自動管理する永続記憶層です。(OpenAI GitHub) そのためセッションを利用していても、業務タスクの進行状態まで自動的に正しく設計されるわけではありません。 記憶は追加することよりも、何を残さないか、いつ更新・削除するかを決める方が重要です。将来の別タスクでも再利用する価値がある情報だけを選別し、現在の実行にしか意味のない値は短期状態へ残すことで、古い情報の混入を抑えられます。
6.4 エージェント状態とチェックポイントの違い
状態は現在の情報そのもので、チェックポイントはある時点の状態を再開可能な形で保存したものです。 再開可能性を高めるには、保存された状態だけでなく、その状態がどの版のスキーマで作られ、どの外部情報を前提にしていたかも追跡できるようにします。再開時には古い外部情報を必要に応じて更新し、チェックポイントをそのまま現実世界の最新状態として扱わないことが重要です。
| 比較項目エージェント状態チェックポイント | ||
| 意味 | 現在値 | 時点保存 |
| 更新 | 継続的 | 特定時点ごと |
| 再開 | 単独では保証しない | 主目的の一つ |
| 履歴 | 最新値中心 | 複数世代を保持可能 |
| 障害復旧 | 材料になる | 直接利用しやすい |
LangGraphではチェックポインターを使用するとグラフ状態を保存し、後から復元できるようになります。(LangChain AI) 状態とその保存履歴を分けて考えることが重要です。 チェックポイントは単なるバックアップではなく、安全に処理を続けるための再開契約として設計すると理解しやすくなります。保存境界、状態版、外部副作用の確認方法まで定義しておけば、プロセス停止や人間承認待ちを挟んでも同じ地点から一貫して処理を継続できます。
6.5 エージェント状態と実行設定の違い
実行設定は「どのモデルを使うか」「最大試行回数はいくつか」といった処理規則であり、状態は実際に処理した結果です。 この考え方を本番へ持ち込むときは、モデルに推測させる情報とプログラムが確定的に管理する情報を分けることが重要です。境界を明確にするほど、再開、監査、テストが容易になり、長いタスクでも同じ条件から同じ行動を再現しやすくなります。
| 比較項目エージェント状態実行設定 | ||
| 変化 | 実行中に頻繁に変化 | 比較的固定 |
| 例 | 現在作業、結果、承認 | モデル名、上限、方針 |
| 保存目的 | 再開・継続 | 再現性 |
| モデルへ提示 | 必要部分のみ | 必要項目のみ |
| 版管理 | 状態版 | 設定版 |
実行設定まで状態の一部として自由に書き換えられるようにすると、途中でルールが変わり再現性が失われます。設定と実行結果は別に版管理します。 実装では、この情報を誰が更新し、どの時点で確定し、いつ無効になるのかまで決めておくと、後続処理の判断が安定します。さらに状態変更の理由と関連する入力を記録しておけば、予期しない挙動が起きた際にも、会話だけを読み直さず原因を追跡できます。
7. 状態遷移でエージェントの行動を制御する
複雑なエージェントでは、「次に何をするか」を毎回自由生成させるより、許可された状態遷移を定義した方が安全です。モデルは遷移候補を提案できますが、実際に遷移可能かどうかをプログラムが検査します。 実装時には、承認の有無だけでなく、誰が何に対して承認したのか、承認後に対象内容が変更されていないかまで確認できる形にすると安全です。さらに、実行直前にも状態を検証すれば、古い承認や別操作への誤用を防ぎやすくなり、監査時にも判断根拠を追跡できます。
7.1 状態値を有限な候補として定義する
"何となく調査中"のような自由文章だけでは、条件分岐が難しくなります。調査待ち、調査中、確認待ち、実行可能、完了、失敗など明確な値を用意します。
これによりログ検索、監視、再開処理も簡単になります。状態数を増やしすぎる必要はありませんが、業務上意味が異なる段階は明示的に分けます。 再開可能性を高めるには、保存された状態だけでなく、その状態がどの版のスキーマで作られ、どの外部情報を前提にしていたかも追跡できるようにします。再開時には古い外部情報を必要に応じて更新し、チェックポイントをそのまま現実世界の最新状態として扱わないことが重要です。
7.2 許可されない遷移を防ぐ
未承認状態から決済完了へ直接移れる設計では、安全性をモデル判断だけに任せることになります。 この種の情報はモデルへの自然言語指示だけに依存させず、アプリケーション側の検証条件として持たせることが重要です。承認記録と実行対象を識別子で結び付けておけば、再開や再試行が発生しても、許可された操作だけを確実に進められます。
例えば「候補取得済み → 承認待ち → 承認済み → 実行中 → 完了」という順序を定義し、承認待ちから実行中へ進むには承認記録が必要という条件をコードで検査します。 実装時には、承認の有無だけでなく、誰が何に対して承認したのか、承認後に対象内容が変更されていないかまで確認できる形にすると安全です。さらに、実行直前にも状態を検証すれば、古い承認や別操作への誤用を防ぎやすくなり、監査時にも判断根拠を追跡できます。
7.3 状態遷移に理由を付ける
状態が「調査中」から「人間確認待ち」へ変わったとき、理由が残っていなければ後から調査できません。 この考え方を本番へ持ち込むときは、モデルに推測させる情報とプログラムが確定的に管理する情報を分けることが重要です。境界を明確にするほど、再開、監査、テストが容易になり、長いタスクでも同じ条件から同じ行動を再現しやすくなります。
遷移元、遷移先、時刻、実行者、理由、関連ツール結果を記録します。監査が必要なシステムでは、現在状態だけではなく遷移履歴が重要になります。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
7.4 失敗状態を一種類にまとめない
通信失敗、認証失敗、入力不備、利用者拒否、内部例外では、次に取るべき行動が異なります。
再試行可能な失敗、修正要求が必要な失敗、即時停止すべき失敗などに分類します。状態遷移がこの分類を利用すれば、無意味な自動再試行を防げます。 失敗を一つの例外として捨てるのではなく、次の行動を決める入力として状態へ残すと、再開処理の精度が上がります。副作用を伴う操作では冪等性や操作識別子も組み合わせ、再試行が新しい事故を生まないことまで確認する必要があります。
7.5 完了状態を明確に定義する
モデルが回答文を生成しただけでタスク完了とは限りません。必要なファイル保存、外部更新、結果確認まで終わって初めて完了となる場合があります。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
「何が満たされれば完了か」を状態遷移条件として定義します。これによりエージェントが途中結果を完成扱いする問題を減らせます。 状態遷移は自由な文章の更新ではなく、許可された遷移と成立条件を明示した小さな状態機械として扱うと安全です。遷移元、遷移先、理由、時刻、関連するツール結果を記録しておけば、異常な飛び越しやループを検出でき、障害時の再現にも役立ちます。
8. 状態を永続化して停止後も正しく再開する
長時間タスクでは、プロセス停止、サーバー再起動、人間承認待ちなどによって実行が中断されます。すべてを最初からやり直すのではなく、安全に状態を保存し、同じ地点から再開できる設計が重要です。 この種の情報はモデルへの自然言語指示だけに依存させず、アプリケーション側の検証条件として持たせることが重要です。承認記録と実行対象を識別子で結び付けておけば、再開や再試行が発生しても、許可された操作だけを確実に進められます。
8.1 意味のある境界でチェックポイントを保存する
モデル呼び出し前、ツール実行後、人間承認待ちへ入る直前など、再開しやすい地点で状態を保存します。 実装時には、承認の有無だけでなく、誰が何に対して承認したのか、承認後に対象内容が変更されていないかまで確認できる形にすると安全です。さらに、実行直前にも状態を検証すれば、古い承認や別操作への誤用を防ぎやすくなり、監査時にも判断根拠を追跡できます。
LangGraphの永続化機構では、グラフの各段階で状態をチェックポイントとして保存できます。(Docs by LangChain) ただし非常に大きな状態を毎段階フル保存すると容量が増えるため、保存方式も考慮する必要があります。 チェックポイントは単なるバックアップではなく、安全に処理を続けるための再開契約として設計すると理解しやすくなります。保存境界、状態版、外部副作用の確認方法まで定義しておけば、プロセス停止や人間承認待ちを挟んでも同じ地点から一貫して処理を継続できます。
8.2 再開時に外部状態を再確認する
一日前に「在庫あり」で停止し、翌日に再開した場合、その情報をそのまま使うべきではありません。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
チェックポイントは当時の内部状態を復元するためのもので、外部世界が停止していたわけではありません。再開時に鮮度が重要な外部情報を再取得します。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
8.3 状態形式へ版番号を付ける
アプリケーション更新によって状態フィールドが増減すると、古いチェックポイントを新コードで読み込めなくなる可能性があります。 再開可能性を高めるには、保存された状態だけでなく、その状態がどの版のスキーマで作られ、どの外部情報を前提にしていたかも追跡できるようにします。再開時には古い外部情報を必要に応じて更新し、チェックポイントをそのまま現実世界の最新状態として扱わないことが重要です。
状態に版番号を付け、旧版から新版へ変換する移行処理を用意します。長期実行エージェントほど、この状態形式の互換性が重要になります。 状態項目は単なるキーと値の集合ではなく、各フィールドの意味、型、更新主体、寿命、必須条件まで含む契約として設計すると保守しやすくなります。版番号と移行規則も用意しておけば、アプリケーション更新後でも古い状態を読み込み、段階的に新しい形式へ変換できます。
8.4 保存失敗と処理成功の順序を考える
外部操作が成功した直後、状態保存前にサーバーが停止すると、再開後には「まだ実行していない」と見える可能性があります。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
副作用を持つ操作では、外部操作識別子や重複防止キーを利用し、再開時に実行済みか確認できるようにします。単純なメモリ保存だけでは完全な一貫性を保証できません。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
8.5 再開用状態へ秘密情報を無制限に入れない
停止・再開のために状態を直列化すると、その中身がデータベースやログへ長期間保存される場合があります。 チェックポイントは単なるバックアップではなく、安全に処理を続けるための再開契約として設計すると理解しやすくなります。保存境界、状態版、外部副作用の確認方法まで定義しておけば、プロセス停止や人間承認待ちを挟んでも同じ地点から一貫して処理を継続できます。
OpenAI Agents SDKの実行状態も、アプリケーション文脈を含む直列化可能な情報を保持するため、秘密情報を意図せず状態へ入れないよう注意が示されています。(OpenAI GitHub) 保存される可能性があるものとして状態を設計します。 再開可能性を高めるには、保存された状態だけでなく、その状態がどの版のスキーマで作られ、どの外部情報を前提にしていたかも追跡できるようにします。再開時には古い外部情報を必要に応じて更新し、チェックポイントをそのまま現実世界の最新状態として扱わないことが重要です。
9. 複数エージェントで状態を安全に共有する
複数エージェントが同じ仕事へ参加すると、状態共有がさらに難しくなります。全員が同じ状態を自由に書き換えると競合が起き、逆に完全分離すると連携できません。共有範囲と所有権を定義する必要があります。 複数の実行主体が同じ情報を扱う場合は、共有すること自体よりも、誰が書き換えられるかと、どの版を読んで処理したかを明確にすることが重要です。所有権と更新番号を持たせれば、並列処理の結果が互いを上書きする問題を検出し、必要な場合だけ再評価できます。
9.1 各エージェントの私有状態を分離する
調査担当の検索候補や文章担当の下書きなど、他エージェントが直接変更する必要のない情報は私有状態へ置きます。 実装では、この情報を誰が更新し、どの時点で確定し、いつ無効になるのかまで決めておくと、後続処理の判断が安定します。さらに状態変更の理由と関連する入力を記録しておけば、予期しない挙動が起きた際にも、会話だけを読み直さず原因を追跡できます。
共有状態を最小限にすると競合が減り、どのエージェントがどの情報を管理するか明確になります。 共有状態を最小限にし、私有状態、イベント通知、確定済み共有結果を分けると、競合の範囲を小さくできます。さらに入力版と結果版を紐付ければ、古いデータを使った分析結果を最新状態へ誤って統合する事故も防ぎやすくなります。
9.2 共有状態には所有者を設定する
例えば全体計画は統括エージェントだけ更新でき、専門エージェントは作業結果だけ追加できる設計にします。 この考え方を本番へ持ち込むときは、モデルに推測させる情報とプログラムが確定的に管理する情報を分けることが重要です。境界を明確にするほど、再開、監査、テストが容易になり、長いタスクでも同じ条件から同じ行動を再現しやすくなります。
全員が計画そのものを自由に変更すると、同じ瞬間に異なる方向へ書き換えられる可能性があります。 実装では、この情報を誰が更新し、どの時点で確定し、いつ無効になるのかまで決めておくと、後続処理の判断が安定します。さらに状態変更の理由と関連する入力を記録しておけば、予期しない挙動が起きた際にも、会話だけを読み直さず原因を追跡できます。
9.3 書き込み競合を検出する
二つのエージェントが同じ状態を読み、その後それぞれ変更すると、後から保存した方が前の変更を消す可能性があります。 この考え方を本番へ持ち込むときは、モデルに推測させる情報とプログラムが確定的に管理する情報を分けることが重要です。境界を明確にするほど、再開、監査、テストが容易になり、長いタスクでも同じ条件から同じ行動を再現しやすくなります。
状態版番号や更新番号を利用し、読み込み後に別の更新があれば保存を拒否します。競合時には最新状態を再読込して処理を再評価します。 複数の実行主体が同じ情報を扱う場合は、共有すること自体よりも、誰が書き換えられるかと、どの版を読んで処理したかを明確にすることが重要です。所有権と更新番号を持たせれば、並列処理の結果が互いを上書きする問題を検出し、必要な場合だけ再評価できます。
9.4 メッセージ受け渡しと共有状態を使い分ける
一時的な通知まで共有状態へ永続保存すると、状態が巨大になります。
「分析完了」というイベントはメッセージとして送り、最終分析結果だけ共有状態へ保存するなど、通知と事実保存を分けます。 共有状態を最小限にし、私有状態、イベント通知、確定済み共有結果を分けると、競合の範囲を小さくできます。さらに入力版と結果版を紐付ければ、古いデータを使った分析結果を最新状態へ誤って統合する事故も防ぎやすくなります。
9.5 統合前に結果の版を確認する
複数エージェントが並列分析している間に元データが更新される可能性があります。
各結果に参照した入力版を付け、異なる版の結果を誤って統合しないようにします。
10. 状態サイズを制御してモデル文脈を肥大化させない
エージェントが長く動くほど状態は増えます。しかし増えた状態をすべてモデルへ入力すると、費用、遅延、情報探索難度が増大します。保存状態と推論用文脈を分け、必要な情報だけを選択する必要があります。 モデルへ渡す情報量を増やせば判断が必ず良くなるわけではなく、不要な履歴が増えるほど重要な制約が埋もれ、費用と遅延も大きくなります。そのため、保存用状態から推論に必要な項目だけを抽出する文脈生成層を設け、必須情報、参考情報、監査用履歴を分離して扱う方が安定します。
10.1 全会話履歴を毎回送らない
数百ターンの会話をすべて毎回モデルへ渡す方法は単純ですが、入力が増え続けます。
古い部分を要約し、最近の重要発話だけ原文で残す方法が有効です。ただし要約によって重要な制約が失われないよう、業務制約は構造化状態として別に保持します。 文脈圧縮では単にトークン数を減らすのではなく、目的、禁止条件、承認条件、未完了作業など、次の判断に必要な情報が維持されているかを評価する必要があります。入力サイズとタスク成功率を同時に測れば、過度な要約による品質低下を発見しやすくなります。
10.2 状態を重要度で分類する
現在の作業に必須、参考情報、履歴のみというように重要度を付けます。
推論時には必須情報を常に入れ、参考情報は必要時だけ検索し、履歴は監査用として保存するだけにします。 実装では、この情報を誰が更新し、どの時点で確定し、いつ無効になるのかまで決めておくと、後続処理の判断が安定します。さらに状態変更の理由と関連する入力を記録しておけば、予期しない挙動が起きた際にも、会話だけを読み直さず原因を追跡できます。
10.3 大きなツール結果を要約する
検索結果100件をそのまま次の推論へ渡すより、必要項目だけ抽出した構造を作ります。
原文は外部保存し、状態には要約と参照先を保持すれば、後から詳細確認も可能です。
10.4 文脈作成を独立した処理にする
状態保存処理とモデル入力作成を同じにすると、「保存したものはすべて送る」という構造になりやすくなります。 この考え方を本番へ持ち込むときは、モデルに推測させる情報とプログラムが確定的に管理する情報を分けることが重要です。境界を明確にするほど、再開、監査、テストが容易になり、長いタスクでも同じ条件から同じ行動を再現しやすくなります。
現在状態から必要情報を選び、モデル用の文脈を生成する専用処理を設けます。これによりモデル変更や入力上限変更にも対応しやすくなります。 モデルへ渡す情報量を増やせば判断が必ず良くなるわけではなく、不要な履歴が増えるほど重要な制約が埋もれ、費用と遅延も大きくなります。そのため、保存用状態から推論に必要な項目だけを抽出する文脈生成層を設け、必須情報、参考情報、監査用履歴を分離して扱う方が安定します。
10.5 圧縮による情報損失を評価する
要約を短くすれば費用は減りますが、重要な情報まで消える可能性があります。
圧縮前後でエージェントのタスク成功率を比較し、単に入力トークン数だけを最適化しないようにします。 文脈圧縮では単にトークン数を減らすのではなく、目的、禁止条件、承認条件、未完了作業など、次の判断に必要な情報が維持されているかを評価する必要があります。入力サイズとタスク成功率を同時に測れば、過度な要約による品質低下を発見しやすくなります。
11. 障害復旧と再試行を状態設計へ組み込む
エージェントは外部API、モデル、ネットワークなど多数の不安定要素に依存します。失敗を例外処理だけで扱うのではなく、状態の一部として設計すると、再開や監視が容易になります。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
11.1 再試行回数を状態へ保存する
プロセス再起動のたびに再試行回数がゼロへ戻ると、永久に同じ失敗を繰り返す可能性があります。 再試行を設計するときは、回数だけでなく失敗分類、最終失敗時刻、次回実行可能時刻、同じ操作を繰り返して安全かどうかも記録すると実用的です。これにより、一時障害には自動回復を試みつつ、認証失敗や入力不備のように人間の介入が必要な問題を無限に繰り返すことを防げます。
試行回数、最後の失敗時刻、次回試行可能時刻を保存します。
11.2 再試行可能な失敗だけ再実行する
通信一時障害は再試行してよい一方、認証拒否や利用者入力不備を何度繰り返しても成功しません。 失敗を一つの例外として捨てるのではなく、次の行動を決める入力として状態へ残すと、再開処理の精度が上がります。副作用を伴う操作では冪等性や操作識別子も組み合わせ、再試行が新しい事故を生まないことまで確認する必要があります。
失敗分類を状態へ保存し、種類ごとに次の遷移を決めます。
11.3 副作用を持つ操作は冪等にする
同じ実行要求を二回送っても結果が重複しない設計を可能な範囲で採用します。
状態側には操作識別子を保存し、外部側と照合します。
11.4 失敗途中の状態を破棄しない
エラー発生時に状態を全部初期化すると、どこまで成功していたか分からなくなります。
エラー時点の状態を保存し、調査や部分再開に利用します。
11.5 人間へ引き継ぐための状態を作る
自動復旧できない場合、人間が何が起きたか理解できる必要があります。
現在目的、完了項目、失敗箇所、直近ツール結果、推奨次操作を簡潔にまとめた引継ぎ状態を生成します。 特に外部APIやツールが副作用を持つ場合は、成功したかどうかを文章で推測せず、返却された識別子や応答状態を使って確定させます。こうして内部状態と外部状態の対応関係を残しておけば、障害復旧時にも重複実行や誤更新を避けやすくなります。
12. 状態へ含まれる機密情報と権限を守る
エージェント状態には利用者情報、外部API結果、承認記録、内部識別子などが集まりやすいため、単なるアプリケーション変数として軽く扱うべきではありません。保存、転送、ログ出力のすべてで機密性を考える必要があります。 この種の情報はモデルへの自然言語指示だけに依存させず、アプリケーション側の検証条件として持たせることが重要です。承認記録と実行対象を識別子で結び付けておけば、再開や再試行が発生しても、許可された操作だけを確実に進められます。
12.1 秘密情報を状態へ直接保存しない
API鍵やパスワードそのものを状態へ入れると、チェックポイントやログへ複製される可能性があります。 実運用では、値そのものに加えて取得元、取得時刻、外部識別子、再確認の要否を一緒に保持すると、後続処理の信頼性が上がります。外部世界はエージェントの停止中にも変化するため、保存済み状態を絶対的な事実ではなく、特定時点の観測結果として扱うことが重要です。
秘密管理基盤の参照識別子だけを状態に持ち、実行時に必要な処理が安全な経路から取得します。
12.2 モデルへ渡す状態を明示的に選ぶ
内部状態に利用者識別子や権限情報があっても、それらすべてをモデルへ入力する必要はありません。 実装時には、承認の有無だけでなく、誰が何に対して承認したのか、承認後に対象内容が変更されていないかまで確認できる形にすると安全です。さらに、実行直前にも状態を検証すれば、古い承認や別操作への誤用を防ぎやすくなり、監査時にも判断根拠を追跡できます。
モデルが必要とする情報だけ変換し、内部情報が生成回答へ漏れないようにします。
12.3 保存状態を利用者単位で隔離する
識別子指定ミスによって別利用者の状態を読み込む事故は重大です。
データベース段階で利用者または組織境界を強制し、モデルの判断にアクセス制御を任せません。
12.4 状態変更にも権限を設定する
状態を読む権限と書く権限を分けます。監視エージェントは閲覧のみ、実行エージェントは特定項目だけ更新可能という設計ができます。 この種の情報はモデルへの自然言語指示だけに依存させず、アプリケーション側の検証条件として持たせることが重要です。承認記録と実行対象を識別子で結び付けておけば、再開や再試行が発生しても、許可された操作だけを確実に進められます。
複数エージェント構成では特に有効です。
12.5 保存期間を情報種類ごとに決める
全状態を永久保存する必要はありません。
一時検索結果は短期間、監査記録は必要期間、利用者設定は削除要求までというように寿命を分けます。 長期的に残す情報には、出典、更新時刻、信頼度、失効条件を持たせると、後から内容が変わった場合にも安全に訂正できます。また、保存する価値がある情報と現在の作業だけで必要な一時情報を分けることで、将来の検索精度と状態の見通しを両立できます。
13. 状態を観測してエージェントの挙動を評価する
エージェントの最終回答だけを評価すると、なぜ成功・失敗したか分かりません。状態遷移、ツール呼び出し、再試行、承認待ちなどを観測することで、内部行動の品質を分析できます。 実装時には、承認の有無だけでなく、誰が何に対して承認したのか、承認後に対象内容が変更されていないかまで確認できる形にすると安全です。さらに、実行直前にも状態を検証すれば、古い承認や別操作への誤用を防ぎやすくなり、監査時にも判断根拠を追跡できます。
13.1 状態遷移履歴を保存する
「開始 → 調査 → 比較 → 承認 → 実行 → 完了」のような履歴を残します。
不自然な往復や長時間停滞を発見できます。
13.2 ツール利用を状態と結び付けて記録する
ツール名だけでなく、その時点の目的や状態を一緒に記録します。
同じツールが繰り返されている場合、モデル判断の問題か状態更新漏れかを切り分けられます。
13.3 トークン使用量と状態サイズを追跡する
OpenAI Agents SDKでは各実行の利用量を実行文脈から確認できます。(OpenAI GitHub) 状態サイズと入力トークン数を時系列で追えば、会話が長くなるにつれて費用が異常増加していないか確認できます。 モデルへ渡す情報量を増やせば判断が必ず良くなるわけではなく、不要な履歴が増えるほど重要な制約が埋もれ、費用と遅延も大きくなります。そのため、保存用状態から推論に必要な項目だけを抽出する文脈生成層を設け、必須情報、参考情報、監査用履歴を分離して扱う方が安定します。
状態圧縮の改善効果も、タスク成功率と入力量の両方で測定します。
13.4 再開成功率を独立した指標にする
長時間エージェントでは、通常完走率だけでなく停止後に正しい地点から再開できるかが重要です。 チェックポイントは単なるバックアップではなく、安全に処理を続けるための再開契約として設計すると理解しやすくなります。保存境界、状態版、外部副作用の確認方法まで定義しておけば、プロセス停止や人間承認待ちを挟んでも同じ地点から一貫して処理を継続できます。
意図的に複数地点で停止し、再開後の重複実行、状態欠損、最終結果を評価します。
13.5 状態不整合を自動検出する
「完了なのに未処理項目が残っている」「承認なしなのに実行済み」など、成立してはいけない組み合わせを規則として定義します。 この種の情報はモデルへの自然言語指示だけに依存させず、アプリケーション側の検証条件として持たせることが重要です。承認記録と実行対象を識別子で結び付けておけば、再開や再試行が発生しても、許可された操作だけを確実に進められます。
実行後に自動検査すれば、モデル出力が自然でも内部状態が壊れているケースを検出できます。
14. Pythonでエージェント状態を実装する
状態実装では、自由な辞書を使うこともできますが、本番では型、版、更新規則を持たせた方が安全です。以下では特定のエージェント基盤に依存しない形で、状態構造、遷移、チェックポイント、競合制御、文脈作成を実装します。 再開可能性を高めるには、保存された状態だけでなく、その状態がどの版のスキーマで作られ、どの外部情報を前提にしていたかも追跡できるようにします。再開時には古い外部情報を必要に応じて更新し、チェックポイントをそのまま現実世界の最新状態として扱わないことが重要です。
14.1 型付き状態を定義する
状態項目を明示すると、存在しないキーや異なる型が混ざる問題を早期に検出できます。
作業段階、完了項目、ツール結果などを構造として定義します。
Python実装例
from dataclasses import dataclass, fieldfrom typing import Any
@dataclassclass エージェント状態: 状態版: int = 1 実行識別子: str = "" 現在段階: str = "開始" 目的: str = "" 完了項目: list[str] = field(default_factory=list) 保留項目: list[str] = field(default_factory=list) ツール結果: dict[str, Any] = field(default_factory=dict) 承認済み操作: set[str] = field(default_factory=set) 再試行回数: dict[str, int] = field(default_factory=dict)
型定義は状態の意味を自動的に保証するものではありませんが、構造崩壊を防ぐ第一段階になります。 構造を明示すると、存在しない値や矛盾した値を早い段階で検出できるだけでなく、監視やテストの条件も作りやすくなります。特に長時間実行では、状態スキーマをAPIと同じように版管理することが、再現性と後方互換性を守る基盤になります。
14.2 許可された状態遷移だけ実行する
段階変更をどこからでも直接書き換えるのではなく、専用関数を通します。
Python実装例
許可遷移 = { "開始": {"調査中"}, "調査中": {"比較中", "失敗"}, "比較中": {"承認待ち", "完了", "失敗"}, "承認待ち": {"実行中", "取消"}, "実行中": {"完了", "失敗"}, "失敗": {"調査中", "停止"},}
def 状態を遷移する(状態, 次段階): 現在 = 状態.現在段階
if 次段階 not in 許可遷移.get(現在, set()): raise ValueError( f"許可されない状態遷移です: {現在} -> {次段階}" )
状態.現在段階 = 次段階
承認のような追加条件が必要な遷移では、この関数内で状態を検査します。
14.3 チェックポイントを保存する
状態を直列化し、実行識別子と世代番号で保存します。実環境ではデータベースなどへ置き換えます。 チェックポイントは単なるバックアップではなく、安全に処理を続けるための再開契約として設計すると理解しやすくなります。保存境界、状態版、外部副作用の確認方法まで定義しておけば、プロセス停止や人間承認待ちを挟んでも同じ地点から一貫して処理を継続できます。
Python実装例
import jsonfrom dataclasses import asdictfrom pathlib import Path
def チェックポイント保存(状態, 世代): 保存先 = Path( f"checkpoints/{状態.実行識別子}/{世代}.json" ) 保存先.parent.mkdir( parents=True, exist_ok=True, )
内容 = asdict(状態)
# set は JSON に直接保存できないため変換 内容["承認済み操作"] = list( 内容["承認済み操作"] )
保存先.write_text( json.dumps( 内容, ensure_ascii=False, indent=2, ), encoding="utf-8", )
return 保存先
保存前には秘密情報が混入していないか検査する層を追加すると安全です。
14.4 状態版による競合を検出する
複数処理が同じ状態を更新する場合、読み込んだ時点の更新番号を確認します。
Python実装例
class 状態競合(Exception): pass
def 状態を更新する( 保存済み状態, 更新予定状態, 読み込み時更新番号,): if ( 保存済み状態["更新番号"] != 読み込み時更新番号 ): raise 状態競合( "読み込み後に別の更新が行われています" )
更新予定状態["更新番号"] = ( 読み込み時更新番号 + 1 )
return 更新予定状態
競合した場合には上書きせず、最新状態を再取得して処理をやり直します。
14.5 モデルへ渡す文脈を状態から選択する
保存状態全体をそのままモデルへ渡すのではなく、推論に必要な部分だけ構築します。
Python実装例
def モデル文脈を作る(状態): return { "目的": 状態.目的, "現在段階": 状態.現在段階, "完了項目": 状態.完了項目[-10:], "保留項目": 状態.保留項目, "利用可能なツール結果": { 名前: 結果 for 名前, 結果 in 状態.ツール結果.items() if 結果.get("モデル提示可能", False) }, }
この分離によって、内部状態の保存方式とモデル入力方式を独立して改善できます。
15. 本番環境でエージェント状態を運用する
本番のエージェント状態管理では、「保存できる」だけでは不十分です。状態が壊れないこと、再開できること、他利用者と混ざらないこと、古い版から移行できること、費用が増え続けないことまで含めて運用する必要があります。 再開可能性を高めるには、保存された状態だけでなく、その状態がどの版のスキーマで作られ、どの外部情報を前提にしていたかも追跡できるようにします。再開時には古い外部情報を必要に応じて更新し、チェックポイントをそのまま現実世界の最新状態として扱わないことが重要です。
15.1 状態の所有権を最初に決める
どのサービスが状態の正本なのかを決めます。会話履歴を複数の仕組みで同時管理すると、二重履歴や不整合が起きやすくなります。 文脈圧縮では単にトークン数を減らすのではなく、目的、禁止条件、承認条件、未完了作業など、次の判断に必要な情報が維持されているかを評価する必要があります。入力サイズとタスク成功率を同時に測れば、過度な要約による品質低下を発見しやすくなります。
OpenAI Agents SDKの資料でも、クライアント側で管理する履歴とOpenAI側の管理状態を無計画に混ぜると文脈が重複する可能性があるため、会話ごとに一つの永続化方式を選ぶことが推奨されています。(OpenAI GitHub) モデルへ渡す情報量を増やせば判断が必ず良くなるわけではなく、不要な履歴が増えるほど重要な制約が埋もれ、費用と遅延も大きくなります。そのため、保存用状態から推論に必要な項目だけを抽出する文脈生成層を設け、必須情報、参考情報、監査用履歴を分離して扱う方が安定します。
15.2 状態形式をアプリケーション契約として管理する
状態スキーマを内部実装の細部として扱うと、機能追加のたびに互換性が壊れます。
版番号、必須項目、削除予定項目、移行規則を明文化し、API契約と同じように管理します。
15.3 状態保存の障害を監視する
モデル推論が成功しても、状態保存に失敗すれば次回実行で情報が失われます。
保存成功率、保存時間、競合回数、復元失敗率を監視対象にします。
15.4 定期的に長時間実行試験を行う
短い会話だけでは、状態肥大化、再開問題、古い記憶混入などを発見できません。
数十・数百段階の実行、サーバー停止、人間承認待ち、ツール失敗を含む試験を行います。
15.5 状態品質を公開判定へ組み込む
最終回答品質が高くても、再開すると二重送信するエージェントを本番へ出すべきではありません。 チェックポイントは単なるバックアップではなく、安全に処理を続けるための再開契約として設計すると理解しやすくなります。保存境界、状態版、外部副作用の確認方法まで定義しておけば、プロセス停止や人間承認待ちを挟んでも同じ地点から一貫して処理を継続できます。
公開判定例
def 公開判定(評価): 条件 = { "タスク完了率": 評価["タスク完了率"] >= 0.95,
"再開成功率": 評価["再開成功率"] >= 0.99,
"重複副作用率": 評価["重複副作用率"] == 0,
"状態不整合率": 評価["状態不整合率"] <= 0.001,
"他利用者状態混入": 評価["他利用者状態混入件数"] == 0, }
不合格 = [ 名称 for 名称, 合格 in 条件.items() if not 合格 ]
return { "公開可能": len(不合格) == 0, "不合格項目": 不合格, }
モデル評価だけでなく状態管理の品質を公開条件へ追加することで、実際に長時間動かせるエージェントかどうかを判断できます。 評価では最終回答だけを見るのではなく、状態遷移、待機時間、再試行回数、重複操作、復元成功率などを時系列で追跡すると原因分析が容易になります。正常時の値だけでなく、障害注入や意図的な停止を含む試験を行うことで、本番でしか現れにくい状態不整合も事前に検出できます。
おわりに
エージェント状態は、単純な会話履歴や「AIが覚えている情報」と同じものではありません。現在の目的、作業段階、完了済み項目、ツール結果、外部識別子、人間承認、権限、再試行、障害情報、チェックポイントなどを含み、自律型AIが複数の時間・複数の処理をまたいで一貫した行動を続けるための中心的な実行情報です。状態を適切に分離しなければ、モデルが高性能でも重複実行、古い情報利用、承認漏れ、再開失敗といった問題が起こります。
重要なのは、保存状態、モデル文脈、短期記憶、長期記憶、セッション、チェックポイントを同一視しないことです。現在の主要なエージェント基盤でも、実行時の局所文脈、セッション記憶、状態チェックポイント、長期記憶はそれぞれ異なる役割として扱われています。(OpenAI GitHub) 状態全体をモデルへ見せるのではなく、保存すべき情報と推論に必要な情報を分けることで、安全性、費用、再現性を改善できます。
最終的に優れたエージェント状態設計とは、「前の会話を覚えているエージェント」を作ることではありません。処理がどこで停止しても正しい地点から再開でき、同じ副作用を二度起こさず、複数エージェントが競合せず、人間承認を正しく引き継ぎ、古い情報を適切に失効させ、必要な情報だけをモデルへ渡せる状態を作ることです。状態管理をモデルの付属機能ではなく、エージェント全体の実行基盤として設計することで、短いデモから長時間安定して動作する自律型AIシステムへ発展させることができます。
EN
JP
KR