核心摘要

AI Agent 从 POC 到生产需要的是一份晋级契约(Graduation Contract),而不是更精彩的 Demo。团队必须冻结完整发布单元,用代表性结果和关键不变量验证它,在不产生副作用的影子流量中观察真实分布,再分别灰度扩大用户暴露面与执行权限,并在放量前完成回滚演练。发布门禁只能根据版本化证据给出 advance、hold 或 rollback,不能根据单一平均分猜测“已经就绪”。

目录

核心要点

  • POC 只证明在已记录条件下的有限可行性;生产就绪要证明系统能在代表性流量上受控重复。
  • 可发布单元包括模型、Prompt、Tool、Policy、Retrieval、Memory、Runtime、UI 和 Evaluator。
  • 用户暴露面和执行权限是两个独立灰度维度。即使只放量给少数用户,不受限的写权限仍可能造成很大影响。
  • Outcome Check 与确定性不变量的优先级应高于单一 LLM Judge 或综合平均分。
  • 回滚必须可执行、经过演练,并能在不破坏运行中任务的前提下阻止新副作用。

POC 能证明什么,不能证明什么

AI Agent POC 是一个可证伪实验:它验证特定系统和数据集下,一个明确工作流是否具备可行性。POC 不是缩小版生产环境。

区别在于,Demo 通常控制输入、操作人、数据、Tool、时序和重试;生产环境会出现模糊用户请求、过期状态、权限边界、依赖故障、并发、长尾输入、服务责任和真实副作用。

问题 POC 证据 生产证据
工作流能否运行 选定示例能够完成 代表性与对抗性任务的结果测试通过
结果是否有价值 Sponsor 接受一次 Demo 用户相对现有基线完成目标任务
动作是否安全 操作人观察每一步 Policy 独立授权身份、资源、参数与副作用
系统是否可靠 单次运行成功 重复试验、故障注入、恢复与 SLO 窗口通过
经济性是否成立 单次 Session 成本不高 每次成功任务成本包含重试和人工纠正
团队能否运营 Builder 查看控制台日志 Owner、Alert、Runbook、Rollback、Retention 与 Deletion 已验证

不要先问“怎样把这个 Agent 生产化”,而要先问“这个工作负载是否需要 Agent”。Anthropic 区分了路径固定的 Workflow 与由模型动态决定过程的 Agent,并建议只有在复杂度能够改善结果时才增加复杂度。OpenAI 也把 Agent 定位于确实需要模型决策和 Tool Use 的工作流。如果确定性代码、Retrieval 或有界 Workflow 已满足契约,减少自主性本身就是生产改进。

本文只负责晋级与放量决策。Checkpoint、Policy Decision、Effect Journal 与 Reconciliation 等运行时实现,请阅读 Agent Harness 实战;场景设计和 Judge 校准,请阅读 Agent Harness 评估。

先定义晋级契约

晋级契约描述 POC 获得生产流量或执行权限之前必须成立的条件。它应在团队针对最终 Demo 调参之前写完,避免事后悄悄移动成功标准。

契约至少包含:

yaml
workload:
  id: support-refund-assistant
  owner: support-platform
  users: authenticated support agents
  outcome: prepare an evidence-backed refund proposal
  non_goals:
    - approve refunds
    - issue payments
  authority:
    initial: propose_only
    maximum: bounded_write_after_human_approval
  risk_tier: consequential
baselines:
  comparison: current human-assisted workflow
  dataset_revision: support-cases@sha256:8f21
release:
  required_signoffs: [product, operations, security]
  rollback_owner: support-oncall
  fallback: human_only

测量工作负载,而不是只测模型

生产标准应把技术信号连接到用户和业务结果:

  • **Outcome:**目标状态是否真实出现在源系统中?
  • **Quality:**提案是否正确、有依据、完整,并能恰当表达不确定性?
  • **Safety:**身份、租户、Policy、Approval 与 Prohibited Action 不变量是否保持?
  • **Reliability:**Run 是否终止、可恢复,并避免重复或未知副作用?
  • **Experience:**用户能否理解状态、限制、错误和升级路径?
  • **Economics:**每次成功任务的成本与人工投入是多少?

使用相同定义记录现有工作流基线。如果不知道 Baseline、分母、置信区间、严重度分布,以及剩余错误的代价,“Agent 准确率 92%”就无法支持上线决策。

