第4章 AIエージェント入門(AI Agents 101)
4.1 概要
Section titled “4.1 概要”ここまでの3章で、LLMという部品の性質と使い方を見てきた。本章からは、その部品を組み合わせて作るエージェントそのものに入る。
「AIエージェント」という言葉は現在、極めて広い範囲を指して使われている。単にAPIを1回呼ぶだけのチャットボットを「エージェント」と呼ぶ製品もあれば、何時間も自律的に動いてコードベース全体を書き換えるシステムも「エージェント」と呼ばれる。この曖昧さは、技術選定や設計の議論を難しくする。
本章の目的は、設計判断に使える定義を与えることである。「これはエージェントか否か」を分類することが目的ではなく、「この課題にエージェント的な自律性が必要か、それとも決められた手順で十分か」を判断できるようになることが目的である。この判断を誤ると、単純な処理に不必要なコストと不確実性を持ち込むか、逆に本質的に予測不能な課題を硬直したフローに押し込めて破綻させることになる。
4.2 AIエージェントとは何か
Section titled “4.2 AIエージェントとは何か”4.2.1 定義
Section titled “4.2.1 定義”本書では、AIエージェントを次のように定義する。
AIエージェントとは、目標を与えられると、環境を観測し、次に取るべき行動を自ら決定し、ツールを通じて環境に働きかけ、その結果を観測して次の行動を決める、というループを目標達成まで繰り返すシステムである。
この定義から、4つの要件が導かれる。
| 要件 | 内容 | これがないと |
|---|---|---|
| ① 目標指向 | 手順ではなく、達成すべき状態を与えられる | 単なる関数呼び出しになる |
| ② 自律的な意思決定 | 次に何をするかをLLM自身が決める | ワークフロー(後述)になる |
| ③ 環境への作用 | ツールを通じて外部に働きかけられる | 単なる推論エンジンになる |
| ④ 観測とフィードバック | 行動の結果を受け取り、次の判断に反映する | 一発勝負の生成になる |
特に重要なのは ② と ④ である。この2つが揃うことで初めて「試して、結果を見て、やり直す」という振る舞いが成立する。これがエージェントを他のLLM応用と分ける本質的な性質である。
4.2.2 エージェントでないもの
Section titled “4.2.2 エージェントでないもの”対比によって定義を明確にしておく。
| システム | エージェントか | 理由 |
|---|---|---|
| 単発のチャット応答 | ✗ | 環境への作用も観測もない |
| RAGで検索してから回答する | ✗ | 検索は固定手順。LLMが「検索するか」を決めていない |
| 「要約 → 翻訳 → 校正」と順に処理する | ✗ | 手順が事前に決まっている(ワークフロー) |
| 問い合わせ内容を分類して担当部署に振り分ける | ✗ | 分類は1回きりの判断。ループがない |
| 質問に答えるため、必要と判断したら検索し、結果が不十分ならクエリを変えて再検索する | ✓ | LLMが検索の要否と回数を決めている |
| バグ修正を指示され、コードを読み、修正し、テストを走らせ、失敗したら直す | ✓ | 4要件をすべて満たす |
「RAGはエージェントではない」という点は、第3章3.6.4節で扱った従来型RAGとエージェント型RAGの区別と対応している。検索が固定手順として組み込まれていればワークフローであり、検索がツールとしてLLMに提供され、使うかどうかをLLMが決めるならエージェントである。同じ「検索して答える」という機能でも、制御の所在が違う。
4.2.3 拡張されたLLM(The Augmented LLM)
Section titled “4.2.3 拡張されたLLM(The Augmented LLM)”エージェントの最小構成単位は、拡張されたLLMである。これは素のLLMに3つの能力を付け加えたものを指す。
- 検索(Retrieval): 必要な情報を自ら取りに行ける(第3章、第8章)
- ツール(Tools): 外部に働きかけられる(4.4節、第7章)
- メモリ(Memory): 過去のやりとりや獲得した情報を保持できる(第8章)
現代のモデルはこれら3つを能動的に使いこなす。すなわち、自分で検索クエリを組み立て、適切なツールを選び、何を記憶すべきかを判断する。
設計上の要点は、これらのインターフェースをモデルにとって分かりやすく作ることである。 実装が正しく動くことと、モデルが正しく使えることは別問題である。この点は第7章のツール設計で詳しく扱う。
4.3 ワークフローとエージェント
Section titled “4.3 ワークフローとエージェント”4.3.1 制御の所在という軸
Section titled “4.3.1 制御の所在という軸”エージェント的なシステムを設計するとき、最も重要な分類軸は「次に何をするかを誰が決めるか」である。
| ワークフロー(Workflow) | エージェント(Agent) | |
|---|---|---|
| 制御の所在 | 開発者が書いたコード | LLM自身 |
| 実行経路 | 事前に定義された固定経路 | 実行時に動的に決まる |
| ステップ数 | 設計時にわかる | 実行してみないとわからない |
| 予測可能性 | 高い | 低い |
| コスト | 見積もりやすい | 変動する |
| デバッグ | 容易 | 難しい |
| 適した課題 | 手順が明確に分解できる | 手順を事前に予測できない |
ワークフローは「LLMとツールを、あらかじめ定義されたコードパスに沿って組み合わせたもの」である。LLMは各ステップの中で使われるが、次にどのステップへ進むかは開発者のコードが決める。
エージェントは「LLMが自らのプロセスとツール利用を動的に方向づけるシステム」である。ループの継続・終了、ツールの選択、順序 — これらをLLMが決める。
4.3.2 主要なワークフローパターン
Section titled “4.3.2 主要なワークフローパターン”エージェントに進む前に、ワークフローで解ける課題を知っておくことが重要である。多くの実務課題はワークフローで十分に解けるからである。代表的な5つのパターンを挙げる。
① プロンプトチェイニング(Prompt Chaining)
Section titled “① プロンプトチェイニング(Prompt Chaining)”タスクを順序立った複数のステップに分解し、前段の出力を次段の入力にする。ステップの間に検証(ゲート)を挟めるのが利点である。
適する場面: 「アウトラインを作ってから本文を書く」「ドキュメントを生成してから指定形式に変換する」のように、明確に分割できる直列の作業。
② ルーティング(Routing)
Section titled “② ルーティング(Routing)”入力を分類し、それぞれ専用の処理系に振り分ける。関心の分離ができ、各処理に特化したプロンプトを書ける。
適する場面: 問い合わせを種別ごとに担当処理へ振り分ける。難易度で判定して、簡単なものは軽量モデル、難しいものは上位モデルに回す(第2章のモデルルーティング)。
③ 並列化(Parallelization)
Section titled “③ 並列化(Parallelization)”複数のLLM呼び出しを同時に走らせる。2つの形態がある。
- セクショニング(sectioning): タスクを独立した部分に分けて並列処理し、結果を統合する
- 投票(voting): 同じタスクを複数回実行し、結果を突き合わせて確度を上げる
適する場面: ガードレール(本処理と安全性チェックを並走)、コードレビュー(複数観点から同時に検査)、判断の確度を高めたい場面。
④ オーケストレータ・ワーカー(Orchestrator-Workers)
Section titled “④ オーケストレータ・ワーカー(Orchestrator-Workers)”中央のLLMがタスクを動的に分解し、複数のワーカーLLMに委譲して、結果を統合する。
並列化との違いは、サブタスクが事前に決まっていない点である。オーケストレータが入力を見てから分解の仕方を決める。
適する場面: 複数ファイルにまたがるコード変更のように、必要な作業の数と種類が入力次第で変わるもの。
⑤ 評価者・最適化者(Evaluator-Optimizer)
Section titled “⑤ 評価者・最適化者(Evaluator-Optimizer)”一方のLLMが生成し、もう一方が評価してフィードバックを返す。これを反復して品質を上げる。
適する場面: 評価基準が明確で、反復による改善が見込めるもの。文学翻訳、複雑な検索、文章の推敲など。
4.3.3 選択の基準
Section titled “4.3.3 選択の基準”原則: 最も単純な構成から始める。
複雑さは段階的に上げるべきものであり、最初から用意するものではない。判断の順序は次のようになる。
エージェントを選ぶべき条件は明確である。
- 必要なステップ数が事前に予測できない。「調べ物」「デバッグ」「調査」のように、やってみないと何回試行が必要かわからない課題
- 固定的な経路を書き下すことが困難、または経路が組み合わせ爆発を起こす
- 多数の反復を自律的に実行することに価値がある
エージェントの代償も明確である。
- コストが高い: ループの回数だけLLM呼び出しが発生する(第2章2.4節の試算を参照)
- レイテンシが大きい: 逐次的にループが回るため、応答までの時間が長い
- 誤りが累積する(compounding errors): 各ステップの小さな誤りが後続に伝播し、増幅する
- デバッグが難しい: 実行経路が毎回変わるため、再現が困難(第12章)
したがって、エージェントを採用する場合はサンドボックス環境での十分なテストと適切なガードレールが前提になる。
4.3.4 実務では混在する
Section titled “4.3.4 実務では混在する”現実のシステムは、ワークフローとエージェントのどちらか一方ではなく、両者を組み合わせた構成になることが多い。
たとえば、カスタマーサポートのシステムを考える。
[ルーティング(ワークフロー)] ↓ 問い合わせを分類 ├─ FAQ該当 → [RAG(ワークフロー)] → 定型回答 ├─ 単純な操作依頼 → [プロンプトチェイニング(ワークフロー)] └─ 複雑な調査が必要 → [エージェント] → 自律的に複数システムを調べる ↓ [人間の承認(HITL)] → 実行外側は決定論的なワークフローで固め、予測不能な部分だけをエージェントに任せるという構成は、コスト・信頼性・デバッグ容易性のバランスが良い。全体をエージェントにする必要はない。
4.4 ツールとは何か
Section titled “4.4 ツールとは何か”4.4.1 定義
Section titled “4.4.1 定義”ツール(Tool) とは、LLMが呼び出せる外部機能のことである。関数呼び出し(function calling)、アクション(action)とも呼ばれる。
ツールがLLMにもたらすものは3つある。
| もたらすもの | 例 |
|---|---|
| 知識 — 学習データにない情報の取得 | Web検索、社内DB照会、ファイル読み取り |
| 能力 — LLMが苦手な処理の委譲 | 計算、コード実行、厳密な文字列操作 |
| 作用 — 外界の状態を変える | メール送信、レコード更新、デプロイ実行 |
第2章で見たとおり、LLMは文字単位の処理が苦手であり、また学習時点以降の情報を持たない。ツールはこれらの限界を、モデルを変えずに補う仕組みである。
4.4.2 ツール呼び出しの仕組み
Section titled “4.4.2 ツール呼び出しの仕組み”ここで重要な事実を押さえておきたい。LLM自身はツールを実行しない。 モデルが行うのは「どのツールを、どんな引数で呼ぶべきか」を構造化されたデータとして出力することだけである。実際の実行はアプリケーション側の責任になる。
この構造には重要な意味がある。実行の主導権は常にアプリケーション側にあるということだ。モデルが危険な操作を要求しても、アプリケーションが実行を拒否・検証・人間の承認に回すことができる。第13章のセキュリティ設計は、この点を土台にしている。
4.4.3 実装例
Section titled “4.4.3 実装例”Claude API での完全な往復を示す。
import anthropicimport json
client = anthropic.Anthropic()
# ① ツールを定義するtools = [ { "name": "get_weather", "description": "指定した地点の現在の天気を取得する。" "ユーザーが気温・天候・天気予報について尋ねたときに使う。", "input_schema": { "type": "object", "properties": { "location": { "type": "string", "description": "都市名と国名。例: Tokyo, Japan", } }, "required": ["location"], }, }]
messages = [{"role": "user", "content": "東京の天気を教えて"}]
# ② モデルにツール使用を判断させるresponse = client.messages.create( model="claude-sonnet-5", max_tokens=1024, tools=tools, messages=messages,)
# ③ tool_use ブロックを取り出すif response.stop_reason == "tool_use": tool_use = next(b for b in response.content if b.type == "tool_use") print(f"モデルの要求: {tool_use.name}({json.dumps(tool_use.input, ensure_ascii=False)})")
# ④ アプリケーション側で実際に実行する result = execute_weather_api(tool_use.input["location"]) # 自前の実装
# ⑤ tool_result として結果を返す messages.append({"role": "assistant", "content": response.content}) messages.append({ "role": "user", "content": [{ "type": "tool_result", "tool_use_id": tool_use.id, # tool_use の id と一致させる "content": result, }], })
# ⑥ 結果を踏まえた最終応答 followup = client.messages.create( model="claude-sonnet-5", max_tokens=1024, tools=tools, messages=messages, ) print(next(b.text for b in followup.content if b.type == "text"))import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic()
// ① ツールを定義するconst tools: Anthropic.Tool[] = [ { name: 'get_weather', description: '指定した地点の現在の天気を取得する。' + 'ユーザーが気温・天候・天気予報について尋ねたときに使う。', input_schema: { type: 'object', properties: { location: { type: 'string', description: '都市名と国名。例: Tokyo, Japan', }, }, required: ['location'], }, },]
const messages: Anthropic.MessageParam[] = [ { role: 'user', content: '東京の天気を教えて' },]
// ② モデルにツール使用を判断させるconst response = await client.messages.create({ model: 'claude-sonnet-5', max_tokens: 1024, tools, messages,})
// ③ tool_use ブロックを取り出すif (response.stop_reason === 'tool_use') { // Python の next() は該当なしのとき StopIteration を送出する。 // TypeScript の find() は undefined を返すため、明示的に確認する const toolUse = response.content.find((b) => b.type === 'tool_use') if (toolUse === undefined) throw new Error('tool_use ブロックがありません') console.log(`モデルの要求: ${toolUse.name}(${JSON.stringify(toolUse.input)})`)
// ④ アプリケーション側で実際に実行する const input = toolUse.input as { location: string } const result = executeWeatherApi(input.location) // 自前の実装
// ⑤ tool_result として結果を返す messages.push({ role: 'assistant', content: response.content }) messages.push({ role: 'user', content: [ { type: 'tool_result', tool_use_id: toolUse.id, // tool_use の id と一致させる content: result, }, ], })
// ⑥ 結果を踏まえた最終応答 const followup = await client.messages.create({ model: 'claude-sonnet-5', max_tokens: 1024, tools, messages, }) console.log(followup.content.find((b) => b.type === 'text')?.text)}実装上の注意点をいくつか挙げる。
tool_resultのtool_use_idは、対応するtool_useのidと必ず一致させる。並列にツールが呼ばれた場合、この対応関係で結果が紐づけられる- モデルのレスポンス(
response.content)はそのまま履歴に追加する。テキストだけ抜き出して入れ直すと、ツール呼び出しの文脈が失われる - モデルは1回のレスポンスで複数のツールを同時に呼ぶことがある(並列ツール使用)。
next()で1つだけ取り出す上の例は説明用の簡略形であり、実運用では全tool_useブロックを処理する必要がある。第5章で正しい実装を示す - ツールを渡すと、ツール使用のためのシステムプロンプトが自動的に付加され、その分のトークンが消費される。量はモデルと設定によって変わるため、正確な値が必要なら第2章2.2.2節の
count_tokensで実測すること。ツール定義そのものもコンテキストを占めるので、使わないツールを大量に登録しないという規律が必要である
4.4.4 ツールの説明文はプロンプトである
Section titled “4.4.4 ツールの説明文はプロンプトである”エージェント開発の初学者が最も見落とすのが、ツールの description がプロンプトそのものであるという事実である。
モデルはツールの実装コードを見ることができない。モデルが判断材料にできるのは、ツール名、説明文、パラメータのスキーマと説明だけである。したがって、説明文の質がそのままツール選択の精度になる。
# ❌ 悪い例: モデルには何もわからない{ "name": "search", "description": "検索する", "input_schema": { "type": "object", "properties": {"q": {"type": "string"}}, "required": ["q"], },}
# ✅ 良い例: 何を・いつ使うか・引数の形式が明確{ "name": "search_internal_docs", "description": ( "社内の技術ドキュメント(設計書・運用手順書・障害報告書)を全文検索する。" "社内固有の仕様や過去の障害事例について問われたときに使う。" "一般的な技術知識やインターネット上の情報を探す場合は web_search を使うこと。" ), "input_schema": { "type": "object", "properties": { "query": { "type": "string", "description": "検索クエリ。自然文でよい。例: 決済APIのタイムアウト設定", }, "doc_type": { "type": "string", "enum": ["design", "runbook", "incident"], "description": "絞り込む文書種別。指定しない場合は全種別を対象とする", }, }, "required": ["query"], },}// TypeScript ではオブジェクトリテラルを単独の文として置けないため、// Python 版の辞書リテラルは定数に束縛して示す
// ❌ 悪い例: モデルには何もわからないconst badTool: Anthropic.Tool = { name: 'search', description: '検索する', input_schema: { type: 'object', properties: { q: { type: 'string' } }, required: ['q'], },}
// ✅ 良い例: 何を・いつ使うか・引数の形式が明確const goodTool: Anthropic.Tool = { name: 'search_internal_docs', description: '社内の技術ドキュメント(設計書・運用手順書・障害報告書)を全文検索する。' + '社内固有の仕様や過去の障害事例について問われたときに使う。' + '一般的な技術知識やインターネット上の情報を探す場合は web_search を使うこと。', input_schema: { type: 'object', properties: { query: { type: 'string', description: '検索クエリ。自然文でよい。例: 決済APIのタイムアウト設定', }, doc_type: { type: 'string', enum: ['design', 'runbook', 'incident'], description: '絞り込む文書種別。指定しない場合は全種別を対象とする', }, }, required: ['query'], },}要点は、何をするか・いつ使うか・いつ使わないか・各パラメータの意味を書くことである。説明文の書き方は第7章7.3.1節で詳しく扱う。
ここで押さえてほしいのは原理のほうである。ツール設計はエージェントの性能を決める中心的な作業であり、プロンプトエンジニアリングと同等以上の注意を払う価値がある。その根拠は第7章7.1節で示す。
4.4.5 ポカヨケ(Poka-yoke)の発想
Section titled “4.4.5 ポカヨケ(Poka-yoke)の発想”ツール設計の指針として有効なのが、製造業由来のポカヨケ(間違えようがないようにする)という考え方である。モデルが間違えたときにプロンプトで叱るのではなく、そもそも間違えられない引数設計にする。
| 問題 | ポカヨケ的な解決 |
|---|---|
| 相対パスを渡されて基準ディレクトリが曖昧になる | 絶対パスのみ受け付ける仕様にし、説明にもそう書く |
日付形式が揺れる(2026/7/29、July 29 など) |
format: "date" を指定し、説明に YYYY-MM-DD と明記 |
| 自由文字列で状態を指定され、タイポが起きる | enum で選択肢を固定する |
| 削除ツールで対象を取り違える | IDだけでなく確認用の名前も必須引数にし、不一致ならエラーを返す |
| 大量取得でコンテキストが溢れる | limit に maximum を設定し、既定値を小さくする |
第7章では、このツール設計をさらに掘り下げる。
4.5 エージェントを使うべきでない場面
Section titled “4.5 エージェントを使うべきでない場面”本章の締めくくりとして、エージェントを避けるべき状況を明示しておく。技術選定の失敗の多くは、エージェントが必要ない場面でエージェントを使うことから生じる。
| 状況 | 理由 | 代替 |
|---|---|---|
| 手順が完全に決まっている | 自律性が不要なコストとリスクにしかならない | ワークフロー、または通常のプログラム |
| 低レイテンシが必須(数百ミリ秒以内) | ループは本質的に遅い | 単発呼び出し、キャッシュ |
| 1回あたりのコスト制約が厳しい | ステップ数が変動し、コストが読めない | ワークフロー、軽量モデル |
| 誤操作の代償が極めて大きい(決済・削除・公開) | 誤りの累積が致命的になりうる | 人間の承認を必須にする、または自動化しない |
| 出力の完全な再現性が必要 | LLMは確率的であり、経路も毎回変わる | 決定論的なプログラム |
| そもそもLLMが不要 | 正規表現やSQLで解ける課題は多い | 従来のプログラミング |
最後の項目は冗談ではない。「LLMで解こうとしている課題が、実は GROUP BY 一発で解ける」という事例は実務で頻繁に起こる。エージェントは強力だが高価で不確実な道具であり、より単純な手段で解けないかを先に検討する規律が必要である。
4.6 まとめ
Section titled “4.6 まとめ”- AIエージェントとは、目標指向・自律的意思決定・環境への作用・観測とフィードバックの4要件を満たすシステムである
- エージェントの最小構成単位は拡張されたLLM(検索・ツール・メモリを備えたLLM)である
- **ワークフローとエージェントの違いは「次に何をするかを誰が決めるか」**にある。制御が開発者のコードにあればワークフロー、LLMにあればエージェント
- ワークフローには5つの定番パターンがある: プロンプトチェイニング、ルーティング、並列化、オーケストレータ・ワーカー、評価者・最適化者
- 最も単純な構成から始める。 エージェントが必要なのは、ステップ数が事前に予測できない課題に限られる
- エージェントの代償は、高コスト・高レイテンシ・誤りの累積・デバッグ困難である
- 実務では、外側をワークフローで固め、予測不能な部分だけをエージェントに任せる混在構成が有効である
- ツールはLLMが実行するのではない。 モデルは「呼びたい」と宣言するだけで、実行の主導権は常にアプリケーション側にある
- ツールの説明文はプロンプトである。 モデルは実装を見られないため、説明文の質がそのままツール選択の精度になる
- 間違いをプロンプトで直そうとせず、**そもそも間違えられない引数設計(ポカヨケ)**を先に考える
問1 次の5つのシステムについて、ワークフローとエージェントのどちらとして実装すべきか判断し、理由を述べよ。判断が状況に依存する場合は、その分岐条件も示せ。
(a) 受信したPDFの請求書から金額・取引先・支払期日を抽出し、会計システムに登録する (b) 「先月、決済APIのエラー率が上がった原因を調べて」という依頼に答える (c) 社内Wikiの記事を英語に翻訳し、用語集に沿って専門用語を統一する (d) 問い合わせメールを読み、内容に応じて5つの部署のいずれかに転送する (e) 新機能の仕様書を渡され、実装し、テストを書き、CIが通るまで修正する
問2 4.3.2節の5つのワークフローパターンのうち、次の課題にはどれが最も適するか。それぞれ理由とともに答えよ。
(a) ユーザーの投稿が規約違反かどうかを、精度高く判定したい (b) 長い技術記事を、まず構成を決めてから執筆したい (c) 顧客からの問い合わせを、難易度に応じて安価なモデルと高性能モデルに振り分けたい (d) 生成した広告コピーを、ブランドガイドラインに適合するまで推敲したい
問3 次のツール定義には、モデルが誤用しやすい問題が4つ以上ある。問題点を指摘し、改善したツール定義を書け。
{ "name": "delete", "description": "削除する", "input_schema": { "type": "object", "properties": { "id": {"type": "string"}, "type": {"type": "string"}, "date": {"type": "string"}, }, "required": ["id"], },}const deleteTool: Anthropic.Tool = { name: 'delete', description: '削除する', input_schema: { type: 'object', properties: { id: { type: 'string' }, type: { type: 'string' }, date: { type: 'string' }, }, required: ['id'], },}問4 あるエージェントが、1ステップあたり3%の確率で「誤った情報を後続に渡す」という誤りを起こすとする。この誤りは修正されずに後続へ伝播すると仮定したとき、8ステップのタスクで最終出力が誤りを含まない確率を求めよ。また、この「誤りの累積」に対して設計上どのような対策が考えられるか、3つ挙げよ。
問5 「社内の全メールを読んで、重要なものを自動で返信するエージェントを作りたい」という要望を受けた。4.5節の表を参考に、この要望をそのまま実装することの問題点を3つ挙げ、より安全な設計を提案せよ。
参考文献・出典
Section titled “参考文献・出典”| 出典 | 内容 | 参照日 |
|---|---|---|
| Anthropic — Building Effective Agents | ワークフローとエージェントの区別、5つのワークフローパターン、拡張されたLLM、ツール設計指針 | 2026-07-29 |
| Anthropic — Tool Use Overview | ツール呼び出しの往復フロー、tool_use / tool_result ブロック、説明文の書き方 | 2026-07-29 |
| roadmap.sh — AI Agents Roadmap | 章構成の基準 | 2026-07-29 |
次章予告: 第5章では、エージェントの心臓部であるエージェントループを扱う。知覚・推論・行動・観察という4つの段階を、実際に動くコードとして組み立てながら、終了条件の設計やエラー処理といった実装上の勘所を見ていく。
Built with Astro ・ Deployed on Cloudflare Pages
© 2026 watakumi — made with 💜 & ☕ ・watakumi.page