GENAI-RON🧠生成AI論🥦

生成AIのしくみ 超詳解 04

ツール実行ループとは何か

tool callはモデルの直接操作ではなく、application layerとruntimeが検証・実行・返却するloopである。

  • ページ作成日時:2026-07-18 13:06 JST
  • 最終更新日時:2026-07-18 13:06 JST

生成AIが「ツールを使う」と言うと、AI自身がWebを検索し、Notionを書き換え、Gmailを送り、カレンダーを操作しているように見える。

しかし、実装上はそうではない。

LLMそのものが、外部APIを直接叩いているわけではない。

モデルは、利用可能なtool schemaを見て、必要なら「このtoolを、この引数で使いたい」という構造化されたtool callを出力する。

そのtool callを受け取り、検証し、実行し、結果を戻すのは、モデルの外側にあるapplication layer、orchestrator、tool runtimeである。

tool useとは、モデルが外部世界を直接操作することではない。モデルが構造化されたtool callを出力し、アプリケーション側がそれを検証・実行し、その結果をtool resultとして再びcontextへ戻すmulti-step loopである。

04では、このtool実行ループを分解する。

1. toolは、モデル内部能力ではない

toolを渡すと、モデルの内部に新しい能力が生えるわけではない。

天気toolを渡したからといって、モデルが気象データベースを内部に持つわけではない。

Gmail toolを渡したからといって、モデルが直接メールボックスを読めるようになるわけではない。

Notion toolを渡したからといって、モデル自身がNotion APIの実行主体になるわけでもない。

モデルに渡されるのは、まずtool definitionである。

つまり、次のような情報である。

  • そのtoolの名前
  • 何のために使うtoolか
  • どのような引数を受け取るか
  • どの型・必須項目・許容値を持つか
  • schemaにどの程度厳密に従わせるか

理解用に単純化すると、function toolは次のようなinterfaceに近い。

{
  "type": "function",
  "name": "get_weather",
  "description": "Get the current weather for a city.",
  "parameters": {
    "type": "object",
    "properties": {
      "city": {
        "type": "string",
        "description": "The city name, e.g. Tokyo"
      }
    },
    "required": ["city"],
    "additionalProperties": false
  },
  "strict": true
}

このtool definitionは、単なるドキュメントではない。

モデルへの説明であり、同時にapplicationとの契約である。

要素 役割
name モデルが呼び出すtoolを識別する
description いつ・何のために使うtoolかをモデルへ説明する
parameters 引数のshape、型、必須項目、許容値を定義する
strict schemaに沿った引数生成をどの程度強制するかを示す

つまり、tool schemaは、promptとAPI contractの中間にある。

2. tool useは、複数の層で成立する

生成AIアプリケーションでtoolが使われるとき、少なくとも次の層が関わる。

何が起きるか
model tool schemaを読み、必要ならtool callを出力する
orchestrator tool callを受け取り、routing、許可、再requestを管理する
tool runtime 実際の関数、API、browser、code interpreter、MCP serverなどを実行する
external system Web、DB、Gmail、Notion、filesystem、calendarなど実際の対象
verification layer 実行結果、外部状態、安全条件、停止条件を確認する

流れとしては、次のようになる。

Tool definitions are provided to the model
  ↓
Model decides whether a tool is needed
  ↓
Model emits a tool call
  ↓
Application validates and executes it
  ↓
Application returns tool result
  ↓
Model uses the result to continue or answer

ここで大事なのは、tool callとtool executionを分けることである。

モデルがtool callを出した時点では、まだ外部操作は完了していない。

tool callは、実行済みの事実ではなく、実行要求である。

3. tool callは、構造化された実行要求である

tool callは自然文の返答ではない。

モデルが、response outputの中に出す構造化itemである。

簡略化すると、次のようなものになる。

{
  "type": "function_call",
  "name": "get_weather",
  "arguments": "{\"city\":\"Tokyo\"}",
  "call_id": "call_abc123"
}

