一个反复出现的问题:Agent 调不动工具,问题出在哪儿
2026 年的 Agent 项目,绝大多数都死在"工具调用"这一关。逻辑跑得很顺,模型一旦遇到多参数 JSON、多轮依赖或者异常分支就开始乱出参数,或者干脆不调工具、直接编造答案。
最近三个月,我和做企业知识库、内部 RPA、跨系统数据编排的几个团队都聊过一遍,Claude Sonnet 4 和 Qwen3 是被提得最多的两个名字。一个偏稳重长链路推理,工具描述稍微模糊也能猜到意图;一个偏指令规整、DashScope 工程链路完善,国内私有化场景下部署更省心。下面把对比、代码、排查路径压成一份可以照着做的清单。
Claude Sonnet 4:稳定,但"挑食"的是工具描述
Claude Sonnet 4 在 tool_use 上是目前最稳的模型之一。Anthropic 官方文档给出的最小示例(platform.claude.com/docs)已经演进到以 claude-opus-4-8 为代表的新一代 Sonnet/Opus 4 系列,结构是 messages 套 tool_use block,再由客户端做执行和回灌。
实战里最常见的翻车点只有一个:工具描述太含糊。比如:
{
"name": "query_orders",
"description": "查询订单",
"input_schema": {
"type": "object",
"properties": {
"order_id": {"type": "string"}
}
}
}
写法看起来够用,Claude Sonnet 4 在多轮对话里会非常礼貌地"猜":它会把 2025-Q4 这种字符串当成 order_id 直传后端。修法是在 description 里写出"必须是后端返回的 32 位 UUID,且需先调用 get_customer 取得",并把 enum 约束加进 schema。Schema 越窄,调错率越低。
另一个经验:对 Claude 来说,max_tokens 偏小会直接截断 tool_use block,造成后端看到一半的 JSON。Anthropic 官方推荐把 tool 响应也按真实业务返回后再喂回去,不要在客户端"代整理"。
Qwen3:工程链路顺,但并行调用要拦一道
Qwen3 的工具调用走 DashScope OpenAI 兼容接口,参数风格跟 OpenAI Tools 一致,迁移成本低。官方 Qwen-Agent 文档(qwenlm.github.io/Qwen-Agent)开箱即用,支持 MCP 工具协议(这正是 2026 年 Agent 圈最常被提起的协议层)。
Qwen3 的优势是中文指令遵循严格,tool description 写得差一点也不会跑偏;国产私有化部署链路成熟,从千问到昇腾卡再到大模型一体机,大部分已经有现成镜像。短板是并行工具调用。Qwen3 在多轮里愿意"一次发 5 个工具请求",但任意一个失败会拖垮整个 batch。建议在客户端做一层并发包装:
async def safe_call(qwen, tools, prompt, max_parallel=3):
resp = await qwen.chat(prompt, tools=tools)
calls = parse_tool_calls(resp)
results = await asyncio.gather(
*(invoke(t) for t in calls),
return_exceptions=True
)
return zip_and_filter(calls, results)
把 max_parallel 卡在 3,超过的排队。这样既能保留 Qwen3 的速度优势,又不会因为某个慢接口把整轮拖死。
双模型路由:先做 200 条回归再说
如果 Agent 同时接 Claude Sonnet 4、Qwen3(甚至 GPT-5.x 和 Gemini 2.5),不要上来就五五分流。我们之前在《Agent 选型别押一家,三模型路由怎么搭》里实操过一套更稳的切流方式:先用 200 条贴近真实业务的回归用例,横向跑一遍,把"按业务画像路由"的分线规则先稳定下来。
经验值是:长链条、强合规、带计费相关操作(订单、退款、续费)的请求优先 Claude Sonnet 4;中文场景、文档问答、结构化抽取优先 Qwen3。熵平后,从 10% 流量开始切,线上 P0/P1 报错率稳三天再放量。
工具调用里最常见的 5 个错误
把最近半年踩过的坑汇总,错误集中在五处:
1. 工具描述和实际语义不符。 模型会按 description 字面理解,微妙的语义差异(比如"已发货" vs "已签收")会直接影响下游业务判断。
2. Tool result 太大撑爆上下文。 一个搜索返回 8 万字的工具,直接把上下文堆到模型上限。下游要么裁剪,要么用 RAG 重写一次再喂回。夏季 Agent 调用量上升,这类问题在计费账单上最先显现,具体可以参考《模型上下文太长扯不清账?三套 Agent 计费监控开源脚本》。
3. 错误处理直接抛回去。 模型看不到 traceback,只看到 500 Internal Server Error,会陷入循环调用。Tool 实现层要把错误归类,转成可读消息。
4. 并发工具被串行执行。 模型生成了并行调用,客户端按顺序调用,延迟翻倍。Claude 和 Qwen3 都支持 tool_choice 强制并发,但工程实现要看 SDK 是否真正异步。
5. OAuth 刷新令牌在工具里硬编码。 这条跟合规强相关,出事就是《Agent 自动续费陷阱背后:计费接口的合规缝隙》里讲的那一类:长周期 token 被前端或 Agent 直接复用,刷新窗口错了导致重复计费。
把工具编排做成可观测的
工具调用的"另一面"是观测。不是看模型答了什么,而是看 tool 链路:每次进来多少参数、出去了什么、耗时多少 Token、单次调用成本。规模上来后,光看日志不够,要有结构化 trace。
代码层面一个值得抄的写法是把每次工具调用包成一个标准事件:
trace = {
"agent_id": agent.name,
"model": agent.model,
"tool": call.name,
"input_hash": short_hash(call.input),
"latency_ms": int((t1 - t0) * 1000),
"status": "ok|error|timeout",
"tokens_in": usage.input,
"tokens_out": usage.output
}
emit("tool_call", trace)
把 trace 落到 ClickHouse 或 SLS,后续做单工具回归、成本拆解、限流分级都顺。
写在最后
工具调用这件事,Claude Sonnet 4 和 Qwen3 都过了及格线。差距不在"能不能调用",而在工程实现细节:描述写法、并发策略、错误消息、上限管理、计费观测。
对于正在搭建企业级 Agent 的团队,建议从一条小链路开始:10 个工具以内、回归用例 200 条,把上面 5 个错误全跑过一遍再扩展。同时考虑接 MCP 协议让工具可复用,这是 2026 下半年最值得跟进的方向——WAIC 2026 上专家插件路线被高文院士团队反复强调,MCP 正是与之配套的工具层规范。
把这套工程框架搭稳,再谈所谓"通用 Agent",会顺很多。