第十三章 Agent与工具调用¶
导读¶
LLM 本身只能"说话",不能"做事"。Agent = LLM + 工具调用 + 循环——让模型能查数据库、调 API、执行代码、操作浏览器。本章解释 Agent 的核心范式(ReAct、Function Calling、Plan-Execute)、记忆系统、多 Agent 协作、失败模式。
13.1 从对话到行动¶
单纯的 LLM 对话限制明显:
- 知识截止;
- 不能算精确数学(只能续写数字);
- 不能访问实时数据;
- 不能执行业务操作(下单、查库)。
Agent 思路:让 LLM 决定**调用什么工具**,把工具结果反馈给它,循环直到完成任务。
[用户问题] →
[LLM 思考:我需要查天气] →
[调用 weather_api(date="今天")] →
[工具返回:{rain_mm: 12}] →
[LLM 思考:现在可以回答了] →
[输出:今天降雨 12 毫米]
这就是 ReAct(Reasoning + Acting)的核心循环。
13.2 ReAct 范式¶
# 伪代码
state = {"question": "...", "history": []}
for step in range(max_steps):
thought, action = llm.react(state)
if action == "finish":
return llm.final_answer(state)
observation = tools[action.name](**action.args)
state["history"].append((thought, action, observation))
ReAct 的 prompt 模板(简化):
Question: {question}
Thought 1: I need to ...
Action 1: search[{query}]
Observation 1: ...
Thought 2: Based on ..., I should ...
Action 2: calculator[{expr}]
Observation 2: ...
...
Thought N: I now know the answer
Final Answer: ...
优点:可解释(thought 可见)、可调试、灵活。
缺点:每步都是 LLM 调用 → 慢且贵;thought 占 token;易陷入循环。
13.3 Function Calling:结构化替代¶
现代 LLM(GPT-4、Claude、Llama-3 等)原生支持 Function Calling:
# 定义工具
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
"date": {"type": "string", "format": "date"}
},
"required": ["city"]
}
}
}]
# 调用
response = llm.chat(messages=[...], tools=tools)
if response.tool_calls:
for call in response.tool_calls:
result = execute_tool(call)
messages.append({"role": "tool", "content": result})
相比 ReAct 文本的优势:
- 结构化输出,参数 schema 校验;
- token 省(不输出 thought);
- 主流模型经过专门训练,更稳定;
- 可并行调用多个工具。
但失去 thought 的可解释性——可让模型显式输出 thought 字段补回。
OpenAI / Anthropic / Llama 的工具调用格式略有不同,但 API 抽象一致。底层原理是模型训练时引入特殊 token + JSON 格式描述工具调用,推理时引擎解析这些 token 为结构化调用,配合 JSON Schema 做参数校验。
13.4 工具类型¶
| 类型 | 例子 | 难点 |
|---|---|---|
| 检索 | RAG、搜索引擎 | 召回质量 |
| API | REST、GraphQL | 鉴权、错误处理 |
| 代码执行 | Python、SQL | 沙箱、安全 |
| 数据库 | 查询、写入 | SQL 注入、权限 |
| 文件 | 读写、编辑 | 路径安全 |
| 浏览器 | 网页操作 | 元素定位、稳定性 |
| 操作系统 | 命令执行 | 沙箱隔离 |
| 子 Agent | 调用其他 LLM | 上下文传递 |
13.5 记忆系统¶
LLM 上下文有限,Agent 需要记忆系统:
短期记忆¶
- 当前对话上下文;
- 工具调用历史;
- 受 max_seq_len 约束。
长期记忆¶
| 方法 | 思路 |
|---|---|
| 向量库 RAG | 把过往交互 chunk + embedding,按需召回 |
| KV Cache 重写 | 把长历史压缩成几个 token 的 KV |
| 摘要树 | 层级摘要,顶层 + 细节 |
| 知识图谱 | 提取实体关系,结构化存储 |
| 数据库 | 显式存表,Agent 用 SQL 查 |
MemGPT 思路:仿 OS 虚拟内存——主存(context)+ 辅存(向量库),自动 page in/out。
13.6 规划与反思¶
| 范式 | 说明 |
|---|---|
| Plan-and-Execute | 先制定完整计划,再分步执行 |
| ReAct | 边想边做,逐步推进 |
| Reflexion | 失败后反思,更新策略重试 |
| Tree of Thoughts | 探索多条思路,树搜索 |
| Self-Consistency | 多次采样投票 |
适用场景:
- 简单工具调用 → Function Calling 直接做;
- 多步任务 → ReAct / Plan-Execute;
- 难题(数学、推理)→ Tree of Thoughts;
- 长任务 + 失败可能 → Reflexion。
13.7 多 Agent 协作¶
复杂任务可拆给多个 Agent:
| 模式 | 例子 |
|---|---|
| Supervisor + workers | 主 Agent 分派给多个子 Agent |
| Sequential pipeline | Agent A → B → C 串行 |
| Debate | 多 Agent 辩论后由裁判综合 |
| Hierarchical | 树状层级 |
框架:
- LangGraph:基于图的 Agent 编排,主流;
- CrewAI:角色化多 Agent;
- AutoGen(Microsoft):对话式多 Agent;
- OpenAI Swarm:轻量级 handoff 模式;
- Anthropic MCP(Model Context Protocol):标准化工具协议。
13.8 MCP:工具协议标准化¶
2024 年 Anthropic 推出 Model Context Protocol:
- 统一工具描述与调用协议;
- 服务端实现工具,客户端(任意 LLM)通过协议调用;
- 类比"AI 时代的 USB-C"——一次实现,多模型可用。
# MCP server 暴露工具
@mcp.tool()
def search_db(query: str) -> str:
return db.search(query)
# 任意 MCP client(Claude / GPT / Llama)可调用
正在快速成为 Agent 工具生态的标准。
13.9 Agent 失败模式¶
| 失败 | 表现 | 对策 |
|---|---|---|
| 循环 | 反复调同一工具 | 步数上限 + 检测重复 |
| 幻觉工具 | 调不存在的工具 | 严格 schema + 拒绝 |
| 参数错误 | 类型 / 字段错 | schema 校验 + 重试 |
| 上下文爆炸 | 历史累积超窗口 | 摘要压缩 + 分 Agent |
| 错误传播 | 一步错,步步错 | 中间检查 + 反思 |
| 成本爆炸 | 多步 × 大模型 | 小模型做规划,大模型做关键步 |
| 安全 | 工具被滥用 | 沙箱 + 权限 + 人审 |
13.10 工程实现¶
# 简化版 Agent loop
state = {"messages": [{"role": "user", "content": question}]}
for step in range(max_steps):
response = llm.chat(messages=state["messages"], tools=TOOLS)
if response.tool_calls:
for call in response.tool_calls:
result = execute_tool(call)
state["messages"].append({
"role": "tool",
"tool_call_id": call.id,
"content": result
})
else:
# 模型给出最终答案
return response.content
return "达到最大步数"
工程考量:
- 超时与步数上限:避免死循环;
- 流式输出:让用户看到 thought 与 action;
- 错误恢复:工具失败时让模型决定重试或换策略;
- 审计日志:每步 thought/action/observation 都记;
- 人工 in the loop:高风险操作(写数据库、转账)要人审。
13.11 评测¶
Agent 评测比单轮 LLM 难:
- 任务成功率:最终目标是否达成;
- 步数效率:越少步越好;
- 成本:token 消耗;
- 工具调用准确率:参数正确性;
- 轨迹质量:是否合理(人评)。
基准:
- SWE-Bench:软件工程任务;
- WebArena:网页操作;
- ToolBench / API-Bank:API 调用;
- GAIA:通用 Agent;
- τ-bench:实际业务场景模拟。
工程实战要点¶
- Function Calling 优于 ReAct:结构化、稳定、token 省;
- 步数上限必设:避免死循环烧钱;
- 小模型做规划:降低成本;
- 沙箱隔离:代码执行 / OS 命令必沙箱;
- 审计 + 人审:高风险操作不能全自动;
- MCP 是趋势:让工具一次实现多模型用;
- 多 Agent 不是越多越好:通信开销大,简化优先;
- Agent 评测难:任务成功率 + 成本 + 步数三维。
小结¶
- Agent = LLM + 工具循环(Thought → Action → Observation);
- ReAct 是经典范式,Function Calling 是现代标准;
- 工具类型:检索 / API / 代码 / 数据库 / 浏览器 / OS / 子 Agent;
- 记忆系统:短期上下文 + 长期向量库 / 摘要 / 知识图谱;
- 规划范式:ReAct / Plan-Execute / Reflexion / Tree of Thoughts;
- 多 Agent 协作:supervisor / pipeline / debate / hierarchical;
- MCP 是工具协议标准化趋势;
- 失败模式:循环、幻觉工具、参数错、上下文爆炸、错误传播、成本爆炸、安全;
- 工程要点:步数上限、沙箱、审计、人审、小模型规划。
练习题¶
- 解释 Agent 与单轮 LLM 调用的核心区别。
- ReAct 与 Function Calling 的优劣对比?
- Agent 的长期记忆有哪几种实现方式?
- Plan-and-Execute 与 ReAct 适合什么不同场景?
- 多 Agent 协作的 4 种典型模式是什么?
- MCP 解决了什么问题?
- Agent "循环"失败模式如何检测与处理?
- 高风险工具调用(如转账)应该如何工程化?
下一章:第十四章 评估与安全