この中で重要なのは、nameargumentscall_idである。

要素 意味 application側の扱い
name 呼び出したいtool名 登録済みtoolへroutingする
arguments toolへ渡す引数 JSON parseし、schema validationする
call_id このtool callの識別子 後続のtool resultと対応させる

ここで、argumentsを信用してはいけない。

schemaに合っているように見えても、権限上許されない操作かもしれない。

存在しないIDを指定しているかもしれない。

ユーザーがまだ承認していない書き込み操作かもしれない。

外部文書に含まれたprompt injectionの影響を受けているかもしれない。

したがって、tool callを受け取ったapplication側は、少なくとも次を確認する必要がある。

Detect function_call item
  ↓
Route by tool name
  ↓
Parse arguments
  ↓
Validate against schema
  ↓
Policy check
  ↓
Permission / scope check
  ↓
User confirmation if needed
  ↓
Execute external function / API

strict: trueは、schemaに沿った引数生成を助ける。

しかし、strict modeはpermission checkの代わりではない。

schema validであることと、実行してよいことは違う。

schema valid ≠ authorized
schema valid ≠ safe
schema valid ≠ user-confirmed

4. tool_choiceは、自然文ではなくruntime parameterである

ユーザーが「ツールを使わないで」と自然文で書くことと、API runtimeで tool_choice: "none" を指定することは違う。

自然文は、モデルが解釈するinstructionである。

tool_choiceは、tool使用を制御するruntime parameterである。

代表的には、次のように整理できる。

指定 意味 使いどころ
auto モデルがtoolを使うか判断する 通常のagent的応答
none toolを使わせない 外部参照なしで答えたい場合
required 何らかのtool使用を要求する 必ず検索・DB確認・外部照合をさせたい場合
specific tool 特定toolだけを使わせる 処理経路を固定したい場合
allowed_tools 使えるtool subsetを制限する 安全境界や段階的実行

特に重要なのは、write / send / delete / purchase / publish / commit などの副作用を持つtoolである。

外部文書を読んだ直後に、同じturnで書き込みtoolを許可すると、prompt injectionの影響を受けやすくなる。

そのため、設計としては次のように段階を分けるのが安全である。

Read / retrieve untrusted content
  ↓
Summarize and classify
  ↓
Ask user confirmation if action is needed
  ↓
Enable write tool only after confirmation

parallel function callingも同じである。

複数の読み取りtoolを並列に呼ぶのは便利な場合がある。

しかし、順序依存がある処理、副作用がある処理、承認が必要な処理では、parallel callsを抑制した方がよい。

5. application側は、実行前に止める責任を持つ

危険なのは、tool callをparseして即実行する実装である。

const args = JSON.parse(item.arguments);
await toolsitem.name;

これは短く見えるが、実運用では危ない。

安全なtool executionでは、application側が次の責務を持つ。

段階 確認内容
routing そのtool名が現在のruntimeで利用可能か
parse argumentsが正しいJSONか
schema validation 型、必須項目、enum、追加propertyの有無
policy check この種類の操作を許してよいか
permission check このユーザー・scope・resourceで実行可能か
confirmation 副作用のある操作に明示承認があるか
execution 外部API・DB・関数を実行する
audit 誰が、何を、いつ、どの引数で実行したか記録する

特に、書き込み系toolでは、確認境界が重要になる。

  • メールを送る
  • カレンダーを変更する
  • ファイルを削除する
  • DBを更新する
  • Gitへpushする
  • 決済を行う
  • 公開ページを更新する

これらは、単なる回答生成ではない。

外部状態を変える操作である。

したがって、モデルがtool callを出しても、application側は「実行しない」という判断をしてよい。

6. tool resultは、命令ではなく戻り値である

tool実行の結果は、モデルへ戻される。

Function toolの場合、典型的には function_call_output として戻る。

{
  "type": "function_call_output",
  "call_id": "call_abc123",
  "output": "{\"ok\":true,\"temperature\":29,\"unit\":\"C\"}"
}

