Agent 工具调用参数嵌套错误:问题分析与解决方案
来源会话:c4130 nccl(llama.cpp 4×V100 NCCL 多卡优化任务) 涉及工具:
ssh_hub(远程服务器执行/文件传输) 现象级别:同一失败调用连续重复 30+ 次,任务停滞数十分钟
一、问题现象
在执行远程 NCCL 验证任务时,agent 反复调用 ssh_hub 工具执行远程命令,每次均返回同一错误:
stderr: 不支持的 command: undefined
随后同一失败调用被重复发送 30+ 次,系统反复提示"重复调用无进展",但 agent 持续重发结构完全相同的调用。最终靠两件事打破循环:
- 退回无参最小调用(
list)做基线对照,发现参数结构乱了; - 换用 c4130-ipv6 通道 + "本地写脚本 → 上传 → 简单命令执行"的拆解方式。
二、错误调用 vs 正确调用
正确格式(顶层平铺字段):
tool: ssh_hub
command: "run"
alias: "dell-c4130"
remote_command: ["bash", "-lc", "python3 /tmp/test_final.py"]
错误格式(参数被多包进一层 arguments):
tool: ssh_hub
arguments: {
"command": "run",
"alias": "dell-c4130",
"remote_command: ["bash", "-lc", "python3 /tmp/test_final.py"]
}
工具从顶层读取 command 字段时读不到值 → undefined → 不支持的 command: undefined。
三、根因分析:三层缺陷叠加
| 层 | 缺陷 | 作用 |
|---|---|---|
| 模型侧(诱因) | 格式幻觉:大量工具调用训练样本使用 {"name":..., "arguments":{...}} 结构(OpenAI function calling 风格),模型内化了"参数要包一层"的习惯;而本环境要求顶层平铺字段 | 产生了错误的参数结构 |
| 工具侧(放大器) | 错误信号不可行动:只说"command 缺失",没说"你多包了一层"。对 agent 而言"换个 command 值"与"换包裹结构"看似同等可能,它选了前者 | 错误结构被持续使用 |
| 系统侧(失控点) | 重复检测只报警("你在重复调用"),不给纠偏策略 | 失败被放大为长时间停滞 |
四、解决方案(按有效性排序)
4.1 Harness 侧(最根本)
1)边界处做 schema 校验
调用到达工具之前,先按工具 schema 校验;失败时返回结构化错误:
Invalid arguments: unexpected top-level key "arguments".
Expected top-level fields: command (required), alias, remote_command, ...
把"undefined"这种猜谜式报错变成一行即可修复的报错。
2)工具识别并点名反模式
ssh_hub 特判"唯一顶层字段是 arguments 且其中恰好是已知字段"的情况,直接提示:
看起来你把参数包进了 arguments 对象;本工具要求顶层字段。 正确形式:
{command: run, alias: ..., remote_command: [...]}
检测 + 点名,远比泛泛报错有效。
3)宽容归一化(自动解包)
harness 做宽松处理:发现单个 arguments 对象包含已知字段时,自动解包并记录警告日志。此类错误直接归零,不依赖模型自觉。
4)重复检测从"报警器"升级为"断路器"
同一失败调用连续 N 次时,不要只报"重复",注入强制策略切换:
已连续 5 次同样失败。停止重试同一结构;先做无参最小调用验证连通性; 对照一次成功调用的参数结构。
核心是逼它换结构,而不是换内容。
4.2 Prompt 侧(行为纪律)
- 参数按工具 schema 的顶层字段传递,绝不额外包裹;
- 同一调用连续两次同错 → 停止重试:先查错误、对照 schema、再做最小测试调用;
- 每个工具的 description 里附一个正确调用示例(few-shot 对这类格式问题非常有效)。
4.3 训练侧(治本,但最慢)
用本 harness 的真实调用格式做微调,替换通用训练中的包裹习惯。这是唯一能从源头防住的方式,但成本最高、周期最长。
4.4 操作侧(人卡住时怎么解)
看到 agent 在同一个错误里打转时:
- ❌ 不要给正交提示(如"你可以同时多次调用工具"——与问题无关);
- ✅ 直接说:"停止重试,先发一个无参的
list最小调用验证连通,再逐字段对比一次成功调用的结构。"
这句话正是原会话中打破循环的钥匙,提前说可以省掉 30 次空转。
五、结论
模型侧的格式幻觉无法完全防住,但 harness 侧做到 schema 校验 + 可行动报错 + 重复断路器 三层,就能把这类错误从"卡死半小时"降级为"多花一次调用"。三层中第 1 层(边界 schema 校验)性价比最高、成本最低,应最先实施。