Agent 版本机制、标注测试集评测、Session 版本锁定语义与灰度回滚的做法,把提示词从应用代码剥离为服务端可版本化的资源。
概述
本篇介绍 Managed Agents 的 Agent 版本机制、版本灰度与回滚做法,示例统一使用 REST/curl。
核心是把「提示词」从应用代码里剥离出来,变成服务端可版本化的资源,从而独立于代码走评审与晋升流程。涉及的机制:POST /agents/{id}(更新即升 version)、Session 与 Agent 版本的绑定关系(支持显式锁定历史版本)、以及 GET /agents/{id}/versions 列出历史版本。
场景
某产品支持系统用大模型把工单路由到正确的团队。PM 希望让更多 API 相关的工单流向平台团队。
在过去,改一句路由提示词要走「PR + CI + 部署」,回滚也是同一套流程。用 Managed Agents 后,提示词存在服务端:每次 POST /agents/{id} 都会产生一个新的、不可变的版本;Session 在创建时锁定 Agent 的某个版本快照(默认是最新版,也可显式指定)。若新版本效果下降,回滚就是「发布一个与旧版本等价的新版本」,之后新建的 Session 立刻用上它,无需部署。
学完本篇能够:
- 建一个返回
version: 1的 Agent; - 对某个版本用标注测试集打分;
- 发布 v2,看到版本号自增;
- 不改 Agent 当前版本,直接锁定历史版本做对比评测;
- 把出现回归的 Agent 拉回 v1 行为,全程无需部署。
环境变量约定
本篇 curl 示例统一使用以下变量:
Authorization: Bearer $DASHSCOPE_API_KEY,一把 Key 覆盖工作空间内全部资源。当前区域仅 cn-beijing。模型 ID 用 qwen3.8-max / qwen3.7-max / qwen3.7-plus(本篇用 qwen3.7-plus,分类任务足够)。
本篇的 Agent 是纯 LLM 分类器(无工具调用),不需要 Environment——Session 不挂
environment_id 也能跑。只有要跑 bash / 读写文件的 Agent 才需要沙箱,见入门:搭一个数据分析 Agent。第一步:建 Agent(v1)
system prompt 让 Agent 把每条工单分类到「团队 + 优先级」,只回一行 JSON:
version: 1。之后每次 POST /agents/{id}(注意:更新动词是 POST,不是 PATCH——PATCH 返回 405;body 里 name 与当前 version 都是必填)都在同一个 id 下产生新版本,版本号自增;这个版本号就是后续绑定和回滚的依据。把响应的 id 填入 AGENT_ID。
第二步:加载标注测试集
评测 fixture 用下面 4 条工单(每团队 1 条;其中 T3 特意写成「提到 API 用量的账单问题」,为后面制造回归):
第三步:给 v1 打分(建立基线)
对每条工单跑一遍 v1,得到基线成绩。每条工单的评测流程(下称 triage)如下:
- 创建一个 Session(
agent传 Agent ID); - 发一条
message事件把工单内容送进去; - 轮询历史事件,直到 Session 回到 idle;
- 收集
assistant输出文本,解析出 JSON,与 ground truth 比对; - 删除 Session(评测完即删,不留痕)。
Session 与 Agent 版本的绑定语义(重要)
agent 字段有两种传法,决定了 Session 锁定哪个版本:
agent 字段形式 | 锁定的版本 |
|---|---|
"agent_xxx"(字符串) | 创建那一刻的最新版本 |
{ "id": "agent_xxx", "version": N }(对象) | 显式指定的版本 N;版本不存在则 404 "Agent not found" |
{ "id": "agent_xxx" }(对象不带 version) | 同字符串形式,锁最新 |
- Session 在整个生命周期内都使用这份快照,此后即使 Agent 继续升版,这条已存在的 Session 也不受影响;
- 顶层加
version字段(与agent平级)无效——会被忽略,仍锁最新。
- 要评测任意历史版本,直接传对象形式
{id, version: N}——不需要先把它变成「当前最新」(这是与直觉相反的一点:很多人以为评测历史版本得先回滚,其实不用); - 默认生产流量走字符串形式锁最新版本,因此「生产用哪个版本」=「谁控制 Agent 的最新版本状态」。
triage 的 REST 实现
先创建 Session(agent 传 Agent ID 字符串,锁定当前最新版本快照;纯 LLM Agent 无需 environment_id):
Session 创建无初始输入字段(没有
initial_events),必须「先建 Session,再发一条 message 事件」两步走。SESSION_ID 后,发工单(把 Subject: ... 和正文拼进 text):
解析细节:判断结束看的
session_status / stop_reason 在 session_status 类型事件的 content[0].data 里({"stop_reason": {"type": "end_turn"}, "session_status": "idle"}),不在事件顶层;顶层 type 为 session_status 即回合结束标记。建议设 60 秒超时。每条 triage 约 8~11 秒。assistant 消息里拼接 content 文本、json.loads 解析出 {"team", "priority"},与期望团队比对;最后删除 Session:
GET /sessions/{id}/events/stream,请求头 Accept: text/event-stream)替代轮询,按 sequence_number 累积流式文本;评测脚本里轮询更简单。归档(POST /sessions/{id}/archive)与删除二选一:评测循环里用 DELETE 更干净。
score 逻辑:对每条工单跑一次 triage,按团队统计「命中 / 总数」。
v1 基线结果(4 条集,qwen3.7-plus):
| 团队 | 命中/总数 |
|---|---|
| api-platform | 1/1 |
| auth | 1/1 |
| billing | 1/1(T3 提到 API 用量,仍正确路由 billing) |
| dashboard | 1/1 |
第四步:发布 v2
PM 想加一条路由规则:凡是提到 API 用量、限流、配额、请求量的工单,都路由到平台团队。用 POST /agents/{id} 更新 system prompt(name + 当前 version 必填),即产生 v2。
新的 system prompt = v1 的内容,追加:
version 会变成 2。
插曲:代码评审去哪了?
一次 API 调用就改了 Agent,中间没有任何评审——做 demo 没问题,生产不行。POST /agents/{id} 本身没有内建审批流;工作空间里任何一把 Key 都能调它。而字符串形式创建的 Session 锁定的是当时的最新版本,这意味着升版之后新建的第一个 Session 就会用上新提示词。这跟用 feature flag、或任何「经 API 而非代码管理的 config」是一回事。
恢复评审的推荐模式:
- 让「生产该用哪个版本」成为一份受变更管控的产物——例如在自己的部署配置里显式记录目标版本号;
- 任何人都可以建 v2 / v3 / v10,这些版本只是躺在服务端、不接生产流量;
- 「晋升」= 更新那份「告诉生产用哪个版本」的 config,这个 config 更新走正常的代码评审流程。进阶做法:生产侧创建 Session 时直接传
{id, version}对象锁定受控版本号,连「Agent 的最新版本」都不必依赖。
第五步:给 v2 打分
用同一套评测跑 v2。有两种做法:
- 默认做法:此时 v2 已是最新版本,直接用字符串形式建 Session(锁 v2);
- 对比评测:Agent 的版本完全不用动——传对象形式分别锁定
{id, version: 1}和{id, version: 2}各跑一遍,随时对比任意两个历史版本的行为。
| 团队 | 命中/总数 |
|---|---|
| api-platform | 1/1 |
| auth | 1/1 |
| billing | 0/1(回归! T3 被路由到 api-platform) |
| dashboard | 1/1 |
第六步:回滚
billing 出现回归。v1 的配置仍完整保留在服务端,回滚不需要重新部署代码。
回滚做法:发布一个与 v1 等价的新版本。默认流量(字符串形式)绑定「创建时刻的最新版本」,所以要让生产行为回到 v1,就把 v1 的 system prompt 原样再发一次 POST /agents/{id},产生 v3(版本号继续自增,配置等价于 v1):
GET /agents/{id}/versions(见文末)。
用「回到 v1 提示词」的 v3 重跑失分的 T3:billing 恢复正确路由。
由于所有版本都在服务端留存:
- v2 仍可继续迭代修复(直接以 v2 为蓝本发 v4,或用
{id, version: 2}锁定评测); - 生产可以先留在 v3,或用小流量金丝雀——一部分请求传
{id, version: N}试新版本,其余走默认最新; - 修好后建一个新版本,走同样的评测 → 晋升流程。
清理
用 archive(归档)而非删除:Agent 不支持 DELETE(返回 405),归档保留审计记录、拆掉容器、停止计量;版本历史是它存在的意义。评测用的 Session 在循环里已即时 DELETE。
小结
机制本身很小——建版本、更新升版、把生产锁到某个版本、必要时再切回去——但一旦提示词变成「版本化的服务端资源」,它就能独立于应用代码被评测和晋升。要点:
- 生产要用哪个版本,应是一份受控产物:把它当作提示词变更的闸门,走正常评审;
- 高风险 Agent 先用小流量灰度新版本,再全量(配合
{id, version}显式锁定做分流); - 理解版本绑定语义:字符串形式锁最新、对象形式
{id, version}锁指定版本(不存在则 404)、顶层version字段无效;已建立的 Session 不受后续升版影响; - 评测历史版本不需要先回滚——对象形式直接锁定任意版本对比;回滚是为了让默认流量恢复旧行为。
附:列出全部版本
查看某个 Agent 的全部历史版本:
config 是内部存储格式的直出:字段用驼峰(mcpServers、workspaceId、gmtCreate),与创建 API 的 snake_case 不同;每版都带完整 system 与 created_at,可用于审计、对比历史提示词,以及决定把哪个版本晋升为生产版本。
下一步
- 进阶:多智能体定制复杂提案:roster 成员的版本锁定语义与这里的 Session 锁定是对偶的。
- 进阶:生产化定时晨报机器人:Deployment 的版本锁定与漂移陷阱。
- 配置智能体:版本与更新语义的控制台视角。