一个 AI Agent 的工具调用链路,真正进生产以后,最怕的不是某一次调用失败,而是失败之后没有证据可查——问题看起来像“偶发”,排障却只能靠猜。
Demo 里工具调用几乎总是成功:问题清楚、数据能取到、接口返回正常。但真实流程里,用户表达会变形、权限各不相同、接口会超时、工具返回会冲突,某些动作还会影响订单、资金或设备状态。只要其中一环没处理好,Agent 就会从“看起来很聪明”变成“出了事没人能解释”。
如果你正在把 Agent 接进真实业务流程,下面按三层来拆:先留证据、再谈幂等与回滚、最后是失败分级。
一、先把证据留下
排障的前提是能还原“它当时基于什么做了这个动作”。一次工具调用至少要落这几类字段,并关联到同一次运行的 run id:
- 工具名与版本
- 入参(结构化,不是拼进一句日志字符串)
- 出参或错误
- trace id / run id
- 错误码与错误分类
- 重试次数
- 权限上下文(谁、什么角色、被授权做什么)
把它封装成统一入口,而不是让每个工具各写各的日志:
def call_tool(name: str, args: dict, ctx: RunContext):
span = tracer.start_span(name, attributes={
"tool.name": name,
"run.id": ctx.run_id,
"actor.role": ctx.role,
})
try:
result = dispatch(name, args)
span.set_attribute("tool.status", "ok")
return result
except ToolError as e:
span.set_attribute("tool.status", "error")
span.set_attribute("tool.error_code", e.code)
raise
finally:
audit.write(ctx.run_id, name, args, span) # 逐步落库,不只记最终输出
关键是逐步记录,而不是只记最终回答。日志仅保留获准字段,凭据与个人信息需要脱敏;上面的代码只表示调用与记录的关系,真实实现还要补权限检查、敏感信息处理和日志失败时的行为。
二、幂等与回滚:副作用动作的底线
会写入或产生副作用的动作(创建工单、发消息、扣费、改状态)必须满足两点:幂等键 + 执行前检查。否则一旦步骤重试,就会重复执行——两张工单、两次扣费、两条发给客户的消息。
设计上分两类动作区别对待:
- 只读查询:确认没有副作用后,可按约定的次数、退避和预算重试;记录数据时间,不能无限重试或把旧缓存冒充最新。
- 写操作:带幂等键,执行前先查“这个 key 是否已执行过”,已执行则返回上次结果而不是再做一次。
- 高风险写操作(改订单状态、对外发送、涉及资金):额外加一道人工确认闸,不靠模型自觉。
回滚路径要在设计期就想清楚:哪些动作可补偿(撤销/冲正),哪些不可逆(已发出的消息)。不可逆动作应尽量前置人审。
三、失败分级:不是所有失败都一样
把失败分成三类,Agent 的处理策略完全不同:
- 可重试:超时、限流、瞬时网络错误 → 带退避重试,记录重试次数。
- 需降级:某工具不可用但有替代路径 → 切换或返回部分结果,并显式标注“数据不完整”。
- 必须人工:权限不足、数据冲突、涉及不可逆动作 → 停下来转人工,不要硬猜。
最贵的错误不是明显报错,而是数据缺失时 Agent 编了一个“看起来合理”的值继续往下走。缺数据时的正确行为是说明不可用并给出原因,而不是补一个假值。
接口变了以后,谁负责把报告恢复?
假设设备接口把字段从 energy_kwh 改成 energy_wh。这个变更是方法示例,不是已发生的客户事故。仅仅让查询不报错还不够:如果把 12000 Wh 当作 12000 kWh,报告会放大一千倍;正确换算应是 12 kWh。实际单位与转换规则必须以接口约定为准,不能靠模型猜。
处理路径是:发现变更 → 判断影响 → 暂停受影响结果 → 修正映射 → 回归检查 → 业务确认。
左右滑动查看完整表格
| 步骤 | 负责角色 | 要交代清楚的结果 |
|---|---|---|
| 发现与说明 | 接口维护方 | 哪个字段或单位变了、何时生效、旧版本是否仍可用 |
| 判断与暂停 | Agent 实现方,业务负责人确认影响 | 列出受影响查询/报告;阻止把未核对结果当正常报告使用 |
| 修正与回归 | Agent 实现方 | 修正映射、校验单位;检查正常、缺项、超时和旧数据等样本 |
| 验收与恢复 | 业务验收方和工程负责人 | 确认数字、范围与来源;记录可以恢复的能力及版本 |
| 后续移交 | 双方约定的维护负责人 | 保存处理记录、回退条件、未解决项及下次变更通知方式 |
恢复至少核对五项:当前接口约定和版本;字段/单位映射;一条可人工核算的正常输入;缺项与失败输入;已生成报告及外部动作的处理结果。责任表中的角色可由同一人承担,但不能留空。
**软件版本回退不会自动撤回已发报告、消息或工单。**如果旧接口已不可用,退回旧代码也可能无法恢复;需要选择可用替代、补偿或人工处理,并核对实际结果。下载变更责任表与恢复检查单。
Sam 的边缘固件与 OTA 个人经历说明相关设备协议与升级背景;这里的字段变更和处理流程是另外设计的方法示例,不能当作那段经历的故障记录。
常见问答
Q:工具偶发返回错误状态,我该先调 prompt 吗? A:先看审计日志定位问题在哪一层(是工具本身、权限、还是入参构造),再决定。先动 prompt 往往是在没有证据的情况下猜。
Q:幂等键应该放在哪一层实现? A:放在产生副作用的动作入口,执行前做去重检查。放在模型或 prompt 层不可靠。
Q:所有动作都加人审会不会太慢? A:只对有副作用、高风险的动作加人审,只读查询直接放行。分级之后,绝大多数调用不需要人工介入。
AgentKick 的首次合作是AI Agent 生产就绪审查与路线图:先核对数据、工具、权限、运行记录与恢复责任,交付问题清单和整改路线图。建设和持续维护的范围另行确定;你可以先画出一条实际变更的处理路径,再用Agent 场景自检整理当前工作。
