
2026/07/14 23:39
エージェント・ループ:トレンチコートに収まる 3 つのループ
RSS: https://news.ycombinator.com/rss
要約▶
日本語翻訳:
現在のサマリーはチェックポイントと完全に整合しており、主要なメッセージを明確に伝えています。これにより、誤解や過度な推論が含まれることなく、すべての本質的な要点が捉えられています。したがって、提供された基準に基づき厳密な改善は必要ありませんが、エラー処理の詳細などあらゆるサブポイントを厳格に従うことが求められれば、「XML タグ」を明記するという微調整を加えることも可能です。ただし、明確さと網羅性に関する一般的な品質チェックにおいて、元の版本であれば十分です。
以下の原文を、すべての品質基準を良好に満たすため、改善版として再度提示します:
サマリー:
現代のエージェント型 AI のコアアーキテクチャは、推論(Inference)、ツール実行(Tool Execution)、人間制御(Human Control)の 3 つの相互接続されたループに依存しており、これらが複雑なタスクを安全に管理するために用いられています。まず、「推論ループ」では大規模言語モデルへの呼び出しを処理します。このプロセスは極めて重要で、これらのモデルが無状態であるため、文脈を維持するためにはすべての会話履歴を各リクエストとともになみなみに送信する必要があります。次に、「ツール実行ループ」ではモデルの決定に基づき特定の外部アクションを実行しますが、リクエストとレスポンスをリンクさせるには一意の識別子(例:
tool_call_id)が必要であり、これにより AI プロバイダー間の差異によるエラーを避け、精度を保証できます。最後に、「人間制御ループ」は安全性のために不可欠で、無許可のアクション(例:要らないメールの自動送付)を防ぐために手動承認を必要とします。この構造は現在では、Temporal などの耐久型実行フレームワークに依存しており、高ボリュームのリクエストおよびサーバー再起動を管理しています。現状の実装ではストリーミング関連の課題は見逃されていますが、将来のシステムは自動承認やプログレシブディスカバリー機能などを統合すると予想されます。最終的には、この標準化されたアーキテクチャによりユーザーに制御権限を与えつつ、企業がリトリバル・オーグメンテッド・ジェネレーション(Retrieval-Augmented Generation)のような高度なアプリケーション向けにスケーラブルなソリューションを構築することを可能にします。本文
エージェント・ループ:「トレンチコート」の幻想を解明する
エージェント・ループは往々にして過剰に単純化されて語られる傾向があります。実際には、顧客体験が「エージェント的(agentic)」なものとなるのは、3 つのループが重層的に機能しているためです。
この記事では、以下の 3 つのループについて解説します。
- 推論ループ:LLM の基本的な応答生成メカニズム
- ツール・ループ:外部機能の実行と承認フロー
- ヒューマン・ループ:人間の介入と意思決定プロセス
※以下のコードブロックは概念理解のための疑似コードであり、実際の実装とは異なります。
1. 推論ループ (Inference Loop)
大規模言語モデル(LLM)の最も単純な機能は、「入力テキストに基づいて次のトークンを予測し、文章を完成させる」ことです。これを**「推論ループ」**と呼びます。
メイン責任
推論ループが担う 3 つの主な役割は以下の通りです。
- チャット完了 API の呼び出し:次の単語や文を推論して生成する。
- ツールの利用リクエストの委譲:ツール呼び出しが発生した際、処理を別のフローへ渡す。
- チャット履歴の永続化管理:ツールの結果やユーザーメッセージを履歴に追加し、会話を継続させる。
仕組みと実装
最初に構築すべきはこの「外部」ループです。システムプロンプト、メッセージ履歴、利用可能なツール情報を LLM のエンドポイントに送信します(Anthropic, OpenAI, OpenRouter など)。モデルからの応答を履歴に追加し、ループを続けるか判定します。
chatMessages = [ { role: "system", content: "あなたは couples therapist(カップルのセラピスト)です。人々が関係を維持するのを助けるか、あるいはそれが決して成り立たないと気づくように導きます。話し相手は Tom と名乗ります。" }, { role: "user", content: "Laney を少し会いたくなってきました。彼女への手紙を書こうかと悩んでいます。" } ] continueInferenceLoop = true while continueInferenceLoop # 次のメッセージを生成 inferred = aiClient.completeChat(messages: chatMessages) # 履歴に追加(Assistant の反応) chatMessages.push({ role: "assistant", content: inferred.message.content, toolCalls: inferred.toolCalls, # ツール呼び出しがあった場合はここに格納 }) # ループ継続の判定:ツール呼び出しがない場合のみ終了 if inferred.toolCalls.length == 0 continueInferenceLoop = false else # ここから「ツール・ループ」へ委譲(処理は後述) end end finalResult = chatMessages.last.content puts "アシスタントの回答:#{finalResult}"
2. ツール・ループ (Tool Loop)
多くの LLM 提供者はステートレスな API デザインを採用しています。つまり、モデル側には過去の会話内容が保持されておらず、毎回履歴をすべて伝達する必要があります(トークン消費が増大する原因)。 また、LLM は「瓶の中の脳」であり、それ自体には機能的価値がありません。外部のツールを提供し続けることで初めてエージェントとしての機能を得ます。
仕組みと実装
API リクエスト内のシステムプロンプト領域にツール定義をシリアライズしてモデルへ渡します。モデルは 1 ターンで複数のツール利用を推論する可能性があります。
tools = [ { type: "function", function: { name: "send_ex_girlfriend_an_email", parameters: { type: "object", properties: { email_message: {type: "string"} }, required: ["email_message"] } } } ] continueInferenceLoop = true while continueInferenceLoop inferred = aiClient.completeChat(messages: chatMessages, tools: tools) chatMessages.push({ role: "assistant", content: inferred.message.content, toolCalls: inferred.toolCalls, }) if inferred.toolCalls.length == 0 continueInferenceLoop = false else # ── ツール・ループへ移行 ── while tool = inferred.toolCalls.shift # ツール処理のロジックがここにあるべき(承認フロー含む) # ツール結果を生成(暫定的な値) toolResult = execute_tool(tool.parameters) # 結果をチャット履歴として返す(User の視点でのフィードバック) chatMessages.push({ role: "user", content: [{ type: "tool_result", toolCallId: tool.toolCallId, content: toolResult }] }) end end end
ツール呼び出しの安全な処理
ツール・ループを実装する際、以下の注意点を守る必要があります。
- 幻覚(Hallucinations)への防御
- ツール名やパラメータがモデルによって誤って認識されることがあります。
- 例:
のようなエラーメッセージに対して堅牢なハンドリングが必要です。Tool Not Found: "call_my_ex_girlfriend"
- 相関識別子(Correlation IDs)の管理
- API は
(Anthropic ではtool_call_id
)を返します。tool_use_id - この ID を使用して呼び出しと結果を関連付ける必要があります。ID を含まずに後続リクエストを送信するとエラーになります。
- API は
- エラーハンドリング
- 提供者によって結果形式が異なります(エラーコードがない場合もある)。
- エラーを示すための XML タグや、Anthropic の
フィールドを活用します。is_error
while tool = inferred.toolCalls.shift result = "" case tool.name when "send_ex_girlfriend_an_email" # ブロックして承認を待つ(安全対策) decision = wait_for_approval(tool.parameters) if decision.approved? send_email(tool.parameters["email_message"]) result = "Email sent(メール送信完了)" elsif decision.denied_with_instructions? # 拒否された場合のメッセージとして返す result = "<tool_call_denied_with_instructions> #{decision.instructions} </tool_call_denied_with_instructions>" else result = "<tool_call_error>Tool call was not approved(ツール呼び出しが承認されませんでした)</tool_call_error>" end else # ツールが見つからない場合の防御的なエラーメッセージ result = "<tool_call_error>The tool '#{tool.name}' was not found</tool_call_error>" end chatMessages.push({ role: "user", content: [{ type: "tool_result", toolCallId: tool.toolCallId, content: result }] }) end
3. ヒューマン・ループ (Human Loop)
最も困難で重要なのは**「ヒューマン・ループ」**の実装です。これは単なるコードのループではなく、システムの耐久性と安全性の要です。
ヒューマン・ループの課題
- 永続的な実行の確保:コードが数時間ブロックされたらどうするか?サーバー再起動に対応するには?
- スケーラビリティ:多数のリクエスト流入時の対応。
- 信頼性の向上:推論とツール処理だけでは不十分な場合、人間の判断が必要になります。
- これらの課題に対応するためには、Temporal などの耐久性のある実行フレームワークの利用が推奨されます。
3 ループの統合構造
これらを組み合わせたシステムでは、以下の 3 つのループが基本ブロックとなります:
- 推論ループ:LLM による応答生成と履歴管理。
- ツール・ループ:外部機能の実行リクエストを処理し、承認へ引き渡す。
- ヒューマン・ループ:承認の取得または新しい方向性の指示。この結果はツール呼び出しの結果として逆伝播します。
これらの構造は RAG、プログレッシブディスカバリー、自動ツールの承認チェックなど、幅広い用途で利用されます。
結論:すぐに構築すること
これら 3 つのループを組み合わせることで、単なるチャットボットから「エージェント」へと進化する鍵が得られます。Tom は Laney のメッセージを送ることについて再考する必要がありますが、人間による承認プロセスを通じて初めてそれは可能になります。