不要套用通用阈值。文案草拟助手与付款 Agent 的损失函数不同。对于跨租户访问等关键不变量,即使总体任务成功率很高,一次观察到的失败也可以阻断发布。

在流量进入前分配责任

生产 Owner 必须能回答:

  1. 谁接受剩余业务风险?
  2. 谁批准发布和每次权限扩张?
  3. 谁收到告警,并能停止新 Run?
  4. 谁对账运行中或 outcome_unknown 的副作用?
  5. 谁维护 Dataset、Policy、Tool 与 Runbook?
  6. 谁向用户说明限制和事故?

NIST AI RMF 将风险管理视为贯穿 AI 生命周期的活动。只有签字文件、没有持续 Owner,不构成生命周期治理。

冻结完整发布单元

Agent Release 是一组版本化组件构成的图,而不是一个模型名称。只比较模型,会遗漏 Prompt、Tool Description、Schema、Retrieval Data、Memory、Policy、Runtime 和用户界面引起的行为变化。

创建不可变 Release Manifest:

json
{
  "release_id": "support-agent-2026-08-23.1",
  "workload_contract": "sha256:1d08",
  "model": "provider/model@snapshot",
  "prompt_bundle": "sha256:4db2",
  "tool_registry": "sha256:908a",
  "policy_bundle": "sha256:ab31",
  "retrieval_snapshot": "sha256:77ce",
  "memory_schema": "v3",
  "runtime_image": "sha256:0f19",
  "ui_contract": "v5",
  "eval_suite": "support-evals@sha256:5b20"
}

每次 Evaluation、Shadow Observation、Canary Decision、Trace 与 Incident 都要引用 release_id。任一组件变化,都要创建新 Candidate 并重新运行受影响门禁。否则团队批准的是一个系统,实际部署的却是另一个系统。

Manifest 也让回滚目标变得准确。如果事故来自 Tool Schema、Retrieval Snapshot 或 Policy Update,仅仅“切回旧模型”并不能恢复已批准版本。

建立生产证据包

生产证据包必须组合确定性、模型、人工、运营与安全证据。Anthropic 的 Agent Evaluation 指南区分 Task、重复 Trial、Grader、Transcript 和真实环境 Outcome,从而避免把一段流畅的最终回复误认为动作已经成功。

使用代表性案例和负例

版本化测试样本并保存其来源:

  • 按真实频率抽样的常见历史任务;
  • 低频但业务关键的任务;
  • 模糊、格式异常、多语言和长上下文输入;
  • 正确行为应是澄清、拒答或不执行的案例;
  • 跨租户、Prompt Injection、数据外泄和越权 Tool 请求;
  • 依赖超时、异常结果、部分故障、取消与重复投递;
  • 已确认的生产事故,每个都转换为 Regression Test。

Synthetic Case 可以扩展覆盖,但不能代替真实分布或领域专家审阅。将探索“Agent 能做到什么”的 Capability Eval,与保护已批准行为的 Regression Eval 分开。

优先校验结果,而不是叙述

当环境存在可观察答案时,优先使用确定性 State Check:

  • 目标 Ticket 是否真实存在?
  • 系统是否没有发起付款?
  • 拒绝后数据库是否保持不变?
  • 相同 Idempotency Key 是否阻止重复副作用?
  • Escalation 是否进入正确队列?

只有语气、完整性等需要解释的质量才使用 LLM Judge,并用人工标签校准。任何未校准 Judge 都不能覆盖失败的授权或 Outcome Invariant。

把运营能力纳入质量

证据包还需要:

领域 必要证据
负载 并发、队列、依赖限制与 Backpressure
延迟 按任务切片统计端到端与分阶段分位数
成本 每次成功任务成本,包含重试与人工复核
恢复 重启、恢复、重复投递与未知结果对账
隐私 收集目的、脱敏、访问、留存与删除
安全 最小权限、注入、污染 Tool Result 与 Secret 处理
无障碍 状态、错误、确认、交接、键盘与辅助功能路径
运营 Dashboard、Alert、Runbook、On-call 与 Rollback Drill

AWS 公开的 Agent Evaluation Blueprint 展示了 Tool Use、Reasoning、Output、多次 Trial 和分阶段部署如何连接 Build-time 与 Production Evaluation。文中的阈值和案例结果只适用于该工作负载,应复用结构,不能复制数字。

