LLMを利用したアプリケーションは、ここ数年で単純な「質問 → 回答」の仕組みから、自分で必要な処理を判断し、外部システムを操作するAI Agentへと進化しています。

従来のLLMアプリケーションであれば、基本的な流れは次のようなものでした。
User
↓
LLM
↓
Answer
一方、AI Agentでは処理が大きく変わります。
User
↓
Agent
↓
LLM
↓
Planning
↓
Skill / Tool Selection
↓
MCP / Tool Calling
↓
External System
↓
Result Validation
↓
LLM
↓
Final Answer
たとえばユーザーから、
今月の売上データを確認して、先月と比較し、問題があればSlackで担当者に通知して
と依頼された場合、LLMが文章を生成するだけでは処理できません。
AI Agentは、
- ユーザーの目的を理解する
- タスクを分解する
- DBから売上データを取得する
- 数値を比較する
- 異常を判断する
- Slack APIを実行する
- 実行結果を確認する
- ユーザーへ結果を報告する
という一連の処理を管理します。
本記事では、AI Agentがユーザーの入力を受け取ってから最終回答を返すまでを、20ステップの実行フローとして整理します。
AI Agentの全体像
AI Agentを理解するうえで、まず次の6つの要素を分けて考えると分かりやすくなります。
| コンポーネント | 主な役割 |
|---|---|
| User | AI Agentへ依頼を送る |
| Agent | 処理全体を制御する |
| Agent Skills | 特定タスクの知識・ルール・実行手順 |
| LLM | 意図理解、推論、計画、文章生成 |
| MCP | Agentと外部Toolを接続する仕組み |
| Tools | API、DB、検索、ファイル操作などを実行 |
重要なのは、
Agent ≠ LLM
という点です。
LLMはAgentを構成する重要な部品ですが、Agentそのものではありません。
イメージとしては、
Agent
├── LLM
├── Memory
├── Skills
├── Tools
├── Planning
├── State
└── Execution Control
となります。
Agentはこれらをまとめるオーケストレーターです。
AI Agentの20ステップ
Step 1. ユーザーが質問・依頼を送る
処理の起点はユーザーです。
東京の今日の天気を調べて、
雨なら傘を持っていくべきか教えて
この時点では、Agentは単なる自然言語としてリクエストを受け取っています。
Step 2. Agentがリクエストを受信する
Agentはユーザーからのリクエストを受け取り、Agent Runを開始します。
内部的には、たとえば次のような情報を保持します。
{
"user_id": 1001,
"message": "東京の今日の天気を調べて",
"session_id": "abc123"
}
ここからAgentが処理全体をコントロールしていきます。
Step 3. 会話履歴・Memoryを取得する
Agentは必要に応じて、過去の情報を参照します。
たとえば、
User:
温度は摂氏で表示して
User:
今後も日本語で答えて
という過去の会話があれば、
language = ja
temperature_unit = celsius
というコンテキストとして利用できます。
一般的には次のような情報がAgent Contextに含まれます。
Conversation History
User Preference
Session State
Long-term Memory
Application Context
ただし、すべての過去情報をLLMに送ればよいわけではありません。
コンテキストが増えすぎると、
- トークンコスト増加
- レイテンシ増加
- 不要な情報による判断精度低下
につながるため、必要な情報だけを取得する設計が重要です。
Step 4. LLMがユーザーの意図を理解する
次にLLMがユーザーの依頼を解析します。
たとえば、
東京の今日の天気を調べて、
雨なら傘を持っていくべきか教えて
という入力なら、
intent:
get_weather
location:
Tokyo
date:
today
condition:
if_rain_recommend_umbrella
requires_external_data:
true
のような構造へ変換できます。
つまり自然言語を、
実行可能なタスク
へ変換する処理です。
Step 5. LLMが実行計画を作成する
複雑な依頼の場合、すぐToolを実行するのではなく、まず処理手順を考えます。
これを一般に、
Planning
と呼びます。
たとえば、
1. 東京の天気情報を取得
2. 降水確率を確認
3. 雨の可能性を判定
4. 傘が必要か判断
5. 回答を生成
という計画です。
より複雑なAgentでは、
Plan
↓
Execute
↓
Observe
↓
Re-plan
を繰り返します。
Step 6. Agentが実行計画を受け取る
LLMが作成した計画をAgentが実行対象として保持します。
ここで役割を整理すると、
LLM
↓
何をすればよいか考える
Agent
↓
実際にそれを実行・管理する
という関係になります。
Step 7. 外部Toolが必要か判断する
Agentは、LLMだけで回答できるのか、外部情報が必要なのかを判断します。
たとえば、
Pythonのlistとtupleの違いは?
ならLLMだけでも回答できます。
一方、
現在のUSD/JPYはいくら?
では最新情報が必要です。
そのため、
外部Toolが必要
と判断されます。
この判断はAgent設計において非常に重要です。
不用意にToolを呼び出すと、
APIコスト
レイテンシ
障害ポイント
セキュリティリスク
が増加します。
Step 8. 適切なSkillを選択する
次に、Agentが利用するSkillを決定します。
たとえば、
Weather Skill
Database Skill
GitHub Skill
Slack Skill
PDF Skill
Deployment Skill
などです。
Skillは単なる関数とは限りません。
一般的には、
実行ルール
専門知識
利用可能Tool
パラメータ生成方法
エラー処理
出力形式
などをまとめたものとして設計できます。
Step 9. Skillが必要なコンテキストを取得する
選択されたSkillは、実行に必要な情報を準備します。
Weather Skillなら、
location: Tokyo
date: today
unit: celsius
language: ja
GitHub Skillなら、
repository: company/backend
branch: develop
issue_number: 123
などです。
つまり、
User Context
+
Agent Context
+
Skill Context
を組み合わせてTool実行に必要な情報を作ります。
Step 10. SkillがTool Callを組み立てる
自然言語のままではAPIを実行できません。
そこでToolの仕様に合わせて、構造化されたパラメータへ変換します。
たとえば、
{
"location": "Tokyo",
"date": "2026-09-13",
"unit": "celsius"
}
です。
Skillは、
自然言語
↓
構造化データ
をつなぐ役割も担います。
Step 11. LLMがパラメータを補完する
すべてのパラメータがユーザーから直接指定されるとは限りません。
たとえば、
今日の東京の天気
だけなら、
{
"location": "Tokyo",
"date": "today"
}
と推論できます。
ただし、この補完処理では注意が必要です。
たとえば、
DBのデータ全部消して
という操作で、
database = production
を勝手に推測する設計は危険です。
重要な操作では、
推論してよい値
と
確認が必要な値
を分ける必要があります。
Step 12. AgentがSkillを実行する
必要な情報が揃ったら、AgentがSkillを実行します。
概念的には、
result = await skill.execute(
context=context,
parameters=parameters,
)
のような処理になります。
ここから外部システムへのアクセスが始まります。
Step 13. MCP経由で利用可能なToolを選択する
外部Toolとの接続にMCPを利用する構成では、AgentまたはSkillがMCP経由でToolを利用します。
MCPは、
Model Context Protocol
の略です。
概念的には、
Agent
↓
MCP Client
↓
MCP Server
↓
Tools
という構成になります。
MCP Serverが提供するToolとして、
search_documents
get_customer
create_github_issue
send_slack_message
query_database
read_file
などを公開できます。
なお、すべてのAI AgentがMCPを必要とするわけではありません。
普通のREST APIやFunction Callingで直接Toolを実行する構成も十分可能です。
MCPはTool接続方法の一つと考えるのが適切です。
Step 14. MCPが具体的なToolを実行する
Agentから、
get_weather
というTool Callが送られたとします。
MCP Serverは内部で、
Weather API
を呼び出します。
概念的には、
Agent
↓
MCP Client
↓
MCP Server
↓
Weather Tool
↓
Weather API
となります。
Agent側がAPI固有の詳細をすべて意識しなくてもよいことがポイントです。
Step 15. 外部Toolが実際の処理を行う
Toolは現実世界のデータやシステムにアクセスします。
たとえば、
API
Database
Filesystem
GitHub
Slack
AWS
GCP
Browser
Search Engine
などです。
天気Toolなら、
{
"city": "Tokyo",
"weather": "rain",
"temperature": 23,
"precipitation_probability": 80
}
というデータを取得できます。
AI Agentの大きな特徴はここにあります。
LLM単体では、
文章を生成する
ことが中心です。
Toolを組み合わせると、
調べる
作る
保存する
送る
変更する
実行する
ことが可能になります。
Step 16. Toolの実行結果を受け取る
外部処理が完了すると、結果がAgent側へ返されます。
ただし、Tool結果をそのままユーザーへ返すとは限りません。
APIレスポンスには、
{
"status": 200,
"data": {
"precipitation": 80
},
"request_id": "XYZ123",
"latency": 420
}
のように、ユーザーには不要な情報も含まれるからです。
Step 17. Skillが結果を解析・検証する
SkillはToolの結果を検証します。
たとえば、
HTTP Statusは正常か
必要なデータが存在するか
値が想定範囲内か
レスポンス形式が正しいか
などを確認します。
実運用では、ここが非常に重要です。
Toolが成功したように見えても、
{
"status": "success",
"data": null
}
というケースもあるからです。
Validationの例
def validate_weather_result(result):
if result is None:
raise ValueError("Weather result is empty")
if "precipitation_probability" not in result:
raise ValueError("Missing precipitation probability")
probability = result["precipitation_probability"]
if not 0 <= probability <= 100:
raise ValueError("Invalid precipitation probability")
return result
Agent開発では、
Toolを呼べることよりも、Tool結果を正しく扱えること
のほうが重要になるケースも多くあります。
Step 18. Agentが結果とコンテキストを統合する
Toolから取得した情報を、元のユーザーリクエストと結合します。
たとえば、
User Request:
今日の東京の天気を調べて、
雨なら傘を持っていくべきか教えて
Tool Result:
雨
降水確率80%
User Preference:
日本語
これらを統合し、
最終回答を生成するためのContext
を構築します。
Step 19. LLMが最終回答を生成する
統合された情報をLLMへ渡します。
LLMは人間が読みやすい自然言語へ変換します。
例えば、
今日の東京は雨の予報で、
降水確率は80%です。
外出する場合は、傘を持っていくことをおすすめします。
となります。
ここで重要なのは、回答の根拠が
LLM内部知識だけではなく
実際に取得したTool結果
になっている点です。
Step 20. Agentがユーザーへ結果を返す
最後にAgentが回答を返します。
Tool Result
↓
Skill Validation
↓
Agent Context
↓
LLM
↓
Final Answer
↓
User
これで一連のAgent Runが完了します。
Sequence Diagramで見る全体フロー
全体をMermaidで表現すると、次のようになります。
Agent・LLM・Skill・MCP・Toolの違い
このあたりは特に混同されやすい部分です。
LLM
LLMは、
理解
推論
分類
計画
要約
文章生成
などを担当します。
つまり、頭脳に近い部分です。
Agent
Agentは、
LLMを呼び出す
Toolを選択する
処理順序を制御する
状態を管理する
再実行する
エラーを処理する
などを担当します。
つまり、実行責任を持つ制御層です。
Skill
Skillは、
特定タスクをどう実行するか
を定義するレイヤーです。
たとえば、
GitHub Pull Request Review Skill
なら、
1. PR情報を取得
2. Diffを取得
3. コードを解析
4. 問題を分類
5. コメントを作成
といった処理ルールを持たせられます。
MCP
MCPは、
Agent / LLM
↓
外部システム
の接続を整理するためのプロトコルです。
MCPそのものがAI Agentではありません。
またMCP自体が処理の目的を判断するわけでもありません。
Tool
Toolは実際に処理をします。
例えば、
SELECT
INSERT
HTTP Request
GitHub Issue作成
Slack送信
ファイル読み込み
Web検索
などです。
よくある誤解
「Agent = LLM」ではない
よくある構成として、
response = llm(prompt)
があります。
これはLLMアプリケーションですが、必ずしもAgentとは言えません。
Agentらしい構成では、
判断
↓
計画
↓
実行
↓
観測
↓
再判断
が行われます。
ReAct型Agent
代表的なAgentの考え方として、
Reason
Act
Observe
を繰り返すReActがあります。
イメージとしては、
Thought:
現在の天気を知らない
Action:
weather APIを呼ぶ
Observation:
東京 雨 降水確率80%
Thought:
傘を勧めるべき
Answer:
今日は傘を持っていくことをおすすめします
となります。
実際のプロダクトでは内部推論そのものを表示する必要はありませんが、
判断
↓
Tool実行
↓
結果確認
↓
次の判断
という設計思想は非常に重要です。
Agentは必ず1回だけToolを呼ぶわけではない
現実のタスクでは複数Toolを利用します。
例えば、
GitHubのIssueを調べて、関連するSlackの議論も確認して、対応方針をまとめて
という依頼なら、
GitHub Tool
↓
Issue取得
Slack Tool
↓
関連メッセージ検索
LLM
↓
情報を整理
Agent
↓
不足情報を判断
GitHub Tool
↓
PR取得
LLM
↓
最終回答
という動きになります。
したがって実際のAgentは、
LLM → Tool → LLM
という単純な構造ではなく、
while task_not_finished:
reason()
select_tool()
execute_tool()
observe()
update_state()
というループに近くなります。
擬似コードで見るAgent Loop
async def run_agent(user_input):
context = load_context(user_input)
for _ in range(MAX_STEPS):
decision = await llm.decide(
user_input=user_input,
context=context,
)
if decision.type == "final_answer":
return decision.answer
if decision.type == "tool_call":
tool = tool_registry.get(decision.tool_name)
result = await tool.execute(
**decision.arguments
)
validated_result = validate(result)
context.append({
"tool": decision.tool_name,
"result": validated_result,
})
raise RuntimeError("Maximum Agent steps exceeded")
ここで重要なのが、
MAX_STEPS
です。
Agentに無制限にToolを実行させると、
無限ループ
API課金増大
外部サービスへの大量アクセス
誤操作
につながる可能性があります。
本番環境で必要になる設計
Agentを実際の業務システムへ導入する場合、LLMの精度だけ考えていてはいけません。
1. Tool Permission
Toolごとに権限を分けます。
read_database
write_database
delete_database
send_email
create_issue
deploy_production
特に、
DELETE
UPDATE
SEND
DEPLOY
PURCHASE
のような副作用のある操作は注意が必要です。
2. Human in the Loop
重要操作では人間による承認を挟みます。
例えば、
AI:
本番DBのレコードを12件更新します。
実行しますか?
[実行]
[キャンセル]
のような設計です。
Agentだからといって、すべて自律実行させる必要はありません。
3. Idempotency
Agentは同じToolを再実行する可能性があります。
たとえば、
Slack送信
を再実行すると、
同じメッセージが2回送信される
可能性があります。
そのため、
idempotency_key
などを利用した設計が重要です。
4. Timeout
Toolが永遠に返ってこない可能性もあります。
result = await asyncio.wait_for(
tool.execute(),
timeout=10,
)
AgentシステムにはTool Timeoutを必ず用意した方が安全です。
5. Retry
一時的なネットワーク障害などに備えます。
Retry 1
↓
Retry 2
↓
Retry 3
↓
Failure
ただし更新系APIでは無条件Retryすると危険です。
6. Observability
Agentでは通常のWebアプリ以上にログ設計が重要です。
最低限、
Agent Run ID
User Request
LLM Model
Prompt Tokens
Completion Tokens
Selected Tool
Tool Arguments
Tool Result
Latency
Error
Final Response
などを記録すると調査しやすくなります。
Agent Traceの例
{
"run_id": "run_001",
"steps": [
{
"type": "llm",
"action": "analyze_request",
"latency_ms": 850
},
{
"type": "tool",
"name": "get_weather",
"latency_ms": 420
},
{
"type": "llm",
"action": "generate_answer",
"latency_ms": 720
}
],
"total_latency_ms": 1990
}
これがないと、
Agentが遅い
という問い合わせに対して、
LLMが遅いのか
Toolが遅いのか
MCPが遅いのか
DBが遅いのか
を判断できません。
Agentの実行状態を持つ
複雑なAgentでは、現在の状態を明示的に管理すると扱いやすくなります。
class AgentState:
user_input: str
current_step: int
plan: list
tool_results: list
messages: list
status: str
例えば、
RECEIVED
↓
PLANNING
↓
EXECUTING
↓
WAITING_TOOL
↓
VALIDATING
↓
GENERATING
↓
COMPLETED
といったState Machineとして設計できます。
AI Agentアーキテクチャの例
本番では次のような構成が考えられます。
┌──────────────┐
│ User │
└──────┬───────┘
│
▼
┌─────────────────┐
│ Agent API │
│ FastAPI/Laravel │
└────────┬────────┘
│
┌───────────┴────────────┐
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ LLM │ │ Memory │
└──────┬───────┘ │ Redis / DB │
│ └──────────────┘
▼
┌──────────────┐
│ Agent Skills │
└──────┬───────┘
│
▼
┌──────────────┐
│ MCP Client │
└──────┬───────┘
│
┌─────┼──────────────┐
│ │ │
▼ ▼ ▼
GitHub Slack Database
Agentを設計するときに重要な考え方
AI Agentを作る場合、
とりあえず使えるToolを全部LLMに渡す
という設計はあまりおすすめできません。
Toolが100個あれば、
LLMがToolを選びづらい
Promptが大きくなる
誤選択が増える
セキュリティ範囲が広がる
ためです。
より良い設計は、
User Request
↓
Routing
↓
Skill
↓
必要なToolだけ公開
です。
例えば、
Developer Agent
├── GitHub Skill
├── CI Skill
└── Deployment Skill
Customer Support Agent
├── Customer Skill
├── Order Skill
└── Mail Skill
のように責務を分けます。
Multi-Agentという選択肢
さらに複雑になると、1つのAgentにすべてを担当させず、複数Agentへ分割できます。
Manager Agent
│
├── Research Agent
├── Coding Agent
├── Database Agent
└── Review Agent
Manager Agentが、
どのAgentに何を任せるか
を判断する形です。
ただしMulti-Agent化すると、
コスト
レイテンシ
障害ポイント
デバッグ難易度
も増えます。
最初からMulti-Agentにするのではなく、
Single Agent
↓
Skills
↓
Tools
から始め、必要になったところで分割するのが現実的です。
Agent開発で重要なのは「賢さ」より「制御」
AI Agentというと、
どれだけ賢いLLMを使うか
に注目しがちです。
しかし本番システムでは、それ以上に、
どのToolを許可するか
最大何ステップ動くか
エラー時にどうするか
Tool結果をどう検証するか
いつ人間へ確認するか
どの処理をログに残すか
が重要になります。
言い換えると、
良いAI Agentとは「何でもできるAI」ではなく、「許可された範囲で安全かつ確実に仕事を完了できるシステム」
と考えた方が実務的です。
まとめ
AI Agentの実行全体フローを簡略化すると、次のようになります。
User
↓
Agent
↓
Context / Memory
↓
LLM Intent Analysis
↓
Planning
↓
Skill Selection
↓
Tool Selection
↓
MCP / Tool Calling
↓
External System
↓
Validation
↓
Context Integration
↓
LLM
↓
Final Answer
↓
User
各コンポーネントの役割は、
| コンポーネント | 役割 |
|---|---|
| Agent | 全体制御 |
| LLM | 理解・推論・計画・文章生成 |
| Memory | 過去情報の保持 |
| Skill | 専門的な実行ロジック |
| MCP | Tool接続を整理するプロトコル |
| Tool | 実際の外部処理 |
| Validation | Tool結果の検証 |
| Observability | Agent実行の監視 |
と整理できます。
これまでのLLMアプリケーションが、
質問に回答するAI
だったとすれば、AI Agentは、
目的を理解し
↓
計画を立て
↓
必要な情報を調べ
↓
外部システムを操作し
↓
結果を確認し
↓
仕事を完了するAI
と言えます。
今後AI Agentを本番システムへ組み込む際は、単にTool Callingを実装するだけでなく、
Planning、Skill設計、Tool権限、Validation、Human-in-the-Loop、Observabilityまで含めて1つのシステムとして設計することが重要になるでしょう。