
AIエージェントの構築は複雑に聞こえます。すべてをゼロから構築しようとすれば、実際に複雑になり得ます。しかし、コアパターンはシンプルです。言語モデルにツールへのアクセスを与え、どのツールをいつ使うかを自分で判断させ、目標に到達するまで繰り返すだけです。
このガイドでは、アーキテクチャから動作するコードまで、AIエージェントをステップバイステップで構築する方法を解説します。最後には、ウェブ検索、画像生成、結果の配信までを単一のCLIで実行できる実用的なエージェントが完成します。
AIエージェントとは?
コードを書く前に、何を構築するのかを定義しましょう。
AIエージェントとは、目標を受け取り、一連のアクションを計画し、ツールを使ってそれらのアクションを実行し、結果を観察して適応するシステムです。単一のプロンプトに応答するチャットボットとは異なり、エージェントは数十回のツール呼び出しにわたって自律的に目標に向かって作業します。
チャットボット: 「この記事を要約して。」 → 要約を返す。 AIエージェント: 「このトピックを調査し、最良の情報源を見つけ、レポートを作成して公開して。」 → 計画、検索、読解、執筆、公開。
エージェントの力はツール、つまり呼び出せる能力から生まれます。ツールがなければ、エージェントは長いプロンプトを持つ言語モデルに過ぎません。ツールがあれば、世界と対話できます。
AIエージェントのアーキテクチャ
すべてのエージェントは同じ基本ループに従います。
┌─────────────────────────────────────────┐
│ エージェントループ │
│ │
│ 1. 目標を受け取る │
│ 2. 考える: 次に何をすべきか? │
│ 3. 行動する: ツールを選択して呼び出す │
│ 4. 観察する: 結果はどうだったか? │
│ 5. 判断する: 目標は達成されたか? │
│ → いいえ?ステップ2に戻る。 │
│ → はい?結果を返す。 │
└─────────────────────────────────────────┘
これはReActパターン(推論+行動)と呼ばれます。LangChain、CrewAI、AutoGen、OpenAI Agents SDKなど、すべてのエージェントフレームワークはこのループの何らかのバージョンを実装しています。
必要な3つのコンポーネント:
- 言語モデル — 推論エンジン(Claude、GPT-4o、Gemini)
- ツールセット — エージェントができること(検索、クロール、生成、保存、公開)
- オーケストレーター — 次にどのツールを呼び出すかを決定するループ
ステップ1: ツールを選ぶ
ツールはエージェントが達成できることを定義します。「エージェントは現実世界で何をする必要があるか?」という質問から始めましょう。
一般的なエージェントツール:
| 機能 | 重要な理由 |
|---|---|
| ウェブ検索 | 調査、事実確認、競合分析 |
| ウェブクローリング | 特定ページの深い読み取り、データ抽出 |
| 画像生成 | ビジュアル、図、アセットの作成 |
| ファイル保存 | 永続的な出力、共有、アセット管理 |
| ウェブ公開 | 完成した作業をライブページとして配信 |
| コード実行 | スクリプト実行、データ処理、自動化 |
初心者が最もよく犯すミス: エージェントにツールが少なすぎて、なぜ何も達成できないのか不思議に思うこと。検索のみのエージェントはリンクしか返せません。検索+クロール+保存+公開できるエージェントは、完成した成果物を生み出せます。
ツールをプロビジョニングする最もシンプルな方法: 検索、クロール、画像生成、保存、公開を1つのインターフェースの背後にバンドルした統合機能レイヤーを使用すること。5つの別々のAPIを設定し、5つの認証情報セットを管理する代わりに、エージェントは1つの認証フローで1つのCLIを呼び出すだけです。これにより、エージェントループはシンプルに保たれ、トークンオーバーヘッドも低くなります。
ステップ2: エージェントのシステムプロンプトを定義する
システムプロンプトはエージェントの「取扱説明書」です。モデルに自分が何者で、どんなツールを持ち、それらをどう使うべきかを伝えます。
良いシステムプロンプトには4つの部分があります:
- アイデンティティ: エージェントが何であるか
- 目標: 何を達成すべきか
- ツール: 何をいつ使えるか
- 制約: やってはいけないこと
例:
あなたはリサーチエージェントです。与えられたトピックを徹底的に調査し、
包括的なレポートを作成することが目標です。
以下のツールにアクセスできます:
- search: ウェブで情報を見つけます。広範な調査に使用します。
- crawl: 特定のウェブページを全文読み取ります。有望な情報源を
見つけた後に使用します。
- drive upload: レポートとアセットを永続的に保存します。
- page deploy: 最終レポートをウェブページとして公開します。
ワークフロー:
1. 全体像を理解するために広範な検索クエリから始めます。
2. 最も権威のある情報源を特定し、クロールします。
3. 調査結果を構造化されたレポートにまとめます。
4. 安全に保管するためにレポートをDriveにアップロードします。
5. レポートを公開ページとしてデプロイします。
制約:
- 常に情報源を引用してください。
- ある情報源が別の情報源と矛盾する場合は、さらに調査してください。
- 決して情報を捏造しないでください。
ステップ3: エージェントループを実装する
以下はPythonによる最小限のエージェントループです。このパターンは本番環境でそのまま使えます — 考え、行動し、観察し、繰り返す:
import subprocess
import json
def call_tool(tool_name, **params):
"""ツールを実行して結果を返します。"""
if tool_name == "search":
result = subprocess.run(
["anycap", "search", "--prompt", params["query"]],
capture_output=True, text=True
)
return json.loads(result.stdout)
elif tool_name == "crawl":
result = subprocess.run(
["anycap", "crawl", params["url"]],
capture_output=True, text=True
)
return result.stdout
elif tool_name == "drive_upload":
subprocess.run(
["anycap", "drive", "upload", params["file"]],
capture_output=True
)
return {"status": "uploaded", "file": params["file"]}
elif tool_name == "page_deploy":
result = subprocess.run(
["anycap", "page", "deploy", params["file"]],
capture_output=True, text=True
)
return json.loads(result.stdout)
# エージェントループ
def agent_loop(goal, tools, max_steps=20):
memory = [{"role": "system", "content": SYSTEM_PROMPT}]
memory.append({"role": "user", "content": goal})
for step in range(max_steps):
response = llm_call(memory, tools)
if response.get("done"):
return response["result"]
tool_name = response["tool"]
tool_params = response["params"]
result = call_tool(tool_name, **tool_params)
memory.append({"role": "assistant", "content": str(response)})
memory.append({"role": "tool", "content": str(result)})
return "エージェントが目標を完了せずに最大ステップ数に達しました。"
ステップ4: 失敗を処理する
エージェントは失敗します。重要なのはその対処法です。以下の安全策を最初から組み込んでください:
タイムアウト保護
エージェントを無限にループさせないでください。最大ステップ数と時間制限を設定します。エージェントがいずれかを超えた場合、静かにクラッシュするのではなく、それまでに得た結果を返すべきです。
ツール失敗時の回復
ツール呼び出しが失敗した場合 — URLに到達できない、APIがエラーを返す — エージェントはエラーメッセージを受け取り、次に何をすべきか判断すべきです。エージェントからエラーを隠さないでください。何かがうまくいかなかったことを知る必要があります。
try:
result = call_tool(tool_name, **tool_params)
except Exception as e:
result = {"error": str(e), "suggestion": "別のアプローチを試してください"}
コスト意識
すべての検索、すべてのクロール、すべての画像生成にはクレジットがかかります。エージェントに予算を与え、コストを意識させてください。簡単な質問に答えるために100回の検索を消費するエージェントは、設計が悪いと言えます。
ステップ5: デモと本番の違い
デモエージェントと有用なエージェントの違いは現実世界のツールアクセスです。デモエージェントはテキストを返します。有用なエージェントは公開されたレポート、生成された画像、デプロイされたウェブページを返します。
本番エージェントには5つの能力が必要です: ウェブ検索、特定ページの読み取り、ビジュアル生成、出力の永続的保存、完成した作業の公開。エージェントのコードはシンプルに保たれます — 必要なツールを呼び出すだけです。API統合、認証、エラー処理の複雑さはランタイムにあり、エージェントループにはありません。
エージェント構築時のよくあるミス
ミス1: 終了条件がない
明確な「完了」シグナルのないエージェントは永遠にループします。成功を明示的に定義してください: エージェントは特定の出力(レポート、デプロイされたページ)を生成したとき、または目標が到達不可能であることを確認したときに完了です。
ミス2: ツールが少なすぎる
「検索のみ」のエージェントは、ただの検索エンジンに過ぎません。エージェントに完全なパイプラインを与えてください: 見つける → 読む → 作る → 保存する → 届ける。
ミス3: ツール結果を無視する
エージェントは時にツールを呼び出して出力を無視し、結果がどうだったかを想定して進めてしまいます。すべてのツール結果を次の判断に必ず組み込むように強制してください。
ミス4: ループの過剰設計
ほとんどのユースケースでは、カスタムオーケストレーションフレームワークは必要ありません。良いシステムプロンプトと有能なツールを備えたシンプルなReActループが、タスクの80%で複雑なマルチエージェント構成を上回ります。
チュートリアルから本番へ
ここで構築したエージェントは出発点です。本番-readyにするために:
- ログを追加: デバッグのために、すべてのツール呼び出し、その結果、エージェントの推論を記録します。
- ヒューマンインザループを追加: 公開やメール送信などの高リスクなアクションには、人間の承認を必要とします。
- モニタリングを追加: 成功率、タスクあたりの平均ステップ数、ツール呼び出しの分布を追跡し、ボトルネックを特定します。
- システムプロンプトを反復改善: プロンプトはエージェントの頭脳です。実際の使用パターンに基づいて調整します。
AIエージェントの構築は複雑なアーキテクチャが目的ではありません。推論エンジンに適切なツールと明確な目標を与えることです。シンプルに始めましょう: 1つのモデル、3〜5のツール、基本ループ。シンプルなバージョンが破綻したときに初めて、複雑さを追加してください。