沿两个独立维度灰度

安全放量同时控制暴露面和执行权限。暴露面表示谁会看到 Agent 输出;执行权限表示 Agent 能在外部系统中造成什么结果。

阶段 暴露面 执行权限 晋级证据
sandbox 合成与重放案例 模拟 Tool 离线测试和故障注入通过
shadow 抽样生产请求,隐藏输出 无外部副作用 分布、延迟、成本、分歧与隐私检查
internal 已认证内部员工 只读或只提案 工作流效用和升级行为成立
canary 稳定的小范围用户组 白名单内可逆副作用 SLO 窗口通过,无关键不变量失败
expanded 更广的合格用户组 单独扩大权限 Outcome 稳定,支持容量已验证
production 已批准目标人群 仅契约允许的权限 持续监测与回归门禁

影子模式不是无风险镜像

Shadow Run 仍会处理真实数据并消耗依赖。它也需要合法目的、访问控制、Retention Limit、Rate Budget 和 Redaction。必须禁用或 Stub 所有产生副作用的 Tool,不能只依赖一句“不要写入”的 Prompt。比较 Agent 的 Proposed Action 与真实 Outcome,但不把隐藏输出展示给用户。

灰度分组必须稳定

在观察窗口内,同一用户、账号或工作流应持续命中同一个 Release。按请求随机分流可能把多轮 Session 分配给不同 Candidate、污染 Memory,并破坏 Outcome Attribution。

流量和权限要独立扩大。Canary 可以覆盖更多用户但仍保持 propose_only;有界写入应从低后果操作开始,同时配置明确 Limit、Confirmation 和快速 Containment。

开始前声明停止条件

每个阶段都需要三种决定:

  • advance:声明窗口内所有必要证据通过;
  • hold:证据不完整,或可恢复的非关键门禁未通过;
  • rollback:关键不变量失败,或 Candidate 超过预先定义的损失边界。

日历天数或流量百分比不是门禁。只有所需风险切片积累了足够观察量,而且团队理解缺失数据后,才能晋级。

实现确定性发布门禁

以下 Python 3.9+ 示例独立于 Agent 证明 Go/No-Go Policy。示例阈值只属于一个假设的客服工作流;真实团队必须根据后果、基线、流量和恢复能力定义自己的数值。

python
from dataclasses import dataclass
from enum import Enum
from typing import FrozenSet, Tuple


class Stage(str, Enum):
    SANDBOX = "sandbox"
    SHADOW = "shadow"
    INTERNAL = "internal"
    CANARY = "canary"
    PRODUCTION = "production"


class Decision(str, Enum):
    ADVANCE = "advance"
    HOLD = "hold"
    ROLLBACK = "rollback"


@dataclass(frozen=True)
class ReleaseManifest:
    release_id: str
    workload_digest: str
    prompt_digest: str
    tool_registry_digest: str
    policy_digest: str
    eval_suite_digest: str


@dataclass(frozen=True)
class EvidenceWindow:
    completed_tasks: int
    task_success_rate: float
    baseline_success_rate: float
    p95_latency_ms: int
    cost_per_success: float
    critical_failures: int
    unauthorized_effects: int
    unknown_effects: int
    signoffs: FrozenSet[str]


@dataclass(frozen=True)
class GatePolicy:
    minimum_observations: int
    minimum_success_rate: float
    maximum_regression: float
    maximum_p95_latency_ms: int
    maximum_cost_per_success: float
    required_signoffs: FrozenSet[str]


@dataclass(frozen=True)
class GateResult:
    decision: Decision
    reasons: Tuple[str, ...]


