假设一个 Agent 候选版本在离线评估里从 96% 提升到 98%。是不是可以全量发布?
先别急。下面是本文实验里同一个候选版本进入 Canary 后的结果:
离线 Eval:baseline 96% -> candidate 98%
在线错误率:control 2% -> canary 10%
正确动作仍然是回滚。
离线 Eval 证明候选版本有资格进入小流量现场,不能证明它已经适合接管全部生产任务。真实流量里的工具限流、队列等待、数据分布和副作用,可能在实验集里根本没有出现。
这也是我把原计划中的“Production Ops”和“持续改进”合成一篇的原因。两者不是前后独立的工作:生产系统产生证据,保护机制先止损,确认后的失败再进入下一轮评估。拆开写,反而容易留下两个没有接上的半环。
本文是 AI Agent 工程进阶 的第 11 篇,也是主线收官篇。上一篇 Human Control 解决高风险动作在哪里暂停、由谁批准;这一篇继续回答:Agent 上线以后,怎样观察、降级、发布、回滚,并让一次失败真正降低以后再次失败的概率。
| 项目 | 说明 |
|---|---|
| 内容类型 | Agent 生产运行、渐进发布与持续改进实战 |
| 适合读者 | 已有可运行 Agent,准备进入内测、灰度或生产环境的开发者 |
| 阅读时间 | 约 10-15 分钟 |
| 跟做时间 | 35-50 分钟 |
| 环境要求 | Python 3.10+,零第三方依赖,不需要 API Key |
| 代码检查点 | 3102d9b |
| 实验下载 | agent-production-loop-lab-1.1.1.zip |
| SHA-256 | 3C6FF3861990C9F6BCBBA8A296BFC311CC1B42154F4FEB0DD21D3CE0E2290174 |
| 资料核对日期 | 2026-08-08 |
| 实验边界 | 确定性策略夹具;不是容量测试、SRE 审计、模型质量评测或生产阈值建议 |
一分钟概览
先记住九个结论:
- 生产运营和持续改进是同一个闭环。 可以用
Observe -> Protect -> Improve理解。 - 不要用一个成功率代替完整看板。 至少分开看运行健康、任务质量和业务结果。
- Trace 用于解释单次运行,时间窗口用于触发生产动作。 两者不能互相替代。
- 每个核心指标都要绑定 Owner、阈值、动作和恢复条件。 否则它只是告警噪声。
- 稳定版本和 Canary 的处理不同。 稳定版本可以降级,候选版本越过门槛通常应回滚。
- 离线提升不能覆盖在线回归。 安全、错误率、副作用和成本门禁应保留否决权。
- 生产失败不能直接喂给自动改写流程。 先确认、脱敏、去重,再转成可重复 Eval。
- 自动化适合生成候选改动和报告,不应默认自动合并、全量发布。
- 阈值来自你的任务合同和风险承诺。 本文数字只是能运行的教学夹具。
图 1:Agent Production Loop 用 Observe、Protect、Improve 串起生产运行、发布保护和回归评估
图 1:Observe 提供窗口证据,Protect 把证据转成继续、降级、暂停或回滚,Improve 再把确认后的事故转成下一版发布门禁。封面动画仅用于表现闭环流动。
1. 为什么生产运营和持续改进应该合在一起
如果只做 Production Ops,团队可能拥有很多监控图,却没有回答:这次失败会不会进入回归任务集?
如果只做 Improvement Loop,团队可能不断改 Prompt、换模型,却没有可信的生产证据说明应该改什么。
一个完整闭环要连续回答三个问题:
Observe:现在发生了什么,影响多大?
Protect:系统此刻应该继续、降级、暂停还是回滚?
Improve:怎样把这次失败变成下一版必须通过的测试?
它们分别对应不同时间尺度:
| 时间尺度 | 主要问题 | 典型产物 |
|---|---|---|
| 单次运行 | 这条任务在哪里第一次偏离? | Trace、Span、工具回执、版本元组 |
| 运行窗口 | 当前版本是否仍在承诺范围内? | SLO、预算、队列、错误率、降级决策 |
| 发布周期 | 候选版本是否比旧版本更值得上线? | Regression Eval、对照报告、Canary、回滚记录 |
关键不是把三层数据堆进同一平台,而是让证据能够向下一层流动,同时保留责任边界。
2. Observe:别让一个成功率统治看板
一个回答正确但耗时 90 秒、调用 40 次工具的 Agent,可能不可运营;一个延迟很低却总把复杂问题转给人工的 Agent,也可能只是把成本藏到了别处。
我会把最小生产记分卡拆成三层。
图 2:Agent 生产看板至少分为运行健康、任务质量和业务结果三层
图 2:三层信号回答不同问题。Trace 负责解释某次失败,窗口指标负责触发运行动作,业务结果负责判断自动化本身是否值得继续。
三层信号的响应速度不同。写入结果未知、安全回归和 Provider 故障可以成为即时硬门禁;用户是否再次追问、人工是否重做等业务结果通常有延迟,更适合周度复盘和任务设计调整。不要因为一个滞后指标刚刚波动,就让发布系统秒级自动回滚。
2.1 运行健康:系统还能稳定执行吗
第一层关注执行面:
| 信号 | 它在回答什么 | 可能动作 |
|---|---|---|
p95_latency_ms | 大多数任务之外,慢请求尾部是否恶化 | 限制复杂任务、切换草稿模式、扩容 |
queue_age_seconds | 请求是否在排队中失去时效 | 限流、拒绝新任务、转人工 |
tool_error_rate | 外部依赖是否已经不适合继续写入 | 只读降级、熔断工具 |
cost_per_task | 单任务是否越过预算承诺 | 停止追加步骤、转人工 |
unknown_write_count | 外部写入结果是否无法确认 | 立即暂停写操作并对账 |
provider_available | 当前模型或服务是否可用 | 切换 Provider、使用固定流程或人工接管 |
这里最危险的不是一个普通错误,而是“写入结果未知”。超时并不等于失败:外部系统可能已经执行成功,只是回执丢失。继续重试可能造成重复付款、重复发信或重复发布,因此它应比成本和延迟拥有更高优先级。
2.2 任务质量:系统仍然做对了吗
第二层来自任务合同和 Eval:
- 核心任务通过率;
- 正确拒答率;
- 安全回归数;
- 证据完整率;
- Grader 分歧与人工抽检;
- 不同任务切片的退化情况。
这里要避免只看总体平均数。新版可能让常见问题更好,却让高风险写操作更差;平均分上涨不能抵消安全切片回归。
2.3 业务结果:任务真的被解决了吗
第三层容易被工程看板忽略:
- 用户是否需要再次追问;
- 人工是否重做或纠正结果;
- 工单是否真的关闭;
- 下游是否出现重复写入或错误状态;
- 自动化究竟节省了时间,还是只把工作转移给 Reviewer。
这类指标通常需要业务系统和人工反馈,不会自然出现在模型 Trace 里。它也最能提醒团队:一个技术上健康的 Agent,未必完成了值得自动化的任务。
Trace 与监控的分工
OpenAI Agents SDK 可以记录模型生成、工具调用、handoff、guardrail 和自定义事件;OpenTelemetry 也提供跨系统的 Trace、Metric 与 GenAI 属性约定。但“能采集”不等于“已具备可运营性”。生产动作仍应由聚合窗口、任务合同和业务规则决定。工具参数与结果可能含敏感数据,进入观测平台前要做字段白名单和脱敏。
3. Protect:指标必须通向一个明确动作
只设置告警,不设置动作,通常会得到两种结果:值班人员临场猜,或者所有人逐渐忽略告警。
先用一个最小例子区分三个容易混在一起的词:
SLI:实际测到的指标,例如“窗口内任务成功率 97%”
SLO:团队承诺的目标,例如“任务成功率不低于 95%”
Error Budget:在约定窗口内允许消耗的失败空间
本文还会使用“单任务成本预算”。它限制一次 Agent 允许花多少调用、Token 或金额,和可靠性 Error Budget 不是同一件事。
更可执行的做法是先写降级矩阵:
| 条件 | 稳定版本动作 | Canary 动作 | 恢复条件 |
|---|---|---|---|
| 工具错误率越界 | read_only,停止外部写入 | rollback | 工具窗口恢复并通过健康检查 |
| p95 或队列越界 | draft_only,只生成草稿 | rollback | 连续窗口回到 SLO 内 |
| 单任务成本耗尽 | handoff,停止继续规划 | rollback | 预算或策略重新批准 |
| Provider 不可用 | 固定流程、备用 Provider 或人工接管 | rollback | Provider 健康且任务重放通过 |
| 写入结果未知 | pause_writes,先查回执 | rollback 并暂停写入 | 对账完成,幂等状态明确 |
| 安全或离线 Eval 回归 | 阻止下一次普通发布 | rollback | 修复版本通过全部门禁 |
稳定版本先降级,是为了保留一部分有用能力;Canary 回滚,是因为候选版本还没有获得扩大影响面的资格。
本文实验采用如下教学阈值:
OperationsPolicy(
min_success_rate=0.95,
max_p95_latency_ms=5000,
max_cost_per_task=0.30,
max_queue_age_seconds=120,
max_tool_error_rate=0.10,
max_handoff_rate=0.40,
min_candidate_eval_pass_rate=0.95,
max_canary_error_rate_delta=0.03,
max_canary_cost_ratio=1.20,
)
这些数字只服务于固定夹具。真实阈值必须从任务合同、流量基线、风险等级和团队承诺中推导,并明确窗口长度、最小样本量、Owner 与例外流程。
4. Canary:离线通过只是入场券
Canary 的价值不在于“先发 10%”,而在于建立一组可比较证据:
固定候选版本
+ 有代表性的少量流量
+ 同期 Control
+ 绝对 SLO
+ 相对退化阈值
+ 明确观察窗口
+ 自动回滚条件
图 3:候选版本先通过离线门禁,再用小比例 Canary 同时比较绝对 SLO 和相对 Control
图 3:实验中的 10% 只是夹具参数,不是生产建议。即使候选离线分数更高,只要在线错误率、安全或成本越界,仍然回滚。
4.1 为什么既看 Control,又看绝对 SLO
只和 Control 比较会漏掉一种情况:候选与旧版同样糟糕。比如两边成功率都是 80%,相对差值为零,但都低于业务承诺。
只看绝对 SLO 也不够。候选可能勉强在阈值内,却比 Control 明显变差。合理门禁应同时检查:
candidate meets absolute SLO
AND candidate does not regress beyond control delta
AND no safety regression
AND cost stays within policy
4.2 晋级不是终点
Canary 通过后也不应一步跳到永久全量。更稳妥的做法是逐步扩大流量,每一级保留:
- 当前版本和策略版本;
- 观察窗口;
- 回滚点;
- 触发回滚的证据;
- 谁批准了扩大影响面。
Google SRE 对 Canary 的定义同样强调局部、限时部署与对照分析;错误预算耗尽后,普通发布应让位于可靠性恢复。本文不直接照搬某个流量比例,因为 Agent 的风险由任务和副作用决定,而不是由一个通用百分比决定。
4.3 哪些情况先不要做在线 Canary
Canary 不是所有 Agent 的默认发布方式。先用下面四个问题做判断:
| 当前条件 | 更合适的下一步 | 原因 |
|---|---|---|
| 仍是原型,没有稳定任务集 | 先补 Contract、Eval 和可重复基线 | 没有成功标准,在线差值无法解释 |
| 流量很低,观察窗口只有少量任务 | 回放、Shadow 或人工抽检 | 小样本容易把偶然波动当成版本差异 |
| 没有同期 Control,只有发布前后数据 | 先保留旧版本并建立可比流量 | 时间、用户和依赖变化会污染结论 |
| 动作不可逆且没有补偿路径 | Sandbox、审批和无副作用演练 | 小比例真实错误仍可能造成不可接受后果 |
这里的 rollback 也只表示停止继续向候选版本分配任务并恢复旧版本。它不会撤回已经发送的消息、退款或数据写入;这些副作用仍要依靠幂等键、回执对账和补偿流程处理。
5. Improve:事故怎样变成 Regression Eval
把所有生产输入自动存进数据集并不叫持续改进。真实 Trace 可能包含隐私、偶发依赖故障、错误人工标签和重复样本。
我只在下面条件满足后,才把事故转成 Eval 候选:
- 已确认:确实违反任务合同或运行策略,不是正常拒答。
- 已脱敏:正文、凭据、客户信息和工具载荷不进入评估工件。
- 已去重:同一故障模式不靠重复样本虚增权重。
- 有预期结果:说明应该回答什么,或应该采取哪个控制动作。
- 可重复:测试不依赖已经消失的现场状态。
- 有 Owner:有人决定它何时修复、何时可以关闭。
图 4:生产 Trace 经确认和脱敏后成为 Regression Eval,再通过离线 Gate 与 Canary 推动下一版
图 4:闭环中的自动化可以生成报告、Eval 候选和代码 diff,但默认不自动合并或全量发布。下方数字来自本文固定实验。
Anthropic 的 Agent Eval 方法把评估拆成 Task、Trial、Grader 与 Transcript,并区分探索能力上限的 capability eval 和防止旧问题复发的 regression eval。生产事故更适合进入后者:目标不是证明模型突然更聪明,而是固定一条已经发生过的失败边界。
OpenAI 的 Agent Improvement Loop 示例则把 Trace、反馈、生成 Eval、验证闸门与 Codex handoff 接在一起。一个实际可控的起点是:系统生成候选改动和验证报告,开发者审查 diff 后再合并,而不是让线上失败直接触发自动部署。
关于 OpenAI Evals 的时效说明
截至 2026-08-08,OpenAI 官方文档已经给旧 Evals 平台列出弃用时间表。因此本文使用本地、版本化的通用 Eval 工件,不把闭环绑定到即将关闭的旧平台接口。接入任何托管评估服务前,都应重新核对当前文档。
6. 跟做 Production Loop Lab
本文把前十篇逐步演进的 Agent Reliability Lab 更新到 1.1.1。它不调用真实模型,而是用九个确定性窗口专门验证控制路径。
Lab 只输出 continue、read_only、rollback 等策略决定,不会操作真实流量、部署版本或补偿既有副作用。事故夹具也只包含预先确认、预先脱敏的元数据;代码验证的是这些元数据能否形成稳定 Eval 候选,不实现生产 Trace 的确认、脱敏和去重管道。
6.1 获取实验
可以直接下载本文固定版本:
SHA-256 校验值:
3C6FF3861990C9F6BCBBA8A296BFC311CC1B42154F4FEB0DD21D3CE0E2290174
也可以查看 GitHub 精确提交。
git clone --branch agent-engineering-series https://github.com/RalfNick/ai-agent-learn.git
cd ai-agent-learn/phase-7-agent-engineering/agent-reliability-lab
git checkout 3102d9bab197a67351daf6ae12a5353f61d936c3
python run_lab.py ops-loop --output reports-local
python -m unittest discover -s tests
主命令公开接口只有一个:
python run_lab.py ops-loop --output <report-directory>
6.2 应该看到什么
total_cases: 9
matched_cases: 9
eval_candidates: 6
release checks: 10 / 10 PASS
unit tests: 113 PASS
九个窗口分别验证:
| 场景 | 策略决策 | 原因 |
|---|---|---|
| 健康稳定版本 | continue | 全部在策略范围内 |
| 工具限流 | read_only | 工具错误预算越界 |
| 工具恢复 | continue | 保留故障样本,同时用独立窗口验证恢复 |
| 延迟与队列恶化 | draft_only | p95 延迟先越界 |
| 单任务成本耗尽 | handoff | 停止继续规划 |
| 写入结果未知 | pause_writes | 先查回执,避免重复副作用 |
| Provider 不可用 | handoff | 交给备用路径或人工 |
| Canary 在线回归 | rollback | 离线提升不能覆盖在线错误率 |
| 健康 Canary | promote | 离线和在线门禁全部通过 |
实验会生成五类证据:
operations-review.json # 策略、窗口结果与发布门禁
operations-review.md # 适合人工审查的摘要
operations-runs.jsonl # 每个窗口的结构化决策
incident-evals.jsonl # 由预先确认、预先脱敏元数据生成的候选
operations-failures.md # 合同不匹配与受控事故台账
PASS 只说明九个固定窗口符合声明的控制合同。它不证明真实容量、模型质量、监控覆盖或生产阈值正确。
6.3 两个十分钟故障练习
打开 datasets/operations-cases.jsonl,先不要改预期结果。
练习 A:让健康 Canary 变慢
把 canary-promote 的 p95_latency_ms 从 1900 改为 7000,重新运行命令。CLI 应以非零状态退出,策略决定变成:
rollback / latency_slo_missed
这验证候选版本不会沿用稳定版本的 draft_only 降级,而是退出 Canary。
练习 B:模拟工具恢复
不要改写 tool-throttle-degrade。它是以后防止限流降级失效的回归证据。
改动独立的 tool-recovered:把 tool_error_rate 从 0.02 改为 0.18,但保留预期 continue / within_policy。Gate 应以非零状态退出,并显示策略决定变成 read_only / tool_error_budget_exceeded。恢复为 0.02 后,9/9 场景和 10/10 Gate 应再次通过。
这一步体现两个原则:恢复也需要证据;修复新版本时,不要删除已经发生过的失败案例。
7. 一份可直接改写的生产策略模板
下面不是某个框架配置,而是一份设计草稿。可以先用它和产品、SRE、安全及业务 Owner 对齐,再映射到 Prometheus、OpenTelemetry、云监控或自有发布系统。
production_policy:
scope:
task: "内部知识库问答"
version_tuple: [model, prompt, tools, policy, code]
observe:
window: "由基线与流量决定"
runtime: [p95_latency, queue_age, tool_error, cost_per_task]
quality: [eval_pass, safety_regression, evidence_complete]
outcome: [task_resolved, human_handoff, user_correction]
protect:
unknown_write: pause_writes
tool_unhealthy: read_only
latency_or_queue_missed: draft_only
budget_exhausted: handoff
canary_gate_missed: rollback
recovery_requires: [owner, evidence, consecutive_healthy_windows]
release:
offline_gate: [no_safety_regression, candidate_not_worse]
canary_gate: [absolute_slo, control_delta, cost_budget]
promote_requires: [evidence, reviewer, rollback_point]
improve:
incident_to_eval_requires: [confirmed, redacted, deduplicated]
candidate_requires: [reproducible_eval, reviewed_diff]
automatic_full_release: false
填写时最重要的不是补齐所有字段,而是找出无人负责的空白:谁能暂停写入?Provider 故障时是否有备用路径?谁判断一次失败可以进入 Eval?什么时候允许恢复?
8. 从 Demo 到可靠系统:系列最后怎样闭环
回看整个系列,十一篇文章并不是十一项独立功能:
Contract 定义成功与边界
-> Eval 把它变成可比较证据
-> Context 决定每一步看什么
-> Harness 组织模型、工具与状态
-> Tool 约束真实副作用
-> Durable Loop 让中断可以恢复
-> Trace 解释实际路径
-> Memory 管理跨任务信息
-> Graph 管理复杂依赖和并行状态
-> Human Control 划定高风险动作边界
-> Production Loop 观察、保护并推动下一轮改进
它们最终回到同一个判断:
Agent 的可靠性,不是某次回答看起来正确,而是成功有合同、失败有证据、风险有边界、改动能比较、发布可回滚。
9. 收藏清单:第一次把 Agent 放进生产闭环
- 先选一类任务,不要给“所有 Agent”做总看板。
- 写出运行健康、任务质量和业务结果各三个信号。
- 给每个信号补 Owner、阈值、动作和恢复条件。
- 把未知写回执设成独立高优先级状态。
- 固定版本元组,让模型、Prompt、工具、策略和代码可以一起追踪。
- 建立离线 Gate,再让候选进入受控 Canary。
- 同时比较绝对 SLO 和同期 Control,不让平均分覆盖高风险回归。
- 只把确认、脱敏、去重的事故转成 Regression Eval。
- 自动生成候选和报告可以更快,合并与扩大影响面仍保留明确责任人。
- 定期删除无动作、无人负责、长期不使用的告警。
参考资料
OpenAI
- OpenAI Agents SDK:Tracing
- OpenAI Agents SDK:Configuration
- Build an Agent Improvement Loop with Traces, Evals, and Codex
- Evaluation best practices
Agent Eval、SRE 与观测标准
- Anthropic:Demystifying evals for AI agents
- Google SRE Workbook:Canarying Releases
- Google SRE Workbook:Error Budget Policy
- OpenTelemetry Semantic Conventions
- OpenTelemetry GenAI Attributes