一问题:Agent 长着长着就崩了
你给业务上线了一个 Agent,第一版小巧、好用。两周后,业务方说:"能不能再加点能力?"——你加上了。再过几周,又来一波需求,你又加。
如此反复,等你回头看时,发现:
- 系统提示(system prompt)已经膨胀到几百行;
- 工具数量翻倍,甚至嵌套了好几个子智能体;
- 而那些原本表现很好的功能,开始出现 regression(性能回归)。
这是 Anthropic 在客户和自家内部都反复看到的模式——把功能"粘"到现有 Agent 上是最快的路径,但也是最伤架构的路径。
这次 workshop 的目标:拿一个真实变臃肿的 Agent,演示如何用正确的 agentic primitive(工具 / 技能 / 子智能体)把它拆回去,并通过 eval 验证每一步是不是真的有改进。
二主角:StockPilot——一个 400 行系统提示的库存 Agent
StockPilot 是一个虚构的中型零售商内部的库存管理 Agent。它的能力:
- 标记库存不足;
- 预测需求;
- 挑选供应商;
- 提交采购订单(PO);
- 给员工生成周报。
每一项单独看都不复杂。问题在于架构:一个 orchestrator + 12 个工具 + 3 个被工具包装的子智能体,全部由一份膨胀的系统提示统筹。
每次新需求来,开发都倾向于"再加一个工具"或"再加一个子智能体"。久而久之就成了这副样子。
三怎么知道它病了?评估体系
StockPilot 的评估套件有 12 个 eval 任务,分两类:
| 类别 | 前缀 | 性质 | 任务复杂度 |
|---|---|---|---|
| 回归测试 | R* | 单轮、相对简单 | 真实使用场景的代表 |
| 失败模式测试 | F* | 多轮、刻意构造 | 复杂、模拟极端情况 |
评估同时用两种 grader:
- 确定性指标:token 使用量、延迟、turn 数;
- 非确定性指标:用 LLM-as-judge 评估输出风格、语气、质量。
三个典型失败案例
| Eval | 模拟场景 | 失败根因 |
|---|---|---|
| F1:日常低库存扫描 | 给定库存数据,挑出告急 SKU | Agent 走了一条"绕远的路"——结果正确,但路径过低效,达不到效率阈值。 |
| F2:促销期采购流程 | 在促销包条件下下采购单 | Orchestrator 与子智能体之间通信失真——子智能体计算对了,但传回 orchestrator 时信息丢失。 |
| R8:促销月预测 | 计算某促销月的销售预测 | 系统提示里有两条互相矛盾的策略,模型读到后混乱:拿到了正确的 baseline(12 units/day)和正确的 multiplier(3.1x),但计算时用成了 1.35x——上下文污染导致幻觉。 |
R8 是个典型的"上下文问题不是模型问题"——模型周围的信息有矛盾,再聪明的模型也会蒙。
四工作法:在 Eval 上"爬坡"
整个 workshop 的方法论叫 hill climbing——每次只改一点,每次都回归 eval,看 pass rate 有没有真的往上爬。
关键:每改一次都用 eval 把改动锁住,避免靠"感觉"判断改进。
Workshop 上手要点
- Repo 里有
before/和starter/两个目录。before是基于 Messages API 自建的 agent loop;starter是同样的 agent 跑在 Claude Managed Agents (CMA) 上的版本。 - 先
uv run evals --agent before拿基线(理论 83%,实际 Will 现场跑出 62%)。 - 改造目标是把 agent 迁到 CMA:自己只关心 agent 设计,scaling / 内存 / 安全 / 沙箱这些都交给 CMA。
五Fix #1:把系统提示压短,业务知识下沉为 Skill
Skill 是 Claude 可以在需要时按需调入上下文的"打包知识"。可以理解为:一份 markdown + 元数据,描述某领域知识或操作规程;Claude 判断当前任务相关就读,不相关就不读。
关键原则
- 系统提示只留"Claude 无论做什么任务都必须知道"的内容——身份、整体目标、安全约束。
- 业务规则、流程手册、品牌指南 → 全部下沉为 skill。
- 当 Claude 接到任务时,它自己判断需要哪些 skill 召入,不需要就不污染上下文。
效果
StockPilot 的系统提示从 400 行压到 ~50 行(后期最终版本进一步缩到 15 行)。业务知识完整保留,只是从"全量塞"改成"按需取"。
六Fix #2:拒绝写一堆自定义工具,先用类人原语
Anthropic 内部和给客户做 Agent 时遵循一条原则:先用类人原语,自定义工具留到最后。
类人原语指的是:人类员工每天到工位上有什么,就给 Claude 什么——
| 原语 | 对应人类能力 | 在 Claude Code / CMA 里的体现 |
|---|---|---|
| bash | 在终端跑命令 | 执行任意 shell |
| file system (read/write) | 翻文件、写文件 | 读写沙箱内文件 |
| 代码执行 | 写脚本算东西 | Python / 其他语言 |
| web search | 浏览器查资料 | 内置搜索工具 |
| TODO list | 自己列待办 | 内置 to-do 跟踪 |
Claude Code 之所以强,不是因为它特别会写代码,而是因为它拥有人类工程师在岗一天能用到的全部基础工具。 每次模型升级,这套原语会自然变得更厉害——就像同一个人多读了几本书后,用同一台电脑也能产出更多。
决策矩阵
| 选项 | 何时优先 | 何时不用 | 例子 |
|---|---|---|---|
| CMA 内置原语(bash / 文件系统 / 代码执行 / web search) | 任务可以用"通用计算"解决;想要随模型升级自然变强 | 几乎没有"不用"的场景,先用了再说 | 用 bash 跑 Python 处理 CSV,比把 CSV 全塞进上下文便宜得多 |
| 自定义 tool | 上面原语不够,要接特定 API / SDK / 内部系统 | 能用代码执行直接调 CLI/API 时 | 调内部审批系统、专用算法 |
| MCP server | 多个 Agent / 多个 Claude Code 实例共享同一套受治理的工具 | 单 Agent 自用、临时需要 | 公司级的工具中心 |
StockPilot 的工具大瘦身
StockPilot 原有 12 个自定义工具,大部分是"读数据"、"分析数据"、"写报表"——这些都可以用 bash + 代码执行统一替代。
Will 让 Claude 重构后,工具数从 12 → 3(bash + read + write)。其余能力交给代码执行。
七MCP 的位置:能不上就不上
很多客户的现状是:先冲去搞 MCP,结果一堆零散、能力重叠的 MCP server 跑在系统里,反而把上下文搞乱。
MCP 不是首选,是多 Agent 共享治理才该上的最后一档。
另外,代码执行也能直接调 CLI/API——很多本来想用 MCP 解决的能力,让 Claude 直接写代码调外部接口,反而更灵活、更省上下文。
八Fix #3:子智能体——什么情况下值得保留?
StockPilot 原有 3 个子智能体(forecaster / report writer / procurement)。改造后只保留 forecaster,其他全部去掉。
子智能体的两个合理用例
| 用例 | 说明 | 例子 |
|---|---|---|
| 并行性:把一份大问题拆给多个 Claude 同时啃 | 单 Claude 顺序做太慢;任务可并发 | 跨大代码库探索、deep research、多源 web search |
| 新鲜视角:需要一个不带先前上下文的 Claude 来评审 / 处理 | 同一份上下文里的 Claude 容易自洽地走偏 | code review、写代码 + 评审分离 |
StockPilot 保留 forecaster 的理由
预测模块属于第二种用例——主 Claude 在和用户对话过程中积累了大量上下文,如果让同一个 Claude 同时写预测会被对话历史污染。 所以独立一个 forecaster sub-agent,干净的上下文里跑预测,结果回主 Claude。
CMA 的原生 sub-agent 能力(Callable Agents)
CMA 原生支持把 sub-agent 注册为一等公民(不是"工具包装"),好处:
- 可观测性:每个 sub-agent 的 transcript、token、turn 数自动归到 session 元信息里;
- 通信契约:orchestrator ↔ sub-agent 的 message schema 更规范,不容易"传话失真";
- 调试简单:不用自己跨 agent 拼日志。
一个反直觉的趋势
随着前沿模型(如 Claude 4.x)变得更聪明,主 Agent 能管的复杂度变大了——很多过去拆给子智能体做的事,现在让主 Agent 自己做反而更好。Will 说他们看到的趋势是:客户在主动减少 sub-agent 数量,把能力收回到 orchestrator。
九改造结果:从 62% → 92%
| 维度 | 改造前 | 改造后 |
|---|---|---|
| 部署 | Messages API 自建 agent loop | Claude Managed Agents(CMA) |
| 系统提示 | ~400 行(业务规则塞满) | ~15 行(只留恒久要点) |
| 工具数量 | 12 个(含 3 个 sub-agent 工具包装) | 3 个(bash / read / write) |
| 业务知识载体 | 系统提示 | Skills(progressive disclosure) |
| 子智能体 | 3 个,工具包装 | 1 个(forecaster),CMA callable agent |
| Eval pass rate | 62%(Will 现场基线) | 92% |
核心收获:Agent 膨胀的根本原因是把业务知识塞进系统提示和用自定义工具替代类人原语。解决方案分别是 Skills 渐进式披露 和 优先用 bash/文件/代码执行。
十附:相关概念速查
| 概念 | 说明 |
|---|---|
| Skill | 按需召入的打包知识,Claude 判断是否相关再读,不污染上下文 |
| Callable Agent | CMA 原生支持的子 Agent 形态,比工具包装更规范,有独立 transcript |
| 类人原语 | 人类工程师在岗用到的能力(bash/文件/代码执行/search),优先于自定义工具 |
| Hill Climbing | 每次只改一点,每次回归 eval,用数据而非感觉判断改进 |
| Progressive Disclosure | 知识不在系统提示里全量塞入,而是按需召入,减少上下文污染 |