最近几个月一直在折腾 AI Agent,踩了不少坑,也试了几条不同的路径。从最早的单工具调用,到后来尝试多个 Agent 角色分工协作,中间翻车了无数次。这篇把沉淀下来的方案和踩坑记录做个梳理,希望能给正在搞 Agent 的朋友一些参考。
## 为什么我放弃了大一统框架
年初的时候,我还是忠实的 LangChain 用户。但用着用着发现一个问题——抽象层太厚了,出了问题很难定位。尤其是当 Agent 行为不符合预期的时候,你根本不知道是 Prompt 的问题、链式调用的问题、还是底层模型本身的问题。
后来换成了直接调用 API + 手写工具注册的方式。虽然代码量多了点,但每一层发生了什么完全可控。对于想深入理解 Agent 原理的人来说,建议也走一遍这条路。
## Tool-Use 的核心:不是 Function Calling,是上下文注入
很多人以为 Tool-Use 就是让模型输出一个 JSON,然后解析调用。其实真正的关键在于——工具的描述和返回结果如何有效地注入到上下文中。
我目前的方案分三层:
“`
Agent Core(路由决策)
├── Tool Registry(工具注册中心)
│ ├── 工具描述(含参数 schema)
│ ├── 执行函数
│ └── 结果格式化
└── Context Manager(上下文管理)
├── 历史消息窗口
├── 工具结果缓存
└── Token 预算控制
“`
踩坑最多的点是**工具描述怎么写**。一开始我用很简短的描述,比如”搜索网络信息”。结果模型经常误调用——它会在用户问天气的时候调搜索,而不是先试试自己能否回答。后来改成详细的描述,明确标注使用场景和限制条件:
“`
工具:web_search
描述:当用户询问实时信息、最新新闻、或你的训练数据中没有包含的内容时使用。
不要在你已知道答案的问题上调用此工具,优先使用自身知识回答。
每次返回最多10条结果,包含标题和摘要。
参数:query (string, 必需) — 搜索关键词,尽量简洁
“`
改完之后,调用准确率从 70% 左右提升到了 92% 以上。细节决定成败。
## 一个实用的单 Agent 模式
最稳定也最容易 debug 的方案,是一个 Agent 配合多个工具。像这样:
“`python
class Agent:
def __init__(self, tools: list[Tool]):
self.tools = {t.name: t for t in tools}
self.messages = []
def run(self, task: str, max_steps: int = 10) -> str:
self.messages.append({“role”: “user”, “content”: task})
for step in range(max_steps):
response = self._call_llm()
if response.get(“type”) == “final”:
return response[“content”]
tool_result = self._execute_tool(response[“tool_call”])
self.messages.append(tool_result)
return “Max steps reached”
“`
这里有一个小技巧:**给 max_steps 设一个上限**。有些 Agent 会在同一个问题上反复循环,没有上限的话 token 消耗会让你肉疼。
## 什么时候该上 Multi-Agent
单一 Agent 够用的时候,别上多 Agent。这是最实在的建议。
我只有在以下三种情况才切换到 Multi-Agent:
1. **角色冲突**:同一个 Agent 既要写代码又要做安全审查,Prompt 写得再长也容易混淆
2. **工具集过大**:当工具超过 15-20 个时,模型选择的准确率明显下降
3. **需要异步协作**:比如一个 Agent 在等待外部 API,另一个可以继续处理其他子任务
## Multi-Agent 的一种简洁模式
参考了 AutoGen 和 CrewAI 的思路,但我做了一些简化——去掉了它们过于复杂的对话管理。
“`
Coordinator Agent(协调者)
├── Researcher Agent(研究员)
│ 工具:web_search, content_extract
├── Coder Agent(程序员)
│ 工具:code_interpreter, file_read, file_write
└── Reviewer Agent(审查者)
工具:code_review, security_check
“`
核心是 Coordinator 负责路由和汇总,不直接执行具体任务。每个 Specialist Agent 只需要关注自己的领域。
实际运行时的效果还不错。举一个具体例子:让系统写一个数据分析报告,Researcher 搜索数据源 → Coder 写分析脚本 → Reviewer 检查代码逻辑 → Coordinator 汇总成报告。整个过程大约 3 分钟,比我手动一条龙搞完快了 10 倍不止。
## Context Window 是最硬的约束
不管是单 Agent 还是多 Agent,上下文窗口永远是瓶颈。分享一下我的处理策略:
– **滑动窗口**:保留最近 N 轮对话,超出部分压缩摘要
– **工具结果摘要**:长文本工具返回结果时,先让模型总结再注入上下文
– **分层记忆**:短期记忆(当前会话)和长期记忆(向量数据库存储的关键信息)
目前我用的是 Qdrant 做向量存储,检索效果比 Pinecone 好,而且自托管不花钱。
## 踩过的坑汇总
– **工具调用循环**:Agent 反复调用同一个工具拿到的结果一样 → 加缓存,标记幂等性
– **JSON 解析失败**:模型偶尔输出格式不标准的 JSON → 用 `functools.lru_cache` 做重试 + 修复
– **角色混乱**:多 Agent 之间相互抢答 → 用明确的发言权控制,一次只让一个 Agent 输出
– **Token 爆炸**:工具返回结果太大 → 限制每个工具返回不超过 2000 tokens
– **成本失控**:Debug 时每次都要调模型 → 本地跑小模型(Llama 3.1 8B)做快速验证
## 下一步
目前正在尝试把 Agent 的输出接入到 Obsidian 笔记体系里,让 Agent 直接写 markdown 笔记并建立双向链接。这个做好了再单独写一篇。
工具链和代码示例都放在 GitHub 上了,需要的话可以留言或私信。
—
**相关标签**:AI Agent, Tool-Use, Multi-Agent, LLM, 自动化