Agent 不只是套壳:构建可靠的工具调用循环
做一个「会调用工具」的 Agent 出 demo 很容易:给模型几个函数定义,让它决定调用哪个,把结果喂回去,循环几轮。但把它放进真实业务里,你会很快遇到:模型调错工具、参数缺字段、工具报错后 Agent 懵了、或者陷入无限循环不肯停下。
让 Agent 从「能跑」到「可靠」,关键不在更聪明的 prompt,而在把它当成一个需要容错的系统来设计。
Agent 循环的本质
抛开框架,一个工具调用 Agent 的核心循环非常朴素:
while 未完成:
决策 = 模型(对话历史 + 可用工具)
if 决策.是最终回答:
return 决策.内容
结果 = 执行工具(决策.工具名, 决策.参数)
对话历史 += [决策, 结果]
简单到几乎没有「智能」可言。真正决定质量的,是这个循环里每一处的健壮性。
一、工具设计比 prompt 更重要
模型用不好工具,往往是工具本身设计得不好。几条经验:
- 命名即文档。
search_orders_by_user远胜过query。模型靠名字和描述判断该不该用,描述要写清「什么时候用、返回什么、有什么限制」。 - 参数要严格 schema 化。用 JSON Schema 明确每个字段的类型、是否必填、枚举值。模型对结构化约束的遵守度,远高于自然语言里的「请注意」。
- 工具数量要克制。给模型塞 30 个工具,它的选择准确率会显著下降。超过十来个时,考虑分组或分层路由。
二、错误要能「说人话」地返回
工具一定会失败:参数非法、外部接口超时、查无数据。最糟的做法是直接抛异常把整个循环打断。更好的做法是把错误也当成一种工具结果返回给模型,并且写成模型能理解、能据此纠正的话:
{
"error": "参数 start_date 格式应为 YYYY-MM-DD,收到的是 '上周一'。
请换算成具体日期后重试。"
}
这样模型下一轮就能自己修正参数,而不是卡死或胡乱重试。给 Agent 留出「自我纠错」的反馈通道,是可靠性的关键。
三、循环必须能停下来
无限循环是 Agent 最常见的线上事故。三道保险一起上:
- 最大步数限制。比如 10 步还没出结果就强制收尾,给用户一个兜底回复,而不是无限烧 token。
- 检测原地打转。如果连续几轮在重复调用同一个工具、同样的参数,说明模型卡住了,应该中断并提示。
- 明确的完成信号。让模型用一个专门的「完成」动作来结束,而不是靠猜它「好像不想调工具了」。
四、没有可观测性,等于盲飞
Agent 是多步、非确定性的,出问题时如果只能看到最终输出,根本无从排查。每一次运行都应该完整记录:每一步的模型决策、调用的工具与参数、工具返回、耗时与 token 消耗。
当用户说「它答错了」,你要能一眼看出是第几步、哪个工具、什么参数出的问题。这套 trace 能力,是 Agent 系统的「黑匣子」。
五、能不让模型做的,就别让它做
模型擅长理解意图和规划,但不擅长精确、确定性的逻辑。权限校验、金额计算、状态机流转这类事,放进工具的代码里用确定性逻辑实现,别指望模型每次都算对。把模型当「调度员」,把可靠性交给工具本身。
小结
可靠的 Agent = 好的工具设计 + 可纠错的错误反馈 + 能终止的循环 + 完整的可观测性 + 把确定性逻辑下沉到代码。这些没有一项是「prompt 技巧」,它们是扎实的工程。Demo 拼的是模型,生产拼的是这些细节。