Agent 工具调用参数嵌套错误:问题分析与解决方案

0 阅读4分钟

Agent 工具调用参数嵌套错误:问题分析与解决方案

来源会话:c4130 nccl(llama.cpp 4×V100 NCCL 多卡优化任务) 涉及工具:ssh_hub(远程服务器执行/文件传输) 现象级别:同一失败调用连续重复 30+ 次,任务停滞数十分钟


一、问题现象

在执行远程 NCCL 验证任务时,agent 反复调用 ssh_hub 工具执行远程命令,每次均返回同一错误:

stderr: 不支持的 command: undefined

随后同一失败调用被重复发送 30+ 次,系统反复提示"重复调用无进展",但 agent 持续重发结构完全相同的调用。最终靠两件事打破循环:

  1. 退回无参最小调用(list)做基线对照,发现参数结构乱了;
  2. 换用 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 校验)性价比最高、成本最低,应最先实施。