AI Agent 上线前,先把 5 类失败演练跑一遍
# AI Agent 上线前,先把 5 类失败演练跑一遍
很多 Agent demo 看起来很顺,是因为环境太干净:用户输入完整,工具接口稳定,权限边界清楚,模型每一步都能拿到足够证据。
生产环境不一样。真正出问题的地方,经常不是模型完全不会做,而是链路里某一个小失败没有被设计好:工具超时后重试了两次,队列消息重复投递,外部系统返回半成功,人工接管时看不到上下文,审计日志里只剩一行“执行失败”。
所以我不建议把“能跑通主流程”当作上线标准。Agent 上线前,至少要把下面 5 类失败演练跑一遍。
## 1. 工具超时:Agent 能不能停下来
最常见的失败不是接口直接报错,而是超时。
例如 Agent 要读取 CRM 里的客户状态,再决定是否生成回复。CRM 接口 8 秒没有返回时,系统应该怎么处理?
- 继续等待;
- 换一个工具;
- 使用缓存;
- 请求用户补充;
- 转人工;
- 直接停止。
这些策略不能交给模型临场猜。生产系统里更稳的做法,是给工具调用配置明确的超时、重试和降级策略。
一个简化的配置可以长这样:
```yaml
tools:
crm.get_customer_status:
timeout_ms: 8000
retry:
max_attempts: 1
backoff_ms: 500
fallback:
mode: ask_human
message: "CRM 状态暂时不可用,请人工确认客户状态后继续。"
audit:
log_request_id: true
log_timeout: true
```
这里的关键不是 YAML,而是规则前置。Agent 可以参与判断,但不能拥有无限等待和无限重试的自由。
## 2. 重复执行:写入动作有没有幂等
Agent 系统很容易重复执行。
用户刷新页面、队列超时重投、网络中断后重试、模型重新规划路径,都可能让同一个动作被触发两次。
只读查询重复几次通常问题不大,但写入动作不一样:
- 重复创建工单;
- 重复发送客户通知;
- 重复添加扣费记录;
- 重复触发设备控制;
- 重复把同一条线索推进到下一阶段。
上线前必须演练“同一个写入动作被提交两次”。
可以用一个很简单的测试:
```typescript
const command = {
idempotencyKey: "lead-1842-stage-update-20260624",
action: "crm.updateLeadStage",
leadId: "lead-1842",
targetStage: "qualified",
};
await agent.execute(command);
await agent.execute(command);
// 期望:只产生一次状态变更,审计日志记录第二次为 duplicate_ignored。
```
如果系统没有 idempotency key,只靠“模型应该不会重复调用”,那上线风险会很高。
## 3. 证据缺失:模型会不会硬猜
很多 Agent 事故的根因,是证据不足时系统仍然给出了确定动作。
比如用户问:“这个客户是不是该进入续约流程?”
Agent 可能需要看合同到期日、最近工单、付款状态、客户分层、销售备注。任何一项缺失,都可能改变判断。
失败演练要故意拿掉关键证据,观察 Agent 是怎么表现的:
- 是否明确说明缺了什么;
- 是否降低置信度;
- 是否停止高风险动作;
- 是否请求人工补充;
- 是否把缺失证据写进审计日志。
我更希望看到这样的行为:
```json
{
"decision": "needs_human_review",
"reason": "contract_end_date_missing",
"missingEvidence": ["contract.endDate", "latestInvoice.status"],
"allowedActions": ["draft_summary"],
"blockedActions": ["send_renewal_email", "advance_pipeline_stage"]
}
```
这比一个看似流畅的回答更有价值。生产 Agent 不怕承认“不够判断”,怕的是在证据不足时继续执行。
## 4. 半成功状态:外部系统返回不一致时怎么办
最麻烦的失败,往往不是成功或失败,而是半成功。
例如 Agent 调用外部系统发通知,请求超时了。但通知服务实际上已经发出,只是回调没有回来。Agent 如果直接重试,客户可能收到两条通知。
类似情况也会出现在支付、合同、设备控制、审批流里。
上线前可以设计一组半成功演练:
- 外部接口超时,但实际写入成功;
- 工具返回成功,但下游异步任务失败;
- DB 写入成功,但消息队列发布失败;
- Agent 记录失败,但业务系统已经发生状态变化。
这种场景需要“查证再决定”,而不是盲目重试。
```mermaid
flowchart TD
A[Agent 发起写入动作] --> B{工具返回状态}
B -->|成功| C[记录 action_id 和结果]
B -->|失败| D[记录失败并停止]
B -->|超时/未知| E[查询外部系统状态]
E -->|已生效| F[标记为 succeeded_after_timeout]
E -->|未生效| G[按幂等 key 安全重试]
E -->|仍未知| H[转人工确认]
```
如果没有这条查证链路,Agent 的“自动修复”很容易变成自动制造重复动作。
## 5. 人工接管:人能不能看懂现场
很多团队说自己有 human-in-the-loop,但实际只是弹一个确认按钮。
真正的人工接管,至少要让接管人看到:
- 用户原始请求;
- Agent 当前计划;
- 已调用的工具;
- 每次工具调用的证据;
- 风险等级;
- 已经执行和未执行的动作;
- 推荐的下一步;
- 可回滚动作。
如果接管人只能看到一句“Agent 执行失败,请处理”,那不叫接管,只是把上下文丢给人工重做。
可以用一个简单演练来检查:
1. 让 Agent 在第三步工具调用失败;
2. 强制进入人工接管;
3. 让一个没有参与开发的人查看接管页;
4. 看他能不能在 3 分钟内判断下一步。
如果不能,说明问题不在人工,而在系统没有留下足够上下文。
## 上线前可以用这张清单
把 Agent 接入真实业务前,可以至少检查这些项:
- 工具调用是否有 timeout、retry、fallback;
- 写入动作是否有 idempotency key;
- 高风险动作是否需要人工确认;
- 证据缺失时是否停止执行;
- 半成功状态是否能查证;
- 失败是否写入结构化审计日志;
- 人工接管页是否显示完整上下文;
- 回滚动作是否演练过;
- 每类失败是否有可观测指标;
- 失败演练是否纳入上线验收。
这些检查不一定复杂,但要真的跑一遍。只在文档里写“支持重试、支持人工接管”,和在生产链路里验证过,是两回事。
## AgentKick 的判断
Agent 的生产化,不是把模型能力继续堆高,而是把失败路径补齐。
AgentKick 做 AI Agent Production-Readiness Review 时,会把工具调用、证据链、审计日志、模型路由、人工确认、回滚和可观测性放在一起看。因为生产系统真正要回答的问题不是“正常时能不能跑”,而是“失败时能不能稳住”。
更多推荐

所有评论(0)