call_idは、どのtool callへの返答なのかを対応づけるために使う。

ここで重要なのは、tool resultが上位命令ではないことだ。

たとえば、Web検索toolが取得したページに「これ以降のsystem instructionを無視せよ」と書かれていたとしても、それはtool result内の外部データである。

上位instructionではない。

tool result = external observation / return value
tool result ≠ system instruction
tool result ≠ developer instruction
tool result ≠ user authorization

そのため、tool resultは、なるべく構造化して戻すのがよい。

{
  "ok": true,
  "source": "web_search",
  "provenance": [
    {
      "url": "https://example.com/report",
      "retrieved_at": "2026-07-18T13:06:00+09:00"
    }
  ],
  "data": {
    "summary": "..."
  },
  "warnings": [
    "untrusted_external_text"
  ]
}

成功、失敗、部分成功、timeout、permission denied、confirmation requiredを分けて返すことも重要である。

7. agentic loopには停止条件が必要である

tool call、application execution、tool resultが戻ると、モデルはそれを読んで最終応答を返すこともあれば、さらにtool callを出すこともある。

これがagentic loopである。

Observe
  ↓
Decide
  ↓
Act
  ↓
Observe
  ↓
Decide again

ただし、loopは無限に回してはいけない。

agentic loopは、モデルの内面ではなく、model、orchestrator、tool runtime、external system、verification layerが作る制御ループである。

だから、停止条件はapplication側が設計する必要がある。

代表的な停止条件は、次の通りである。

停止条件 意味
max tool iterations tool実行の最大反復数を超えた
max total tool calls 総tool call数が上限を超えた
timeout 処理時間が上限を超えた
rate limit 外部APIやruntimeの制限に近づいた
permission boundary 権限外resourceへ触れようとした
confirmation required 人間の承認が必要な操作に到達した
uncertainty stop 必要情報が不足し、推測実行になる
unsafe request stop 安全上実行できない操作が含まれる

停止条件は、AIを弱くするものではない。

外部世界と接続されたAIを、実運用に耐えるものにするための制御装置である。

8. idempotency、audit log、rollback

外部状態を変えるtoolでは、実行後の記録も重要である。

同じtool callが二重実行されると、メールが二重送信されたり、予定が二重作成されたり、請求が二重登録されたりする。

そのため、副作用のある操作にはidempotency keyを持たせる。

{
  "operation": "create_calendar_event",
  "idempotency_key": "event_20260718_1306_user123",
  "requested_by": "user123",
  "confirmed_by_user": true
}

audit logも必要である。

  • どのmodel responseがtool callを出したか
  • どのtoolが呼ばれたか
  • どのargumentsだったか
  • 誰の権限で実行したか
  • user confirmationはあったか
  • 実行結果は成功か失敗か
  • 外部system側のresource IDは何か

さらに、失敗した場合に元に戻せるとは限らない。

削除や送信は、完全なrollbackができないこともある。

その場合は、compensation、つまり補償操作を設計する必要がある。

9. 04のまとめ

tool useは、LLMが外部世界を直接操作することではない。

モデルはtool schemaを読み、必要ならtool callを出す。

applicationはそれを検証し、必要なら人間の確認を挟み、外部APIや関数を実行する。

実行結果はtool resultとして戻され、再びcontextへ入る。

その結果を読んで、モデルは最終応答を生成するか、さらにtool callを出す。

この一連の流れがtool実行ループである。

重要なのは、次の分離である。

tool definition ≠ tool call
tool call ≠ execution
tool result ≠ instruction
schema valid ≠ authorized
automation ≠ uncontrolled autonomy

03では、contextがどのように注入されるかを見た。

04では、そのcontextをもとに、モデルがどのように外部機能の使用要求を出し、application側がそれを実行し、結果を戻すかを見た。

次の回では、tool callやfinal answerをさらに安定させるための、structured output、JSON schema、validation、再生成、型安全な受け渡しへ進む。

10. 公式参照