把外部 Agent 接入治理平台,最容易走向两个极端:要么只包一层 HTTP,实际权限仍由宿主随意使用;要么要求 adopter 重写运行时,把模型、工具、会话和凭据都迁入平台。
Agent Foundation 选择了第三条路线:保留外部 Agent 的原生运行方式,只把需要权威治理的读取、候选和审核动作接到公共合同上。
为了验证这条路线,我选择了两个差异很大的采用方:
- Waku:需要覆盖一个完整 Agent turn,能够读取 Context、产生显式 Observation、提交 Memory candidate;
- OpenClaw:只需要一个固定的 Context Recall Skill,不允许写入任何语义权威。
两者都使用 public SDK/HTTP 和 Registration,但获得的能力不同。
查看 Agent Foundation 项目总览 · 打开本文交互图
第一性边界:平台不应接管宿主
Waku 和 OpenClaw 仍然拥有自己的:
- 模型与 provider 配置;
- session、chat history 与工具调用;
- shell、sandbox 和插件策略;
- Prompt、业务动作和最终回答;
- provider credentials。
Foundation 不把这些能力变成自己的权威。它负责的是:
- 哪个产品 Registration 被打开;
- 当前 principal 拥有哪些 exact scopes;
- 哪些 Context 可以读取;
- 哪些 Observation 可以提交为候选;
- owner review 是否由独立身份完成;
- governed state 与 receipt 如何持久化。
这个切分让 adopter 不需要变成“Foundation 的子框架”,同时避免宿主因为能调用模型就顺便获得 Memory 或 Graph 写权限。
技术解释图:Waku 通过完整 turn glue 提交候选,OpenClaw 只做只读 recall;二者共享公共 SDK 与 Registration,但 scope、凭据和副作用边界不同。
Waku:接入完整 turn,而不是复制一套 Agent
Waku 接入固定在公开 upstream 版本与源码快照上,没有修改 upstream,也没有导入 Foundation 私有模块。glue 只连接稳定的 Session seam:
begin turn → retrieve context → host model/tools → complete turn
关键约束是:普通 chat 文本不会被自动当作 Observation。只有 adopter 显式 callback 返回 typed Observation 时,Foundation 才会进入治理;callback 返回 None 就表示本 turn 零治理写入。
这避免了把每轮 Question + Answer 自动塞进 Memory 的常见误区。模型回答和权威候选是两种数据,前者属于宿主体验,后者必须由产品明确选择并绑定当前 turn identity。
active-turn guard
glue 使用显式 TurnEnvelope,把 retrieve、complete 和治理动作绑定到当前活动 turn。过期 envelope、跨 session 重放或 host 状态漂移会 fail closed,而不是把 Observation 记到另一个会话。
凭据分离
Waku Agent 进程只持有读取与 proposal 所需权限。owner review 使用单独的 memory:review principal;Agent 不能自提、自批、自执行。
因此,“Agent 能产生候选”不等于“Agent 能把候选变成 Memory”。
OpenClaw:只开放一个只读 Skill
OpenClaw 的需求更窄:在 Skills host 中调用一个固定 CLI,查询 Foundation Context recall。
这个 wrapper 只需要 memory:read,不注册项目、不提交 Observation、不审核 Memory,也不调用 Relation、Graph Proposal 或 raw write。查询参数有长度和数量上限,返回也是有界 typed result。
如果 Foundation unavailable,Skill 返回显式 degraded;它不会伪造一个空 Context,也不会绕到 legacy store。
allowlist 不是安全边界
OpenClaw 的 Skill allowlist 只决定 Skill 是否可见,不等于 shell authorization。命令执行、sandbox、文件访问、provider credentials 和工具审批仍由 OpenClaw host 管理。
这点很重要:平台不能因为“Skill 已列入 allowlist”就宣称宿主安全,更不能把 OpenClaw 的 shell 权限当作 Foundation authority。
为什么两套 adapter 不是重复代码
两者共享的是权威合同,而不是宿主生命周期:
| 维度 | Waku | OpenClaw |
|---|---|---|
| 接入对象 | 完整 Agent turn | 固定 Context recall Skill |
| Foundation 读取 | 有界 Context / Memory recall | 有界 Context recall |
| 候选提交 | 显式 typed Observation | 不允许 |
| owner review | 独立 review principal | 不适用 |
| 模型与工具 | Waku host | OpenClaw host |
| Graph / Relation | 未启用 | 未启用 |
| MCP | 不要求 | 不要求 |
如果强行做一个“万能 adapter”,它必须知道两种宿主的 session、工具、错误模型和生命周期,最终会把产品差异塞进 Foundation。现在的做法只共享 public SDK、HTTP、Registration 与 typed receipts,每个 glue 保留最薄的宿主接线。
Registration 如何防止 adopter 自证能力
adopter 可以声明需求,却不能在请求中写一个 supports_memory=true 就获得能力。
Foundation 会从 Recipe、compiled capability plan、accepted Provider Claims 和唯一 Runtime component owner 共同派生可装配能力。打开 Runtime 时,服务端重新读取 Registration、principal 与 exact scopes;调用者自报的 owner、tenant 或 capability 不作为权威。
这也是 Waku 与 OpenClaw 能共享底层平台但获得不同权限的原因:它们使用的是同一 Registration 模型,不是同一个权限模板。
失败时应该发生什么
受限接入不仅要证明 happy path,还要证明失败不会静默扩大权限。
已验证的关键行为包括:
- Waku callback 缺失时零治理写入;
- active turn 不匹配时 fail closed;
- OpenClaw 只读 credential 无法执行 proposal/review/write;
- Foundation unavailable 时返回 typed degraded;
- wrapper 只依赖 installed public package,不使用源码路径或私有 import;
- host model 或工具能力不会被 Registration 误认为 Foundation capability。
这证明了什么,也没有证明什么
这两个 adopter 证明了一个重要但有限的结论:同一公共 Foundation 合同可以支持不同深度的外部 Agent 接入,而不接管宿主模型、工具和业务策略。
它没有证明:
- Waku 或 OpenClaw 的模型回答更好;
- MCP 已启用或是必要依赖;
- OpenClaw shell/sandbox 已通过生产安全认证;
- 生产 IAM、TLS、Secret rotation、HA/DR 已完成;
- 任意第三方 Agent 都能零成本接入;
- 外部 Agent 获得了 Graph 写权限。
真正可复用的不是“一个万能插件”,而是一组清晰的接入原则:
- 宿主继续拥有模型、工具、会话和最终回答;
- Foundation 只接管明确的权威动作;
- scope 按实际工作流最小化;
- proposal、review 和 execution 使用不同 principal;
- 不可用时显式 degraded,不绕过权威;
- adapter 只依赖 public contract,不复制 Foundation 源码。
这让“接入平台”不再意味着“重写 Agent”,也不再意味着“在宿主里放一把万能数据库钥匙”。
