レッスン3: 停止条件: エージェントはいつ手を引くべきか
学習目標:
- モデルが自分で
end_turn を返すのに任せるだけではループを終わらせるのに足りない理由を説明し、その緊張をはっきり言う: モデルを信頼しなければならないが、そのモデルは多数のターンにわたって動き続けうる
- 骨組みのループに最大ターン数のハードなゲートを足し、そのカウンタがループの外にあるときだけ機能する理由を説明する
- ハードストップ(上限での強制停止)とソフトストップ / サスペンド(人間を待つ、再開可能)を区別し、あるエージェントが止まらなければならない条件を列挙する
前提: レッスン2を読み、stop_reason が駆動する while ループを書けて、end_turn が返ってきたときにループが自然に終わることを知っていること | 前: レッスン2 << | 次: レッスン4 >>
モデルが自分で切り上げるのを当てにしない
レッスン2の骨組みのループが止まる理由はただ1つです: あるラウンドでモデルがツールを要求しなくなり、stop_reason が tool_use から end_turn に変わり、while 条件が偽になって、ループが自然に終わる1。言い換えれば、もう1回転するかどうかの判断は、完全にモデルに委ねられています——モデルが「言うことは言った」と告げたときにループが止まるわけです。
たいていの場合それでうまくいきますが、誰が判断しているのかははっきりさせておきましょう。エージェントとは定義上、モデルが自身のプロセスと自身のツールの使い方を動的に指揮するシステムであり2、いつ切り上げるかもその一部です。自律性こそがエージェントを有用にしているものですが、同じコインの裏側はこれです: "The autonomous nature of agents means higher costs, and the potential for compounding errors."(エージェントの自律的な性質は、より高いコストと、エラーが積み重なる可能性を意味する)2 そしてここで最も重要な一文: "The LLM will potentially operate for many turns, and you must have some level of trust in its decision-making."(LLMは多数のターンにわたって動作する可能性があり、その意思決定にある程度の信頼を置かなければならない)2
腰を据えて考えるべき言葉は信頼です。信頼は、モデルを無監督で放置することと同じではありません。モデルがどこかのステップで詰まったり、ツールが返してきたものに引きずられて脱線したりして、そのまま end_turn を返してこなくなったら、stop_reason しか見ていないループは、あなたの代わりに焦れてくれたりはしません。ラウンドを重ねながら、モデルに付き合って回り続けます——あなたが書いた while 条件のどこにも「もう十分に回った」と書かれていないからです。ですから、モデルによる自己終了だけでは足りません。モデルの気分を待たない、ホストが決める停止条件が必要です。
まずはループにハードなゲートを: 最大ターン数
すべての中で最も基本的な停止条件は、Anthropicのエンジニアリングガイダンスにそのまま名指しされています: "it's also common to include stopping conditions (such as a maximum number of iterations) to maintain control."(制御を保つために、停止条件(最大反復回数など)を含めることもよくある)2 コードに翻訳すれば、ループが何回まで回ってよいかの上限です。
レッスン2の骨組みに対して、変更はわずかです:
ここで重みを担っているのは2つです。第一に、let turns = 0 はループの外で宣言されています。ラウンドをまたいで生き残り、1回ずつ足し上げていく必要があります。そうでなければゲートは何周したのかを知りようがありません。これをループ本体の中に移すと、レベル2の演習が解体するまさにその罠になります。第二に、ゲートはモデルがなぜまだツールを要求しているのかを気にしません——詰まっている、堂々巡りしている、ツールの出力に引きずられて脱線している、どれであろうと問いません。周回数が上限に達したら、ホストは停止し、これ以上リクエストを送らず、制御を自分の側に取り戻します。
これがハードストップです: 境界で無条件に停止し、ループはそこで終わりです。これは、モデルが「終わった」と判断する end_turn によるソフトな終了とは別物です——一方はあなたが設定した上限、もう一方はモデル自身の判断です。MAX_TURNS をどれだけ大きくすべきかに定石はなく、そのタスクにおおよそ何ラウンド必要かに依存することに注意してください。ここでの10は仮置きの値です。大事なのは、ゲートが存在し、暴走したループを実際に止められることです。
ハードストップの先にあるもう1種類: 人間を待つために止まる
最大ターン数のようなゲートには共通する性質があります: そこに達したら道は終わりで、ループは終了し、自動では続きません。しかし停止条件はそれだけではありません。同じ記事はもう1つを名指ししています: "Agents can then pause for human feedback at checkpoints or when encountering blockers."(そのうえでエージェントは、チェックポイントで、あるいは障害にぶつかったときに、人間のフィードバックを待って一時停止できる)2 これはハードストップとは別の生き物であり、切り分けておく価値があります:
- ハードストップ: 上限で停止し、ループは完全に終了、何も自動的には続きません。最大ターン数も予算の使い切りもここに属します。終端状態です。
- ソフトストップ / サスペンド: ループがチェックポイントで意図的に停止し、制御を人間に渡し、その人が答えたらまさにその地点から再開できます。終わりではなく、再開可能な一時停止です。
コードの上では、違いは何を返すかに現れます。ハードストップは最終的な結果を返します——ここで終わりました、と。ソフトストップは状態を保存しなければなりません: 再開できる形で現場のスナップショットを返し、現在の messages と、止まった時点で保留になっているアクションを一緒に引き渡します。そうすれば、人間が対処し終えたあと、そのスナップショットだけで続きを進められます:
ソフトストップの典型的なケースは、モデルの次の一手が取り返しのつかないもの——データベースを落とす、メールを一斉送信する、注文を確定する——であり、実行される前に人間に見てほしい場合か、あるいはモデル自身が詰まっていて追加の情報が必要だと報告してくる場合です。今はハードストップとソフトストップの線を引ければ十分です。needsHumanApproval が実際にどう判断するのか、そして人間が答えたあとループがそのスナップショットからどう再開するのかは、人間をループに残すことを扱うレッスン5の主題です。
フレームワーク: まず「どんな条件で止まらなければならないか」を問う
ハードストップとソフトストップが手元にあると、エージェントの設計に便利な初手ができます。ループを書き始める前に、1つの問いに答えておくのです: これはどんな条件で止まらなければならないか? 答えを書き出してみると、たいていは次の4つに落ち着きます:
- タスクが完了した——モデルが
end_turn を返す。4つの中で最もソフトで、モデルが判断するものであり、本当に完了したのか、途中で諦めたのかは、あなたが確かめる必要があります。
- ターン数の上限——ハードストップ。上で見た
MAX_TURNS のゲートであり、ループが走り出して自分を御せなくなる最悪ケースを捕まえます。
- 人間の判断が必要な障害——ソフトストップ / サスペンドであり、人間のフィードバックを待って一時停止します2。取り返しのつかない操作か、モデルが明示的に行き詰まりを報告したことがきっかけになります。
- 予算の使い切り——ハードストップ。トークン、支出、経過時間のうち、最初に上限に達したものがループを止めます。詳細(どう数えるか、どこに計測を入れるか)はレッスン4に譲ります。
この4つを並べると、見えてくるものがあります: 停止の判断は、すべてがモデルにあるわけではありません。1番はモデルのもの、2番と4番はホストのもの(モデルがどう考えていようと、その印で止まります)、そして3番は共有です。レッスン2のあの骨組みのループは1番だけを実装し、残り3つを落としていました——このレッスンでは最も基本的なハードなゲートである2番を足し、3番と4番はそれぞれレッスン5とレッスン4で入ってきます。
このフレームワークの価値は、4項目を暗記することではありません。習慣を作ることです: ループを書く前に「止まらなければならない」条件を明示的に数え上げる。どうせモデルが止まるだろうという既定の前提の下に埋もれさせておくのではなく。
停止条件は安価な保険であって、過剰設計ではない
こうしたゲートは単純なループを複雑にする、と不満を漏らす人もいるかもしれません。そこでAnthropicが繰り返し立ち返る原則が出てきます: "you should consider adding complexity only when it demonstrably improves outcomes."(結果が明らかに改善される場合にのみ、複雑さを追加することを検討すべきである)2 この一文はたいてい、凝った仕掛けを積み上げるのを思いとどまらせるために引用されますが、停止条件については逆方向を指します——通してよい、と言うのです。
計算してみれば明らかです。最大ターン数のカウンタは、ループの外の宣言1つと中の比較1つ、コードにして数行です。それが防ぐもの——止まらずに回り続けるループ、制御を離れて上っていくコスト、操作されたり壊れたりした出力に基づいて取られる取り返しのつかないアクション——のほうが、はるかに高くつきます。エージェントの自律性はすでに、より高いコストと積み重なるエラーの可能性を伴っており2、停止条件はそのリスクをまっすぐ狙った最も安価なブレーキです。
ですから停止条件は、結果が明らかに改善される場合にのみ足すべき類いの複雑さ2ではありません——その基準を最初から満たしています。最悪ケースの境界を「無制限」から「有制限」に圧縮することは、それ自体が検証可能な結果の改善です。これは自律的なループを「走らせてみようと思える」ものにする最も基本的な制御であって、飾りの追加物ではありません。
まとめ
- ループは
end_turn で自然に終わりますが、それはモデル自身の判断です。その意思決定にはある程度の信頼を置くことしかできず、モデルは多数のターンにわたって動作しうるので、モデルの自己終了だけに頼るのでは足りません2
- 最も基本的なハードなゲートは最大ターン数です: 制御を保つために最大反復回数のような明示的な停止条件を含めることは、よくある方法です2。カウンタはラウンドをまたいで積み上がるようループの外に置く必要があり、本体の中に移すと何も止めないデッドコードになります
- ハードストップの先にはソフトストップ / サスペンドがあります: チェックポイントで、あるいは障害にぶつかったときに、人間のフィードバックを待って一時停止するものです2——終端状態ではなく、現場のスナップショットから続きを進められる再開可能な一時停止です
- エージェントを設計するときは、まずどんな条件で止まらなければならないかを問うてください: タスク完了(
end_turn、モデルの判断)、ターン数の上限(ハードストップ、ホストの判断)、人間の判断が必要な障害(ソフトストップ、共有)、予算の使い切り(ハードストップ、レッスン4で扱います)
- 停止条件は見返りの大きい安価な制御です: 自律性はすでにより高いコストと積み重なるエラーをもたらしており2、最大ターン数のゲートはまさにその最悪ケースを捕まえます。結果が明らかに改善される場合にのみ複雑さを足すという原則2に照らしても、これは最初から基準を満たしています——無制限を有制限に圧縮することは、検証可能な改善です
>> レッスン4: 暴走とフォールバック: デッドループ、空回り、予算バーンアウト