def evaluate_release(
    manifest: ReleaseManifest,
    window: EvidenceWindow,
    policy: GatePolicy,
) -> GateResult:
    manifest_values = (
        manifest.release_id,
        manifest.workload_digest,
        manifest.prompt_digest,
        manifest.tool_registry_digest,
        manifest.policy_digest,
        manifest.eval_suite_digest,
    )
    if not all(manifest_values):
        return GateResult(Decision.HOLD, ("incomplete_manifest",))

    critical = []
    if window.critical_failures:
        critical.append("critical_invariant_failed")
    if window.unauthorized_effects:
        critical.append("unauthorized_effect")
    if window.unknown_effects:
        critical.append("unknown_effect")
    if critical:
        return GateResult(Decision.ROLLBACK, tuple(critical))

    reasons = []
    if window.completed_tasks < policy.minimum_observations:
        reasons.append("insufficient_observations")
    if window.task_success_rate < policy.minimum_success_rate:
        reasons.append("success_slo_missed")
    if (
        window.baseline_success_rate - window.task_success_rate
        > policy.maximum_regression
    ):
        reasons.append("baseline_regression")
    if window.p95_latency_ms > policy.maximum_p95_latency_ms:
        reasons.append("latency_slo_missed")
    if window.cost_per_success > policy.maximum_cost_per_success:
        reasons.append("cost_budget_exceeded")
    if not policy.required_signoffs.issubset(window.signoffs):
        reasons.append("missing_signoff")

    if reasons:
        return GateResult(Decision.HOLD, tuple(reasons))
    return GateResult(Decision.ADVANCE, ())


manifest = ReleaseManifest(
    release_id="support-agent-2026-08-23.1",
    workload_digest="sha256:1d08",
    prompt_digest="sha256:4db2",
    tool_registry_digest="sha256:908a",
    policy_digest="sha256:ab31",
    eval_suite_digest="sha256:5b20",
)
policy = GatePolicy(
    minimum_observations=500,
    minimum_success_rate=0.90,
    maximum_regression=0.01,
    maximum_p95_latency_ms=4000,
    maximum_cost_per_success=0.25,
    required_signoffs=frozenset({"product", "operations", "security"}),
)
healthy = EvidenceWindow(
    completed_tasks=800,
    task_success_rate=0.93,
    baseline_success_rate=0.92,
    p95_latency_ms=3200,
    cost_per_success=0.18,
    critical_failures=0,
    unauthorized_effects=0,
    unknown_effects=0,
    signoffs=frozenset({"product", "operations", "security"}),
)
unsafe = EvidenceWindow(
    completed_tasks=900,
    task_success_rate=0.96,
    baseline_success_rate=0.92,
    p95_latency_ms=2800,
    cost_per_success=0.17,
    critical_failures=0,
    unauthorized_effects=1,
    unknown_effects=0,
    signoffs=frozenset({"product", "operations", "security"}),
)

assert evaluate_release(manifest, healthy, policy).decision == Decision.ADVANCE
assert evaluate_release(manifest, unsafe, policy).decision == Decision.ROLLBACK
print("advance rollback")

预期输出:

text
advance rollback

顺序非常重要:关键不变量应先触发 Rollback,不能被平均质量掩盖。证据不足只产生 hold,不能通过临时协商变成 Pass。

上线后持续运营 Agent

生产环境是新的证据阶段,不是评估终点。Microsoft Agent Lifecycle 在发布后仍要求持续监测和用户反馈;NIST 则把 Measurement 与 Management 放在完整 AI 生命周期中。

记录稳定事件契约

记录:

json
{
  "run_id": "run-882",
  "release_id": "support-agent-2026-08-23.1",
  "workload_id": "support-refund-assistant",
  "cohort": "canary-a",
  "authority": "propose_only",
  "policy_decision": "approval_required",
  "tool_result_class": "success",
  "outcome": "human_approved",
  "latency_ms": 2810,
  "cost_microunits": 184000,
  "redaction_profile": "support-v3"
}

默认不要记录原始 Credential、完整私密文档、不必要的 Tool Payload 或隐藏思维链。OpenTelemetry GenAI Semantic Conventions 已迁移到独立仓库并持续演进;应用应维护自己的稳定事件契约,再在 Telemetry Boundary 映射到当前规范版本。

保持兜底路径可用

Rollback 可以分级执行:

  1. 停止接收新的 Agent Run;
  2. 禁用写权限,同时保留读取或只提案服务;
  3. 将合格工作负载切回上一份 Manifest;
  4. 把流量切回人工或确定性 Workflow;
  5. 在重试前对账运行中和未知结果的副作用。

这些模式必须在 Canary 阶段实际演练。一个从未执行过的 Feature Flag 不能作为回滚证据。

把事故转换成受控变更

每个已确认故障都应产生:

  • 与 run_id、release_id 绑定的 Incident Record;
  • Severity 与受影响人群;
  • 经过脱敏且可复现的 Scenario;
  • 新增或修正后的 Evaluator;
  • 包含修复的 Candidate Manifest;
  • 重新放量前相同的分阶段门禁。

