Skip to content

agent 工具调用 ID 不匹配:回退路径下 tool_call_id 与 assistant 不一致(API 契约) #20

Description

@weed33834

严重度:中–高(条件触发:文本解析回退路径;触发后向 LLM API 发 400)
标签建议:bug

现象

doctoragent/model/agent.py_dispatch_tool_calls 里生成 assistant 消息的 tool_calls[].id 与后续 tool 消息的 tool_call_id 用了不同的计数器时机

  • agent.py:1469(入口,早于任何执行):"id": tc.get("id") or f"call_{self._tool_calls_used}_{idx}" —— 取的是自增前self._tool_calls_used
  • agent.py:1512_run_group 内,每个工具执行后):self._tool_calls_used += 1
  • agent.py:1537(生成 tool 消息,执行之后):call_id = tc.get("id") or f"call_{self._tool_calls_used}_{idx}" —— 取的是自增后self._tool_calls_used

当走文本解析回退路径_parse_tool_calls 产出的 tc 没有 id 字段)时,assistant 侧 id 用自增前的值、tool 侧 id 用自增后的值,两者不一致。下一轮 _call_llm_with_tools 把这组消息发给 OpenAI / 兼容接口时,tool_call_id 与 assistant 的 tool_calls[].id 对不上 → API 返回 400tool_call_id does not match any tool_calls)。

证据

复现(来源 /tmp/repro_tool_call_id.py):2 个工具调用场景下

assistant tool_calls ids : ['call_0_0', 'call_0_1']
tool      messages ids   : ['call_2_0', 'call_2_1']
MATCH: False

(自增前 N=0 生成 assistant id;执行 2 次后 N=2 生成 tool id,差了调用数。)

影响

  • 仅在文本解析回退路径(tcid)触发;结构化 tool_calls(LLM 正常返回带 id)不受影响。
  • 一旦触发,多轮工具调用直接 400 失败,agent 无法继续基于工具结果推理。

建议修复

tool 消息的 tool_call_id 必须与 assistant 侧使用的 id 同源:要么在入口处为无 id 的 tc 预先分配并缓存 id(用同一变量生成两侧),要么在 1537 行用与 1469 行完全相同的取值逻辑(同一 self._tool_calls_used 快照)。确保同一次 dispatch 里 assistant 与 tool 消息的 id 逐一对齐。

关联

#2(同文件 _estimate_tokens 已修)相邻;属 agent 工具编排的契约正确性。

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions