LLMがあなたのコードに直接アクセスすることはありません。LLMはリクエストを渡し、あなたがその関数を実行するのです。 この単純な事実は、「モデルが魔法のようにPythonルーチンを呼び出す」という誤解を覆し、開発者にデバッグとセキュリティの再考を迫るものです。

ディスパッチ・ループのステップ・バイ・ステップ

言語モデル(LLM)がツールを必要とする際、以下の決定論的なシーケンスに従います。

  1. プランニング – モデルが必要なアクション(例:「支払いの返金」)を決定します。
  2. リクエストの生成 – ツール名と引数を含む構造化テキスト(通常はJSON)を出力します。
  3. パース(解析) – アプリケーションまたはサポートフレームワークがそのテキストを読み取ります。
  4. マッチング – フレームワークが、公開されている実際の関数のレジストリから名前を検索します。
  5. バリデーション(検証) – 引数が関数のスキーマに一致しているか、および呼び出し元に権限があるかを確認します。
  6. 実行 – マッチした関数が環境内で実行され、実際の処理を行います。
  7. 返却 – 結果がパッケージ化され、さらなる推論のためにモデルに送り返されます。

LLMを「プランナー」、フレームワークを「ディスパッチャー」、そして関数を「実際にデータや資金を動かすワーカー」と考えてください。

なぜ「魔法」という誤解が続くのか

多くの開発者は、関数呼び出しのように見えるモデルの出力の1行を見て、モデル自身が操作を実行したと思い込んでしまいます。プロバイダーのドキュメントにある「tool calling(ツール呼び出し)」という用語は、モデルが直接コードを呼び出しているかのような印象を与えます。

実際には、モデルは呼び出しを記述した テキストを生成している だけです。ルックアップ、型チェック、権限の強制、エラーハンドリングといった重い処理は、あなたのプロセスが行っています。

内部構造を隠蔽するフレームワーク

PydanticAILangChainのようなライブラリは、このループを抽象化し、ビジネスロジックに集中できるようにします。これらは自動的に以下の処理を行います:

  • スキーマ(例:Pydanticモデル)に基づいた引数のバリデーション
  • 権限の強制(ユーザーがツールを実行できることを確認)
  • 失敗時のリトライ(ツールがエラーを返した場合、モデルに処理を戻す)
  • 暴走ループの防止(連続するツール呼び出しに上限を設ける)
  • 会話状態の維持(ツールの結果を対話に組み込む)

これらのヘルパーを使用しても、パターンは変わりません。モデルがコードを実行することはないのです。

プロバイダーによるネイティブなツール呼び出しサポート

一部のプロバイダーは、ツールの定義とリクエスト形式を標準化する「ネイティブな」ツール呼び出しインターフェースを提供しています。これにより統合はスムーズになりますが、ディスパッチのステップがなくなるわけではありません。リクエストされた操作を実際に実行するコードは、依然としてあなたが記述(またはインポート)する必要があります。

問題の定義を変えれば、デバッグは容易になる

「混乱したエージェント」のせいにするとのではなく、「モデルのレスポンスにツール呼び出しが含まれていなかった」と言うのです。この違いが重要です:

  • ツール呼び出しなし – モデルが直接回答したか、正しくフォーマットされたリクエストを生成できなかった。
  • 不正なリクエスト – JSONの構文が間違っているか、必須フィールドが欠落しているため、ディスパッチャーが拒否した。
  • バリデーション失敗 – 引数がスキーマに一致せず、実行前にエラーが発生した。

失敗を分類することで、ループの各ステージをログに記録し、どこで問題が発生したかを正確に特定できるようになります。

信頼性の高いパイプラインのための実践的なヒント

  • モデルの出力を信頼できない入力として扱う。 副作用を伴うコードを呼び出す前に、すべてのリクエストに対して決定論的なバリデーションを実行してください。
  • 生の(raw)リクエストと各バリデーションステップの結果をログに記録する。 これにより、問題が発生した際に再現可能な履歴を作成できます。
  • 連続するツール呼び出しに明示的な制限を設ける。 暴走ループはリソースを枯渇させたり、レート制限に達したりする可能性があります。
  • 各関数を try/except ブロックで囲む。 モデルが理解できる構造化されたエラーオブジェクトを返し、リトライや適切なフォールバックを促すようにします。
  • 権限チェックをビジネスロジックから分離する。 関数が実行される前に、特に「ユーザー削除」のような特権的なアクションについては、呼び出し元の権利を確認してください。
  • スキーマ駆動の定義(例:Pydanticモデル)を使用する。 これにより、フレームワークがモデルに従うべき JSON スキーマを自動生成できるようになります。

今後の注目点

プロバイダーがネイティブなツール呼び出しAPIを洗練させるにつれ、リクエスト形式に関する契約(コントラクト)がより厳密になり、エラーコードもより詳細になることが予想されます。これらの変化により、バリデーションが容易になり、開発者はより強固なセキュリティの壁を構築できるようになります。ライブラリのアップデートにも注目してください。多くのライブラリが、最新のプロバイダー機能への組み込みサポートを追加しています。

まとめ

LLMは高度なテキスト生成器であり、実行器ではありません。アクションを実行する唯一の権限は、あくまであなたのコードにあります。そして、あなたが構築(またはインポート)するディスパッチャーは、それらのアクションを検証、認可、実行するゲートキーパーとなります。ワークフローを再定義することで、「魔法」という神話を排除し、デバッグを容易にし、あらゆる本番システムに求められるセキュリティ規律を徹底させることができます。