AI agent 从 Demo 到生产,最危险的跳跃不是“模型够不够强”,而是“什么时候开始替代真实流程”。很多系统的问题,不是功能做不出来,而是上线方式太激进:还没观察真实输入,就让 agent 直接写状态、发通知、改数据。
Shadow Mode 的价值,是让 agent 在真实流量旁边跑,但先不真正接管。
建议先配合 AI agent 灰度发布与功能开关、AI Agent 评估框架完全指南、AI Agent 可观测性设计 和 AI agent 产品成功指标 一起看。
先给结论:Shadow Mode 不是 A/B,而是“旁路运行 + 结果对照”
| 模式 | 是否影响真实用户 | 主要目的 |
|---|---|---|
| 离线回放 | 否 | 先用历史数据验证 |
| Shadow Mode | 否 | 看真实输入下的表现 |
| 灰度接管 | 是,部分接管 | 验证真实业务价值 |
| 全量接管 | 是 | 正式上线 |
Shadow Mode 在离线回放和灰度接管之间,最大的好处是能吃到真实输入,又不直接制造副作用。
一、Shadow Mode 最适合验证什么
它最适合回答这几个问题:
- 真实输入是否比离线样本更脏
- prompt / 工具 / 检索在真实上下文里是否偏航
- agent 的输出和人工结果差多远
- 成本和延迟在真实流量下是否可接受
它不适合回答“业务到底会不会接受 agent 结果”,因为此时 agent 还没真正接管流程。
更准确地说,Shadow Mode 验证的是“在真实输入和真实系统边界下,这套 agent 方案是否足够稳定地接近可接管状态”。它不是业务验收的终点,而是上线前最后一段低风险观察带。
二、Shadow Run 至少要保留对照对象
如果 agent 在旁路运行,但没有明确对照对象,最后只会变成“又跑了一遍”。
最小对照结构:
{
"shadowRunId": "shadow_123",
"sourceTaskId": "task_456",
"baseline": {
"type": "human_result",
"artifactId": "decision_001"
},
"candidate": {
"promptVersion": "brief-agent-v9",
"toolSet": "runtime-v3"
}
}
这里的 baseline 可以是人工结果,也可以是旧版本 agent 的结果。没有 baseline,就谈不上对照。
如果系统同时在跑多个候选版本,建议把实验路由信息也写进 shadow 记录:
{
"shadowRunId": "shadow_123",
"experimentId": "exp_runtime_v3",
"routingKey": "team_a_region_cn",
"baselineVersion": "human_v1",
"candidateVersion": "agent_v3"
}
这样做的价值是,当差异被发现时,团队能快速知道这是某个候选版本的问题,还是某个输入分组的问题。
三、Shadow Mode 要定义“差异怎么判”
只看最终答案是否相似,太粗。更实用的是分层看差异:
| 层级 | 看什么 |
|---|---|
| 结构差异 | 是否符合 schema,字段是否齐全 |
| 决策差异 | 是否选了不同工具、不同 nextAction |
| 风险差异 | 是否少了人工确认、少了风险提示 |
| 业务差异 | 如果接管,可能导致什么后果 |
Shadow Mode 的重点不是追求“完全一样”,而是判断“不同是否可接受”。
为了避免评估人员各自凭感觉打分,最好提前定义差异 rubric,例如:
| 维度 | 权重 | 说明 |
|---|---|---|
| schema 完整性 | 30% | 字段是否齐全、结构是否有效 |
| 动作选择正确性 | 30% | nextAction、工具路径是否合理 |
| 风险控制一致性 | 25% | 是否漏掉 review、阻断或告警 |
| 表达质量 | 15% | 可读性、结构性、冗余度 |
这样即使候选结果和人工不完全一致,也能更稳定地判断“差异是否可接受”。
四、不要让 Shadow Mode 偷偷产生副作用
这是最常见事故来源。表面上是旁路运行,实际某个工具仍然真的写了数据库或发了 Webhook。
Shadow Mode 下,工具层应该明确支持:
- 只读执行
- 模拟写入
- outbox 记录
- side effect blocked 标记
如果系统做不到这一点,那不叫 Shadow Mode,只是“带风险的假演练”。
对工具层来说,shadow 最稳的实现通常不是“业务代码里加一个 if”,而是统一通过执行上下文注入:
interface ExecutionModeContext {
mode: 'shadow' | 'live'
sideEffectsAllowed: boolean
outboxOnly: boolean
}
只要执行上下文进入工具网关,每个写工具都必须显式声明在 shadow 下的行为。这样能避免老工具悄悄绕过保护。
五、Shadow 结果要能沉淀成可复盘样本,而不是看完就丢
Shadow 最大的浪费,是团队每天看差异报表,却没有把高价值样本沉淀下来。建议至少把这些样本单独标记:
- 与 baseline 差异很大但最终判断为可接受的样本
- schema 正确但风险判定不同的样本
- 高成本或高延迟样本
- 命中罕见规则或异常路径的样本
这些样本既可以进入后续评测集,也能反过来指导 prompt、policy 和工具改造。
六、什么时候可以从 Shadow 进入灰度接管
不是跑几天没报错就能转正。至少要有明确门槛:
| 指标 | 参考门槛 |
|---|---|
| schema 正确率 | >= 99% |
| 高风险漏拦截 | 0 |
| 与人工结果可接受偏差 | 在定义范围内 |
| p95 延迟 | 不高于基线显著阈值 |
| 成本 | 在预算范围内 |
只要高风险漏拦截不是 0,就不应该进入接管阶段。
更稳的做法是把“升格”拆成两道门:
| 阶段 | 目标 |
|---|---|
| shadow -> guarded canary | 只让极小流量进入真实接管,并保留快速回退 |
| guarded canary -> gradual rollout | 在真实收益成立后逐步放量 |
这样团队不会从“完全不接管”一下跳到“已经开始改真实数据”。
七、上线后要看 Shadow 健康指标,而不只是跑了多少条
一个成熟的 shadow 体系,至少会持续看这些指标:
| 指标 | 用途 |
|---|---|
| 有 baseline 的 shadowRun 占比 | 判断对照是否充分 |
| 差异可归因率 | 判断是否能解释差异来源 |
| 高风险差异率 | 判断是否允许进入下一阶段 |
| shadow 误触发副作用次数 | 判断隔离是否真的可靠 |
| 样本沉淀率 | 判断 shadow 结果是否反哺评测集 |
如果 shadow 数据很多,但大部分差异都无法解释,那说明系统在“收集噪声”,而不是建立信心。
八、失败案例:Shadow Mode 忘了关写入开关,真实状态被误改
一个审批 Agent 在 shadow 期间按理只生成建议,但某个旧工具没有接入新 gateway,仍然会实际更新任务状态。结果团队以为自己在观察旁路结果,实际上已经在偷偷修改业务流。
修复后,他们做了三件事:
- 所有工具必须标记
supportsShadow - Shadow Run 统一走 sandbox/outbox
- 发布前扫描所有写工具是否仍存在真实 host
这类问题说明:Shadow Mode 不是产品策略问题,而是执行层问题。
九、Shadow Mode Checklist
- 是否有明确 baseline 作为对照对象
- 是否记录 experimentId、routingKey 和 candidateVersion
- 是否定义结构、决策、风险三层差异评估
- 是否有统一差异 rubric,而不是凭感觉判断
- Shadow Run 是否绝不产生真实副作用
- 工具层是否显式支持 shadow 模式
- 高价值差异样本是否回流到评测和回归集
- 是否设置转入灰度接管的门槛
- 是否记录 shadow 期间的成本、延迟和拦截率
- 是否监控高风险差异率和误触发副作用次数
- 出现高风险差异时是否自动阻断转正
结语
AI agent 的 Shadow Mode,本质上是在真实世界里练兵,但不直接开火。只有把对照、差异评估、副作用隔离和转正门槛设计清楚,旁路运行才有工程价值,而不是又多跑了一套看不懂的数据。
延伸阅读:


