Anthropic 这周开源的 KYC cookbook,把 multi-agent 工程化压成了一组声明式 YAML
上周那篇关于 single-agent harness 的文章给出了三条原则:harness 不是工作流,本质是 agent 看不见的边界——OS 级 sandbox、hook 拦截器、配置在 prompt 视野之外的 capability 列表。该篇限定在单 agent 内部。multi-agent 协作的工程问题完全不同——多个 agent 如何分职、谁有哪些工具、谁能调谁、agent 之间用什么协议交换数据,过去一直没有公开的最小工程参考实现。
5 月 5 日 Anthropic 将 anthropics/financial-services 开源,4 天累计 18,630 stars。仓内 managed-agent-cookbooks/kyc-screener/ 目录下若干 YAML 文件给出了答案:multi-agent 系统的工程结构可以完全用声明式 YAML 表达,每一段配置对应一项明确的工程约束。
<figure><img src=“images/01-managed-agents-stack.jpg” alt=“01-managed-agents-stack”></figure>
这套 cookbook 在做的事情
KYC 业务(反洗钱合规流程)的工程描述并不复杂:客户上传一份开户材料——合同、护照、股权结构图,统称 onboarding packet;系统从这些文档抽出实体信息,把实体跑反洗钱规则和制裁名单匹配,最后输出一份 Excel 工单交合规人员签字。
cookbook 把这条流水线拆成三个独立 agent,类比成三个岗位:
- doc-reader——文档翻译员:把护照、合同文本翻成结构化字段 JSON。只读、不写、不调外网。
- rules-engine——规则评判员:拿到 JSON 后查内部 KYC 规则与外部制裁数据库,输出 pass/fail。只读、可调一个外部数据库、不写文件。
- escalator——报告速记员:根据评判结果写一份 Excel 工单。整个系统里唯一持写权限的环节。
三组工具集严格不相交。
权限默认 deny
orchestrator 的 agent.yaml:
tools:
- type: agent_toolset_20260401
default_config: { enabled: false }
configs:
- { name: read, enabled: true }
- { name: grep, enabled: true }
- { name: glob, enabled: true }
声明式 allowlist,默认 deny。orchestrator 调度层本身只读、不写;写权限交给唯一一个 leaf。callable_agents 列表中 escalator 后附注释 # only leaf with Write,是整套 cookbook 的设计声明。
工程意义:agent 能调什么一目了然,工具集变更走配置 diff,可纳入 code review 与 CI 静态分析。无需翻阅程序代码中散落的 if-else。
output_schema:agent 之间的协议层
subagents/doc-reader.yaml:
mcp_servers: []
callable_agents: []
output_schema:
required: [packet_id, entity, ubos]
properties:
country: { type: string, maxLength: 2, pattern: "^[A-Z]{2}$" }
在没有 schema 的 multi-agent 系统中,agent 之间用自由文本 JSON 串通讯,下游要自己解析、判断字段、应对脏数据——这部分代码在每个项目里重写一次,且很难做单元测试。
output_schema 把这件事拉到 runtime 层:上游 agent 的输出被强制约束为受控字段,country 必须是两位大写字母,packet_id 必须匹配 pattern。下游 agent 读到的输入是已验证的结构化数据。
工程意义上,output_schema 等同于 multi-agent 系统中的协议层——把 LLM 自由文本输出转为可静态分析的字段契约。
读取层 mcp_servers 与 callable_agents 都是空数组,明确:该 tier 不持有任何外部副作用能力,专司"文档变结构化数据"。
评判员能调外部 API,但既不读原始文档也不写文件
subagents/rules-engine.yaml 接收上游 schema 化的实体 JSON,调外部 sanctions/PEP 服务,输出 pass/fail。
关键工程设计在工具组合:拥有外部 MCP 访问能力,但不读取原始文档,且不持有 write,callable_agents: [] 也不能调起子 agent 完成副作用。
一个能调外部 API 的 agent,本身被定位为副作用最弱的中间环节——这是多数自制 multi-agent 项目里最容易缺位的隔离层。
整套系统里只有一个 agent 能写文件
subagents/escalator.yaml:
system:
text: |
You are the ONLY worker with Write. Take the rules result and screening
hits and produce ./out/escalation-<packet>.xlsx for compliance sign-off.
Never open onboarding documents directly.
整个 callable_agents 树中持 write 的 leaf 仅 escalator 一个。这一约束的工程价值有两层:操作可追溯——所有写入磁盘动作可在 audit log 中通过 escalator 实例 ID 单点定位;依赖图清晰——callable_agents 列表构成静态依赖关系,从 orchestrator 到任意 leaf 的调用路径可在部署前完成图分析。
Never open onboarding documents directly 明确禁止 escalator 接触原始文档,它仅消费上游已 schema 校验的 JSON——读取层输出与写入层输入之间存在严格的接口契约。
<figure><img src=“images/02-agent-prod-walls.jpg” alt=“02-agent-prod-walls”></figure>
外部服务地址走环境变量
mcp_servers:
- { type: url, name: screening, url: "${SCREENING_MCP_URL}" }
MCP server 地址以 ${ENV} 占位符声明,真实 URL 由 agent runtime 在调用瞬间从 vault 注入。该写法把外部依赖从 prompt 内容中完全解耦:同一份 agent.yaml 可在 dev、staging、prod 三环境分别部署,外部服务的迁移、域名变更、密钥轮换都不触及 YAML 本体。
doc-reader.yaml 中 mcp_servers: [] 为空,表示读取层在物理结构上无法访问该服务——外部依赖的可达性以 YAML 声明确定,无法在 runtime 通过 prompt 临时引入。
入口是结构化事件,不是聊天框 prompt
steering-examples.json 是一行业务语义触发器,附结构化标识(packet ID、client ID、as-of 日期),而非操作人员输入的自由文本。
这一选择把 agent 系统从 chat-driven 转为 event-driven:第一,event 类型可枚举,agent 系统输入面在编译期即固定,新接业务方只需扩 event 列表;第二,event 可序列化为唯一标识,每一次 tool call 可反查到具体 event 实例——任务调度、重试逻辑、监控指标全部以 event ID 为主键组织。
多数自制 multi-agent 系统从聊天框 prompt 出发,导致 event 类型在系统中没有显式表示,任务调度、监控、回放、压测均无法围绕一个稳定主键展开。
这套范式的真实份量
把整个仓库通读一遍后,最直接的感受是:multi-agent 工程化第一次有了可参照的声明式范式——和 K8s manifest 之于容器编排几乎是同一种工程进化。过去散落在 Python 代码里的「谁能调谁、谁能写什么、外部依赖怎么进、输入如何校验」全部声明在 YAML 里,剩下的工程动作变成对一份文件做 diff、做 code review、做静态分析。
这件事比 cookbook 里那 10 个业务 agent 模板长效得多。模板两个月内会出现 10 个开源版本;声明式 YAML 范式短期内不会被取代——它解决的是 multi-agent 工程化的底层问题:让一个由若干 LLM 组成的系统具备与传统软件同等的可分析性。
判断一个 multi-agent 项目当前的工程化成熟度,最直接的看法是它在 YAML 里声明了多少能力——声明得越多,未来重构、扩展、审计的代价越低。这把尺子比看代码行数、看 agent 数量、看 demo 流畅度都更接近本质。
5/6 那篇讨论 single-agent harness 的边界原则——边界要藏在 agent 视野之外。本周这个仓把同样思路落到 multi-agent 这一层。两篇连起来传达一个判断:衡量 agent 工程化的真实进展,重点应转向整套系统的可分析性、可重构性、可审计性这三个传统软件指标——而非 agent 单体能力的强弱。这是从模型迷恋回到工程视角的拐点。