用户点踩、Judge Score、Latency Alert 和 Support Ticket 都只是分诊信号。只有经过标注和 Root Cause Analysis 后,它们才能成为发布证据。

验证故障与回滚路径

授予生产权限前,应主动注入:

故障 预期控制
模型超时或 Provider 故障 有界重试、Fallback 或显式未完成状态
Tool Result 格式错误 Schema 拒绝,不推断成功
重复投递 Stable Idempotency Key,只产生一次外部副作用
派发后超时 outcome_unknown,对账后再决定是否重试
跨租户资源 Tool 执行前拒绝
审批过期或参数改变 拒绝并请求新的绑定审批
Retrieval 或 Policy 过期 暂停发布,高风险动作 Fail Closed
Tool 或检索文本被污染 不改变 Policy 或 Authority
Loop 或 Retry Storm Step、Time 和 Spend Budget 终止运行
Telemetry 故障 进入已定义降级模式,不静默丢失必要审计证据
Active Run 中回滚 停止新任务并对账现有副作用
人工队列过载 在不安全自动化前降低权限或流量

Agent 可观测性工程解释 Trace Contract;Agent Memory Persistence解释状态保留与恢复;Prompt Injection 防御解释对抗内容。本文只把它们的产物作为发布证据。

生产就绪检查清单

只有满足以下条件,Agent 才能晋级:

  1. Workload Contract、Baseline、Non-goal、Authority 与 Risk Tier 已批准。
  2. 完整 Release Manifest 不可变且可以部署。
  3. 代表性、负例、多轮与故障场景已版本化。
  4. 确定性 Outcome 和 Critical Invariant Grader 通过。
  5. Model Judge 已针对目标切片用人工标签校准。
  6. Capacity、Latency、Cost per Success、Privacy 与 Deletion 测试通过。
  7. Shadow Mode 禁用副作用,且隐私控制正常运行。
  8. Canary Assignment 稳定,暴露面和执行权限都有边界。
  9. Alert、Owner、Runbook、Kill Switch 与 Rollback Drill 已验证。
  10. Production Failure 会进入受控 Regression 与 Release Cycle。

常见问题

AI Agent POC 实际能证明什么?

POC 证明的是有边界技术可行性。它不证明生产分布上的可靠行为、授权动作、可接受的单位经济性、恢复能力、隐私合规、用户采用或支持责任。应把 POC 配置与失败保留为证据,而不是把成功 Demo 当作上线决策。

AI Agent 生产就绪门禁必须包含什么?

把 Workload Contract 和完整 Release Manifest 绑定到代表性结果测试、关键不变量、运营预算、隐私检查、分阶段观察、回滚准备度与责任人签署。缺少精确系统、Dataset、Policy、观察窗口和分母的分数,不是发布证据。

AI Agent 的影子模式与灰度发布有什么区别?

Shadow Mode 观察代表性生产请求,但隐藏输出并禁用副作用。Canary 服务一个有边界且稳定的 Cohort,并可能允许严格受限的真实副作用。前者以较低用户影响验证分布匹配,后者在可恢复范围内验证真实影响和运营响应。

可以套用通用通过率或固定灰度比例吗?

不可以。阈值应来自工作负载后果、当前基线、不确定性、请求量和恢复能力,并保留每个切片的分母与置信度。即使总体成功率很高,一次关键授权失败也可以阻断发布;低风险草拟工具则可以允许更多复核与纠正。

哪些情况必须回滚 AI Agent?

关键不变量失败、出现越权或重复副作用、结果无法对账、必要审计证据缺失,或预先声明的质量、可靠性、延迟、成本、隐私和升级边界被突破时,应立即回滚。所有触发器都要在生产流量进入前定义并演练。

总结

AI Agent 只有在特定、不可变的 Release 能够在代表性条件下证明受控价值时,才算从 POC 晋级。应在 Demo 前定义契约,冻结所有影响行为的组件,把 Outcome Test 与 Critical Invariant 结合,分开控制用户暴露面和执行权限,并只通过证据门禁逐级放量。生产仍是持续监测阶段,每次重大变更都要重新评估,且始终保留回滚与事故学习闭环。

相关资源

一手来源