コンテンツにスキップ

登場人物と責任範囲

最初に、LLM エージェントを構成する登場人物と、それぞれが何を担当しているのかを整理する。以降の章はこの見取り図を頭に入れた上で、各要素を順番に掘り下げる形になる。

LLM は次のことを知っているか

以下を LLM (モデル) 単体に聞いた場合、どこまで正確に答えられるか考えてみる。

# 質問 LLM 単体でわかる?
Q1 今の日時は? ✗ わからない
Q2 今日の東京の天気は? ✗ わからない
Q3 3847 × 2915 は? △ 推論モデルなら大抵解けるが、速度 / コスト / 信頼性の面でツールが有利
Q4 日本の現在の政策金利は? △ 学習カットオフ次第
Q5 このリポジトリにある examples/agent-demo/src/tools.ts の中身は? ✗ わからない
Q6 富士山の高さは? ◯ わかる

なぜこうなるのか:

  • Q1 (日時): LLM は推論時にクロックを持っていない。入力テキストから日付を推測することはあるが、実行時の「今」を正しく把握する手段がない。
  • Q2 (天気): リアルタイム情報。学習データに含まれるはずがない。
  • Q3 (計算): 少し前の LLM は「次のトークンを確率的に予測する」仕組みから離れられず、桁が増えるとすぐにボロが出ていた。しかし最近の推論モデル (GPT-5.4 reasoning / Claude Sonnet 4.6+ / Gemini 2.5 Pro 等) は、内部で chain-of-thought を展開して筆算相当の手続きを踏むので、3847 × 2915 のような問題はほぼ正答する。ただしそれでも calc ツールを使うべき理由がいくつもある:
  • 速い: 電卓 (あるいは Python) なら μs オーダーで終わることを、LLM は数千〜数万トークン消費してやっている
  • 安い: 推論トークンは大抵のモデルで通常トークンの数倍〜のコスト。桁数が増えるほど料金が跳ねる
  • 確実: 推論モデルでも稀に計算ミスする (特に浮動小数点、大きな桁数、複数ステップの四則混合)
  • 監査可能: ツール実行ログには明示的に入力 / 出力が残るので、「正しく計算されたか」を後から検証できる
  • 要するに「LLM が計算できるかどうか」と「LLM に計算させるべきか」は別の問題
  • Q4 (金利): 学習データに含まれるのは特定時点までで、それ以降の値は知らない。さらに直近の話題は学習時点より数か月古いことが多い。
  • Q5 (リポジトリのファイル): ローカルファイルシステムは学習データに含まれない (当たり前)。
  • Q6 (富士山の高さ): 学習データに含まれる安定した事実は答えられる。

つまり LLM 単体でできるのは「学習時に焼き込まれた一般的な事実と言語運用」+「推論モデルなら論理的展開や筆算」まで。一方で、「今この瞬間の情報」「ローカル環境の中身」、そして 「速度 / コスト / 確実性が求められる計算」は、引き続き別の仕組み (ツール) で補うのが合理的。

登場人物

その「別の仕組み」を組み上げたのがエージェントという構造。本リポジトリの examples/agent-demo/ を例にすると、登場人物はこの 5 つ:

          ┌─────┐
          │  人  │         質問を投げる / 応答を受け取る
          └──┬──┘
             │ 入力 / 出力
      ┌──────────────┐
      │ [入力ガード] │    ユーザ入力の検査 / 正規化 / マスキング
      └──────┬───────┘
  ┌─────────────────────┐   prompt    ┌─────┐
  │    エージェント     │ ──────────► │     │
  │                     │             │ LLM │   学習済みの言語モデル
  │ (agent-demo の      │ ◄────────── │     │
  │  TS プログラム)     │  tool_call  └─────┘
  └─────────┬───────────┘
            │ 呼び出し
      ┌──────────────┐
      │ [ツールガード]│    引数バリデーション / 認可 / レート制限
      └──────┬───────┘
      ┌──────────────┐
      │    ツール    │     search, calc, wikipedia, now, ...
      │ (外の世界に  │     LLM の「手足」。実世界から情報を取る /
      │  繋がる道具) │     実世界に働きかける
      └──────┬───────┘
             │ 結果
      (エージェントへ戻る)
      ┌──────────────┐
      │ [出力ガード] │    LLM の最終応答の検閲 / PII 除去 / 整形
      └──────┬───────┘
          ┌─────┐
          │  人  │        最終応答を受け取る
          └─────┘

それぞれの役割

登場人物 何をする 実体 (agent-demo の場合)
要求を入力し、最終応答を受け取る ターミナルで mise run agent-single -- "..." を叩く人、対話モードの you> プロンプトに入力する人
エージェント 人の要求 → LLM への問いかけ → 必要ならツール呼び出しのループ → 最終応答、のオーケストレーション examples/agent-demo/src/agent-single.ts / agent-chat.ts (LangChain JS の createAgent を使った TypeScript プログラム)
LLM 与えられた会話履歴に対し「次に何を言うか / どのツールを呼ぶか」を判断する LiteLLM 経由で叩かれる Claude / GPT / Gemini / Ollama のモデル
ツール LLM が自分では持っていない情報や能力を提供する (時刻、検索、計算、RAG、API 呼出、ファイル操作など) examples/agent-demo/src/tools.ts に定義された search / fetch_url / wikipedia / now / calc / random_int / end_chat
ガード 安全性 / 整合性 / 認可の担保。入力・出力・ツール実行の各段で働く agent-demo は最小構成のため未実装だが、本番では必須 (後の章で扱う)

誰がやっているのか

最初の Q1-Q5 をエージェント越しに聞くと、それぞれ次のように解決される:

質問 誰が答えるか 流れ
Q1: 今の日時 now ツール LLM が「時刻を知らないので now を呼ぼう」と判断 → ツール実行 → 結果を LLM に戻す → LLM が人間向けに整形
Q2: 今日の天気 search ツール (→ SearXNG → Web) LLM が「Web 検索が必要」と判断 → search ツール → 検索結果から要約
Q3: 3847 × 2915 calc ツール (決定論的な計算) 推論モデルは「頑張れば自力で解ける」が、速度 / コスト / 信頼性のために LLM が「ここは calc に任せるべき」と判断 → 即座に正答
Q4: 政策金利 search or wikipedia ツール LLM が「自分の知識は古いかも」と判断 → 最新情報を取得
Q5: リポジトリのファイル (agent-demo には無いが) file_read ツール ローカルに繋ぐツールを追加すれば解決可能
Q6: 富士山の高さ LLM 単独 学習済みの事実で十分 → ツール呼出なしで直接答える

ここで重要なのは、LLM は「自分には何ができて、何が無理か」を判断するという部分が core であること。道具箱 (tools) をどれだけ揃えても、LLM 側で「これは道具を使うべき場面だ」と認識しなければ使ってくれない。この判断を LLM に促すのがエージェントのシステムプロンプトで、道具を渡すだけなのがツール定義 (JSON schema)。