附录 E:上线与运维清单

Agent 从 demo 走到生产,真正考验的不是“能不能回答一次”,而是“能不能长期、可控、可回滚地服务用户”。这份清单把全书的生产化内容压成一个上线前后都能用的 playbook。

它的用法和正文不同:正文是讲原理,这份附录是给你勾的。建议把它复制进你团队的 Wiki,每次发布前对照过一遍;每个条目都尽量给了“为什么这么做、具体怎么做、常见坑”,而不只是一句口号。全篇以一个跨境电商场景贯穿:一个帮卖家做选品与竞品调研的 Research Agent——它会抓竞品链接、查关键词热度、算利润空间、写调研简报,跨多个工具、跑几分钟甚至几十分钟,还要面对多个卖家租户。这类 Agent 恰好把上线运维的所有难点都占全了:长任务、高成本、外部依赖多、多租户。

上线前:先定运行形态

先回答它以什么方式运行——形态决定了你后面所有的隔离、鉴权、成本策略:

形态适合场景重点风险
本地 CLI个人/小团队、编码 Agent、内部工具凭据散落、危险命令、不可复现
Web/RPC 服务SaaS、后台任务、远程驱动鉴权、会话隔离、断线恢复
后台 Agent长时间调研、定时巡检、异步处理成本失控、任务挂死、状态不可见
多租户平台多客户、多团队共享数据隔离、资源公平、审计合规

pi 的优势是同一套运行时可以长出 CLI、Web/RPC 和后台形态;但越靠近公网和多租户,越要把安全、预算、可观测性前置。

为什么形态要先定? 因为它决定了“错一次的代价”。本地 CLI 里一个 Research Agent 跑飞了,最多烧掉你自己的 key;同样的逻辑放到多租户 SaaS 上,一个租户的调研任务写坏了共享缓存,可能污染所有卖家的选品结果。我们的 Research Agent 大概率是“Web/RPC 服务 + 后台 Agent”的组合:卖家在前端点“帮我调研这个类目”,请求进入队列,后台 Agent 异步跑几分钟再回填结果。这意味着从第一天起就要面对断线恢复(卖家关了浏览器,任务不能死)和成本失控(一次调研可能触发几十次模型调用和上百次抓取)。后台形态的细节见第 33 章。

踩坑:最常见的错误是“demo 用 CLI 形态写,上线直接套一层 HTTP 就发”。CLI 里默认信任本机、凭据放环境变量、危险命令随便跑——这些假设一旦暴露到公网就是漏洞。形态切换时,安全与隔离假设必须重新过一遍,不能沿用。

上线前的准入门槛

不是“功能做完了”就能上线,而是“这些指标达标了”才能上。给 Research Agent 设一组硬性准入门槛(go/no-go gate),任何一项不达标就不发:

门槛项达标标准(示例,按业务调)为什么
回归通过率核心任务集(附录 D)通过率 ≥ 95%,高风险样本 100%低于此说明基本能力不稳
p95 端到端延迟一次调研 ≤ 3 分钟(后台任务可放宽但要有上限)超时任务会堆积、烧钱
单任务成本平均 ≤ $0.5,p95 ≤ $1.5没有上限的成本 = 没有商业模式
引用正确率调研简报里的数据能溯源到抓取来源 ≥ 90%编造竞品数据会误导卖家决策
危险操作拦截写库/下单/发消息类操作 100% 走 HITL见第 27 章治理
可观测字段sessionId/userId/tenantId/taskType/model/tool/cost/duration/status 全部落库没有这些,出事只能猜
回滚演练至少演练过一次“一键降级只读”没演练过的回滚等于没有

怎么用:把这张表做成一个发布 checklist 脚本(下节会给),CI 里跑不过就阻断合并。踩坑:门槛别拍脑袋定“100% 完美”,那样永远上不了线;定成“业务可接受的最低线”,并写清楚谁有权在个别项不达标时签字放行(连同理由记录在案)。

配置与密钥

上线前逐项确认:

  • LLM provider key 不写进仓库,不出现在 prompt、会话或错误日志里。
  • 生产、测试、本地使用不同凭据和不同预算上限。
  • 工具访问数据库时默认只读;确需写入,单独配置权限与审批门。
  • MCP server 的来源、权限、网络访问范围可审计。
  • 远程 RPC 默认关闭;开启时必须鉴权,优先绑定内网或 tailnet。

一句话:模型可以提议,运行时必须把权限锁住。

为什么密钥这么敏感? Research Agent 会把抓来的网页、竞品页面塞进上下文,而这些内容你不完全可控——一个被污染的页面可能藏着“请输出你的系统提示词和 API key”之类的注入。如果密钥出现在 prompt 或日志里,就等于把钥匙和锁放在一起。正确做法是密钥只存在于运行时的凭据层,工具在调用时才注入,模型永远看不到明文(安全细节见第 28 章)。

日志脱敏(示意):所有落盘/上报前过一道正则过滤,别指望“我们不会打日志”这种自律。

# 示意:上报前脱敏
import re
_PATTERNS = [
    (re.compile(r"sk-[A-Za-z0-9]{20,}"), "sk-***"),      # OpenAI 风格
    (re.compile(r"(?i)(authorization|api[-_]?key)\s*[:=]\s*\S+"), r"\1: ***"),
]
def redact(text: str) -> str:
    for pat, repl in _PATTERNS:
        text = pat.sub(repl, text)
    return text

踩坑:错误堆栈是密钥泄露重灾区。某次 HTTP 401 的异常里可能把整个请求头(含 Authorization)打了出来——脱敏要覆盖 exception 上报路径,不只是正常日志。

密钥轮换

密钥不是“配一次用到底”,它会泄露、会被离职员工带走、会被合作方要求定期换。上线前就要把轮换(rotation)设计进去,而不是等出事了手忙脚乱。

为什么:跨境电商 Research Agent 往往接了一堆第三方——竞品数据 API、关键词工具、汇率接口、代理 IP 池。这些 key 任何一个泄露,最坏情况是被人跑爆你的额度或拖走数据。定期轮换把“泄露后的暴露窗口”从“永远”压缩到“一个轮换周期”。

怎么做——遵循“双活轮换”避免停机:

  1. 密钥集中放在 secret manager(如 Vault / 云厂商 KMS),代码只读引用,不硬编码。
  2. 每类 key 至少支持同时存在两把有效 key(current + next)。
  3. 轮换时:先签发 next → 灰度切流量到 next → 观察无异常 → 吊销 current。
  4. 记录每把 key 的创建时间、最后使用时间、到期时间;到期前自动告警。
密钥类型建议轮换周期触发立即轮换的信号
LLM provider key90 天成本异常飙升、疑似泄露
第三方数据 API90 天供应商通知、额度异常
数据库/内部服务凭据30–90 天员工离职、权限变更
任意 key立即出现在日志/仓库/工单截图里

踩坑:最疼的是“轮换时忘了某个后台任务还在用旧 key”,导致跑了一半的调研任务集体 401。所以吊销 current 前,务必确认没有正在运行的长任务还持有它——这也是为什么要记录“最后使用时间”。

依赖与模型版本管理

Agent 的行为不只取决于你的代码,还取决于它依赖的模型和外部服务——而这些你往往控制不了。模型供应商悄悄更新了版本、某个 MCP server 改了返回格式、竞品网站改版导致抓取失效,都会让“昨天还好好的” Agent 今天翻车。

为什么要钉版本:如果你的 prompt 是针对 some-model-2026-06 调优的,供应商把 latest 指向了新版本,你的调研简报格式可能一夜之间就变了样。永远钉具体版本号,不要用 latest

怎么做

  • 模型:钉到带日期的具体版本;升级新版本走灰度(见下节),并在评测集(附录 D)上先跑一遍回归。
  • 外部依赖:给每个 MCP server / 第三方 API 记录版本或 commit,并写契约测试——用固定输入验证返回结构没变。
  • 抓取目标:竞品页面结构会变,抓取器要能检测“解析失败率突增”并告警,而不是默默返回空数据。
# 示意:pin 依赖清单,纳入版本控制
models:
  research_writer: anthropic/claude-x-2026-06-01   # 不用 latest
  cheap_summarizer: some-provider/mini-2026-05-10
mcp_servers:
  keyword-tool: { version: "1.4.2", contract_test: tests/keyword_contract.py }
  competitor-scraper: { version: "0.9.0", contract_test: tests/scrape_contract.py }

踩坑:模型升级往往“能力更强但格式微变”。别假设新模型一定更好——它可能更啰嗦、更爱加免责声明,把你精心设计的结构化输出撑破。升级必须过评测,不能凭“听说新版更强”就直接切。

发布前检查

类别检查项对应章节
Context长会话会压缩吗?压缩摘要保留关键事实吗?第 9 章
Memory长期记忆有提炼、遗忘和用户可控入口吗?第 10 章
RAG检索有来源、版本、score,回答会引用依据吗?第 11 章
State会话/任务状态可恢复、可寻址、可回放吗?第 11、23 章
Tools工具最小权限、参数 schema 清楚、错误结构化吗?第 4 章
HITL高风险动作会暂停并请求人工确认吗?第 7、26 章
Observability会话、token、成本、工具调用都可追踪吗?第 25 章
Budget单会话、单用户、单租户有预算上限吗?第 26 章
Security不可信执行有容器/微 VM/受限环境吗?第 28 章
Multi-tenant数据、执行、资源、配置四层隔离了吗?第 29 章
Evaluation核心任务集与高风险样本跑过回归吗?附录 D

这张表应成为第 35 章综合实战的发布门槛。把它做成一个能在 CI 里跑的脚本,比贴在墙上更可靠:

#!/usr/bin/env bash
# 示意:发布前门禁脚本,任一失败即退出非零,阻断发布
set -euo pipefail

echo "== 1. 回归评测 =="
npm run eval:core         # 附录 D 核心任务集,通过率写入 report.json
node scripts/check_threshold.js report.json --pass-rate 0.95

echo "== 2. 密钥扫描 =="
git grep -nE 'sk-[A-Za-z0-9]{20,}' && { echo "发现疑似密钥!"; exit 1; } || true

echo "== 3. 模型版本已 pin =="
grep -q 'latest' config/models.yaml && { echo "禁止使用 latest"; exit 1; } || true

echo "== 4. 回滚开关就绪 =="
node scripts/check_kill_switch.js   # 确认降级开关可用且已演练

echo "全部通过,可以发布 ✅"

踩坑:检查项写在文档里没人看,写成人工 checklist 会被“这次赶时间先跳过”。凡是能自动化的门禁,尽量做进 CI;实在要人工判断的(如“这次改动风险有多大”),也要留签字记录。

灰度与金丝雀发布

新版本别一次切 100% 流量。Research Agent 尤其危险——它的问题往往不是“崩溃”(那反而好发现),而是悄悄变差:简报开始编数据、成本悄悄涨、某类目调研突然跑偏。这些只有在真实流量下才暴露,所以要用金丝雀(canary)小流量先探路。

怎么做——按比例放量,每一档都设自动回滚条件

阶段流量比例观察时长放行标准自动回滚条件
金丝雀1%30 min无错误率上升、成本平稳错误率 > 基线 2×,或单任务成本 > 基线 1.5×
小灰度10%2 h引用正确率、延迟不劣化引用正确率下降 > 5pp
大灰度50%半天各租户表现一致任一租户错误率异常
全量100%持续观察触发即降级到旧版本

关键:灰度要能按租户/用户维度切,而不只是按请求随机切。把大客户放在后面的档位,先用内部账号和小卖家试。同时保证同一用户在观察期内落在同一版本,否则体验会闪烁、指标也没法归因。

// 示意:按 tenant 做稳定分桶的金丝雀路由
function pickVersion(tenantId: string, canaryPct: number): "new" | "old" {
  const bucket = hashToUnit(tenantId);      // 0..1 稳定哈希
  return bucket < canaryPct ? "new" : "old"; // 同租户始终同版本
}

踩坑:金丝雀期太短是常见错误。Agent 的成本和质量问题有滞后性——一个“偶尔多绕三轮”的 bug,1% 流量跑 5 分钟看不出来,要跑够样本量才显形。宁可慢一点。

上线前明确谁对能力结果负责

Agent 上线不是工程团队把服务交给运维就结束了。一项进入经营流程的 AI 能力,需要一个明确的 Capability Owner(能力负责人),持续协调业务、产品、工程、数据和风控,并对“是否继续运行、何时扩量、何时降级”作出决定。

角色持续责任
业务负责人确认经营目标、流程边界和结果基线,判断业务结果是否成立。
能力负责人维护路线图、指标、自动化等级和扩量节奏,组织定期复盘。
工程与平台团队保障运行时、上下文、工具、观测、成本和发布质量。
数据 / 知识负责人维护数据口径、知识版本、更新频率与访问权限。
风控与安全审批高风险动作的策略、权限、审计和事故响应机制。

建立固定的能力复盘节奏

上线初期可按周复盘,稳定后按月复盘。每次至少检查五组信息:经营结果、流程效率、AI 质量、风险事件、单位有效结果成本。复盘输出不是一份汇报,而是明确的动作:新增回归样本、调整上下文、修改策略、降低或提高自动化等级、暂停某类任务,或扩展到下一个流程。

没有负责人和复盘节奏,Agent 只是一项会上线也会逐渐失真的软件功能;有了持续运营机制,它才可能成为企业长期积累的 AI 能力。

Day-2 运维:该看哪些信号

上线后真正要盯的是这些信号:

  • 成本:按用户、租户、任务、模型、工具聚合。
  • 延迟:模型调用、工具调用、RAG 检索、多 Agent 子任务分别看。
  • 失败率:工具错误、模型限流、策略拒绝、人工审批超时分开统计。
  • 质量:核心任务评测分数、RAG 引用正确率、用户重试率。
  • 安全:被阻止的危险工具调用、越权访问尝试、异常租户流量。
  • 队列:后台 Agent 的等待时间、运行时长、取消/重试次数。

如果只能先做一件事,就先把 sessionId/userId/tenantId/taskType/model/tool/cost/duration/status 这些字段打通。没有这些维度,出了事只能猜。

Agent 特有的、传统监控看不到的信号,尤其要盯:

  • 单任务工具调用次数 / 推理轮数:Research Agent 正常一次调研调 10–20 次工具就够了。如果某类任务突然平均调 80 次,多半是陷入了循环或反复重试——这是成本失控最早的征兆,比看账单快得多。
  • 上下文 token 增长曲线:长任务的上下文会不会无限膨胀?压缩(第 9 章)有没有真的生效?
  • 工具错误的“结构”:是外部依赖挂了(抓取超时),还是模型传了非法参数(schema 不匹配)?前者是运维问题,后者是 prompt/工具描述问题,处理路径完全不同。
  • “看似成功”的失败:任务 status=success 但产出是空简报或全是免责声明。这类最阴险,靠 status 发现不了,得靠质量评测和用户重试率兜底。

怎么做:把这些聚合成两三块看板——一块成本/延迟(给运维盯),一块质量/安全(给产品和风控盯),一块队列健康(给后台任务盯)。可观测的完整方案见第 25 章。踩坑:只加了 dashboard 没加告警,等于让人 24 小时盯屏——没人做得到。看板是用来事后排查的,实时靠告警。

监控告警:阈值该怎么定

告警的艺术在于既不漏报也不吵。一份可直接抄的起步阈值表(数值按你的基线调):

信号告警阈值(示例)级别建议动作
单任务成本> p95 × 2,或 > $2检查是否循环;必要时熔断该任务类型
小时总成本> 日预算 / 10触发成本护栏,见下节
工具错误率5 min 内 > 10%看是外部依赖还是 schema 问题
模型限流(429)5 min 内 > 5%降级到备用 provider / 排队
p95 端到端延迟> 基线 × 1.5查队列积压、外部依赖变慢
HITL 审批积压待审 > 20 或最久等待 > 30 min通知审批人,防任务饿死
引用正确率日均 < 85%质量回归,考虑回滚模型版本
被拦截危险操作单租户 5 min 内 > 3 次疑似注入攻击或异常租户,见第 28 章
队列等待时长p95 > 5 min扩容 worker 或限流入口

为什么要分级:高(P1)要电话叫醒人,中(P2)进工作时段处理,别把所有告警都设成 P1——那样很快就没人当回事(告警疲劳)。怎么定阈值:先用相对基线(“× 2”“× 1.5”),跑一两周积累数据后再收紧。踩坑:绝对阈值(“成本 > $2”)在业务量波动时容易误报或漏报,尽量用“相对基线 + 绝对兜底”两条一起。

成本护栏与熔断

Research Agent 是“烧钱型”Agent——一次调研 = 多次模型调用 × 大上下文 + 大量抓取。没有护栏,一个 bug 或一次滥用就能在几小时内烧掉一个月预算。护栏要分层,且能自动动手,不能只告警。

四层预算上限(预算体系见第 26 章):

层级上限(示例)超限动作
单任务$2 / 任务硬停该任务,标记 budget_exceeded,返回已有的部分结果
单用户$20 / 天该用户后续任务排队或拒绝,提示升级套餐
单租户$500 / 天该租户降级到便宜模型 + 限并发
全局$5000 / 天触发全局熔断,只保留付费大客户

熔断(circuit breaker)示意——超限时自动降级而非直接报错:

# 示意:任务执行前的成本护栏检查
def before_task(ctx):
    if spent(ctx.task_id) > TASK_CAP:
        raise BudgetExceeded(partial=collect_partial_result(ctx))  # 返回半成品,别白烧
    if spent_today(ctx.tenant_id) > TENANT_CAP:
        ctx.model = CHEAP_MODEL          # 降级模型
        ctx.max_tool_calls = 8           # 收紧循环
    if global_spent_today() > GLOBAL_CAP:
        if not ctx.is_priority_tenant:
            raise CircuitOpen("全局成本熔断,非优先租户暂停")

为什么要返回半成品:一次跑到 $2 才被砍的调研任务,如果直接丢弃就是纯亏损;把“已抓到的竞品数据 + 已完成的部分分析”返回给卖家,钱至少没白花。踩坑:熔断一定要有手动恢复开关冷却期——别做成“熔断→自动重试→立刻又熔断”的死循环。恢复要人工确认根因已解决。

回滚与降级

Agent 系统的回滚不只是回代码,还包括:

  • 回滚 prompt / instructions 版本。
  • 回滚工具描述、schema 或权限配置。
  • 回滚模型 provider 或模型版本。
  • 回滚 RAG 索引版本。
  • 暂停高风险工具,只保留只读能力。
  • 把自动执行降级为 human-in-the-loop。
  • 关闭后台任务入口,只保留交互式模式。

每一次上线都应该知道:“如果 10 分钟后成本暴涨或错误率上升,我先关哪个开关?”

为什么 Agent 回滚比普通服务难:普通服务回滚就是回代码镜像;Agent 的“行为”分散在代码、prompt、工具描述、模型版本、RAG 索引五处,任何一处变了都可能翻车,所以要能分别回滚。把这些都做成运行时可切的开关(feature flag / 配置中心),而不是每次都重新发版——出事时你没时间等 CI。

降级开关表(一份能贴在事故 runbook 里的对照表):

开关打开后的效果何时打开
readonly_mode禁用所有写操作,只保留调研/查询疑似数据被写坏、越权
force_hitl所有敏感操作强制人工确认质量下滑、疑似注入
cheap_model_only全量切便宜模型成本告警、贵模型限流
disable_background关后台任务入口,只留交互模式队列雪崩、成本失控
pin_prev_promptprompt/instructions 回退上一版新 prompt 导致行为异常
pin_prev_model模型版本回退新模型版本质量劣化
freeze_rag_indexRAG 锁回上一个索引版本新索引导致检索跑偏

回滚触发条件(配合灰度和告警,能自动触发的就别靠人反应):

  • 金丝雀阶段错误率 > 基线 2×,或单任务成本 > 基线 1.5× → 自动回滚版本。
  • 引用正确率日均跌破 85% → 回退模型/prompt 版本,同时开 force_hitl
  • 全局小时成本 > 日预算 1/8 → 开 cheap_model_only + disable_background
  • 被拦截危险操作在单租户内激增 → 对该租户开 readonly_mode 并告警风控。

踩坑没演练过的回滚等于没有回滚。 上线前务必真的按一次每个开关,确认它生效、且不会引发次生故障(比如切便宜模型后 schema 输出撑破反而错更多)。这也是准入门槛里“回滚演练”那一项存在的原因。

事故响应与 Runbook

告警响了、开关有了,还缺一样:出事时按什么流程走。别指望临场发挥——凌晨三点被叫醒的人需要一份能照着做的 runbook。

通用响应流程(示意,贴进值班文档)

1. 止血(分钟级):先按降级开关表把伤害止住,不急着找根因。
   —— 成本失控 → cheap_model_only + disable_background
   —— 行为异常 → force_hitl 或 pin_prev_prompt / pin_prev_model
   —— 疑似安全 → readonly_mode,通知风控(第 28 章)
2. 定级:判断 P1(影响付费大客户/资金/数据)还是 P2,拉对应的人。
3. 定位:用会话回放(第 24 章)找到出错的那一步——是模型、工具、
   还是外部依赖?看是哪次上线/版本引入的。
4. 修复 + 灰度重新放量:别直接全量,走一遍金丝雀。
5. 复盘:写事故报告,产出可执行的改进项(新告警、新护栏、新回归样本)。

为什么止血优先于定位:卖家的调研任务在批量编造数据、成本在飙升,这时先关阀门比“搞清楚为什么”重要得多。定位可以事后慢慢做,损失止不住就是真金白银。

Runbook 里每类典型事故都该有一页,至少覆盖:成本暴涨、模型限流/供应商宕机、抓取依赖大面积失效、疑似 prompt 注入、某租户数据疑似泄露。每页写清:征兆是什么、先按哪个开关、找谁、怎么验证已恢复踩坑:runbook 写完就烂在文档里没人更新。规定每次事故复盘必须回头改 runbook,否则下次还是抓瞎;而复盘产出的新回归样本要加进附录 D 的评测集,让同一个坑不会踩第二次。

实验清单

读完全书后,可以用这 10 个小实验检验自己是否真的掌握了 Harness 思路:

  1. 给 pi 注册一个只读业务工具,并写清工具描述与参数 schema。
  2. 接一个 MCP server,让 Agent 使用外部通用工具。
  3. 写一个 Skill,把你的领域流程封装成 SKILL.md
  4. 用 Hook 拦截危险命令,要求人工确认。
  5. 做一个 search_knowledge RAG 工具,返回 text/source/score
  6. 跑一次长会话,观察 compaction 前后上下文变化。
  7. 用会话文件回放一次失败任务,定位是哪一步出错。
  8. 给同一个任务跑便宜模型和贵模型,比较成本与质量。
  9. 把一个会话通过 RPC 远程驱动,并验证断线恢复。
  10. 挑 20 个真实任务样本,做成附录 D 风格的回归集。

完成这些实验,比背 API 更重要。API 会变,生产 Agent 的控制点不会变。

一条总原则

上线不是把 Agent 放到服务器上,而是把它放进一套能观测、能限制、能回滚、能持续评测的运行体系里。

没有这套体系,demo 越聪明,生产风险越大。再浓缩成一句可以背下来的操作口诀:先能看见(可观测),才敢放量(灰度);先能踩刹车(护栏与降级),才敢上路(发布);先演练过回滚,才算真的上线。