前言
Chatbot 只会聊天,Agent 会调用工具、拆解任务、自己纠错。这一波 AI 应用落地的核心就是 Agent。这篇不讲虚的,讲清楚
Agent 的循环结构、Function Calling 的机制和工程上必须处理的问题。
一、Agent 的组成
一个 Agent 通常包含四部分:
表格
| 组件 | 作用 |
|---|---|
| LLM(大脑) | 理解任务、决策下一步 |
| Tools(工具) | 搜索、执行代码、查数据库、发请求 |
| Memory(记忆) | 短期上下文 + 长期知识 |
| Planning(规划) | 任务拆解、反思、调整策略 |
和普通 workflow 的区别:workflow 是固定流程,Agent 是模型自己决定下一步做什么。
二、核心循环:ReAct
ReAct = Reason(推理)+ Act(行动),是绝大多数 Agent 的基础模式:
循环:
- Thought:模型思考当前该做什么
- Action:调用某个工具,给出参数
- Observation:拿到工具返回结果
- 重复以上,直到模型认为任务完成
伪代码:
def run_agent(task, tools, max_steps=10): messages = [{"role": "user", "content": task}] for _ in range(max_steps): resp = llm.chat(messages, tools=tools) # 模型决定行动 if not resp.tool_calls: # 不再调工具 = 给答案了 return resp.content for call in resp.tool_calls: result = execute(call.name, call.arguments) # 宿主执行 messages.append({"role": "tool", "content": result, "tool_call_id": call.id}) return "达到最大步数,任务未完成"三、Function Calling:模型不执行,只「申请」
这是最容易误解的一点:
- 你在请求里提供工具列表(名称、描述、JSON Schema 参数)
- 模型判断需要工具时,返回结构化的 tool_calls—— 只是申请,不执行
- 你的代码真正执行工具
- 把结果以 role: tool 的消息回填给模型
- 模型基于结果继续
工具定义示例:
{ "name": "get_weather", "description": "查询指定城市的当前天气", "parameters": { "type": "object", "properties": { "city": {"type": "string", "description": "城市名,如 杭州"} }, "required": ["city"] } }安全边界在于:执行权始终在宿主程序手里,模型只能提请求。这决定了权限控制、沙箱、人工确认都放在宿主侧。
四、工具设计原则(决定 Agent 成功率)
工具写得好不好,比模型选哪个更影响效果:
- 单一职责:一个工具只做一件事,别搞「万能执行器」
- 描述写清楚:模型靠 description 选工具,写清什么场景用、参数含义、返回什么
- 参数少而必填明确:参数越多模型越容易传错
- 错误信息对模型友好:返回「city 不能为空,请提供城市名」而不是 KeyError
- 工具幂等:模型可能重复调用,删除 / 支付类操作必须防重
- 控制返回体积:工具返回几千行内容会撑爆上下文,只回摘要
五、记忆机制
表格
| 类型 | 实现 | 用途 |
|---|---|---|
| 短期记忆 | 对话 messages 列表(受上下文窗口限制) | 当前任务状态 |
| 长期记忆 | 向量库检索历史 / 知识 | 跨会话记住用户偏好 |
| 上下文压缩 | 让 LLM 总结旧对话,替换原文 | 长任务防止超窗口 |
工程重点:上下文不是越多越好,塞满后模型注意力会稀释,主动摘要比无脑拼接更有效。
六、规划与反思
- Plan-and-Execute:先让模型出完整计划,再逐步执行 —— 适合步骤明确的长任务
- ReAct:边想边做 —— 适合探索型任务
- Reflection(反思):执行失败后让模型检查「哪里错了、怎么改」,再重试一次,能明显提升成功率,成本是 token 翻倍
七、可靠性工程(面试加分项)
Agent 最大的问题是不稳定,工程上必须兜底:
- 最大步数限制:防止死循环烧钱(设 max_steps)
- 超时与重试:每次工具调用设 timeout,失败有限次重试
- 人工确认(Human-in-the-loop):高风险操作(转账、删数据)必须人工确认
- 权限最小化:工具只开必要权限,代码执行放沙箱
- 全链路 trace:记录每步的 thought/action/observation,否则出问题无法排查
- 成本控制:统计 token 消耗,长任务考虑换小模型做简单判断
八、怎么评估一个 Agent
表格
| 指标 | 含义 |
|---|---|
| 任务成功率 | 端到端完成比例(最重要) |
| 平均步数 | 步数越多越慢越贵 |
| 工具调用准确率 | 选对工具、传对参数的比例 |
| 单任务成本 | token 消耗 |
没有评测集就没法优化 —— 和 RAG 一样,先量化。
九、常见坑
- 工具描述含糊,模型乱选工具
- 工具返回超长文本,几轮后上下文爆掉
- 没有最大步数,陷入「调工具→失败→再调」死循环
- 让模型直接执行危险操作,没有人工确认
- 只测「正常路径」,异常分支(工具报错、返回空)没兜底
- 模型说「已完成」但实际没完成,缺少结果校验
十、总结与学习路线
记住三层:循环(ReAct)→ 工具(Function Calling + 好的 Schema)→ 兜底(步数、超时、确认、日志)。
建议路线:
- 用任意 LLM API 实现一个 3 工具的小 Agent(计算器 + 搜索 + 文件读写)
- 加最大步数和 trace 日志
- 用 20 条任务建一个评测集,统计成功率
- 再尝试加反思机制,对比前后成功率
如果这篇对你有帮助,点个赞支持一下。后续更新「手把手用 Python 写一个最小可用 Agent」。