← 返回文章列表

Graph-only 产品为什么不该被迫启用 Memory:Evidence dependency profile 的目标化设计

从一次 Registration 失真出发,解释 Agent Foundation 如何把 Memory、Relation 与 Graph 的 Evidence dependency 能力拆成独立、可信、不可伪造的目标化 profile。

一个产品只需要受 Evidence 保护的 Graph 写入,为什么还要声明 Observation、Memory 和 Relation?

如果答案是“因为公共 helper 就是这样组装的”,那问题不在 adopter,而在平台的能力模型。Registration 对外声称自己冻结了产品真正启用的权威,但底层却通过 Memory-shaped helper 顺带启用了其他能力。编译结果可以通过,运行时也可能工作,可是它已经不再准确描述产品边界。

Agent Foundation 在 AF-ER03 中修复的正是这类结构性失真:Evidence dependency 不再是一项只能经由 Memory 打开的总能力,而是按 Memory、Relation、Graph 三个 target family 分别绑定的 profile。

查看 Agent Foundation 项目总览 · 打开本文交互图

最小反例:Graph-only Recipe 被 Memory helper 绑架

设想一个高级分析产品,它已经具备:

  • Evidence Authority,用来冻结精确来源 revision;
  • Graph Proposal Authority,用来记录有界 typed operations;
  • ReviewDecision,用来批准或拒绝候选;
  • Graph Authority,用独立 executor 应用获批操作。

它希望 Graph 中已应用的 element 在 Evidence 被 supersede 或 revoke 后进入保护和重新验证。这个需求本身只涉及 Evidence 与 Graph。

旧组合方式却从 Memory dependency helper 派生能力。于是 Graph-only Recipe 会出现两种坏结果:要么不得不声明并不使用的 Observation、Memory、Relation,要么产品在外层写特殊分支绕过公共 Registration。前者扩大权限,后者制造第二套事实源。

第一性原则很简单:Registration 中出现的每一项能力,都必须有产品真实需求、可信 Provider Claim 和唯一 Runtime owner。 没有这三者,就不应进入 sealed binding。

Profile 冻结的不是一个布尔开关

新的 binding set 使用 EvidenceDependencyProfileBindingV1。它冻结的不是 dependency_enabled=true,而是一组可核对事实:

  • Foundation policy id、version 与 fingerprint;
  • target family:memoryrelationgraph
  • 允许保护的 target kinds;
  • Foundation-owned adapter id 与 fingerprint;
  • 该 profile 所需的 capabilities。

产品 Recipe 只能选择公开 policy id。它不能把自定义 policy code、target kinds、Provider Claim、Runtime component 或 adapter fingerprint 填进请求体。这一点很重要:如果 adopter 可以自报“我已经提供 Graph dependency authority”,Registration 就只是把未经验证的声明持久化了。

Evidence dependency profile 目标化数据流

Graph-only 与 Memory Recipe 可以从同一个可信 catalog 选择不同 profile;Binding Set V2 只冻结被选择的目标族。

Graph-only 现在到底获得什么

一个 Graph-only Recipe 可以组合:

  • Evidence;
  • Graph Proposal;
  • Graph;
  • ReviewDecision;
  • Graph Evidence dependency profile。

它不需要 Observation,不需要 Memory,也不需要 Relation。编译后,accepted Provider Claims 必须满足上述能力;Runtime assembly 必须为每项能力找到唯一真实 owner;Registration 再冻结 exact profile binding。最终打开的 principal-scoped handle 只包含 Graph 所需权限。

这不是“减少几行配置”,而是缩小授权面和故障面:Memory provider 缺失不会阻塞 Graph-only adopter,Relation contract 的变化也不会让一个从未使用 Relation 的产品重新注册。

三个 target authority 仍然相互独立

目标化 profile 不意味着把三套生命周期重新抽象成一个万能接口。

Memory、Relation 与 Graph 对象有不同的状态机、投影语义和副作用边界:

  • Memory 关心 proposal、review、recall 与 protected empty;
  • Relation 还要区分生命周期状态与时间投影;
  • Graph 必须处理 applied marker、Graph revision、outbox、executor 与 reconciliation。

Profile 统一的是“如何声明 Evidence dependency 能力”,不是抹平目标对象。每个 target kind 仍只能有一个 profile owner,避免同一对象同时被两套 revalidator 解释。

兼容性为什么不能变成静默升级

历史 V1 Registration 没有这些 target-scoped profile。最危险的做法,是在 reopen 时根据当前 package defaults 自动补入 profile。这样同一个 Registration identity 会在升级软件后突然获得新的 effect authority。

因此 V1 只按历史投影精确重开,不注入新 profile。若 V1 调用 Relation 或 Graph dependency effect,系统返回 typed 409 evidence_dependency_profile_upgrade_required。产品必须显式重新注册,才能获得新能力。

兼容的目标是让旧行为继续成立,不是让旧身份悄悄变强。

为什么这次没有数据库迁移

AF-ER03 改变的是组合和 Registration 表达,不是 AF-ER02 已经验证过的 dependency persistence、outbox 或 Graph reconciliation 机制。因此实现没有为了“看起来完整”新增无意义 migration,也没有重复一轮等价 PostgreSQL/Neo4j 重型验收。

验证重点放在真正变化的边界:

  • graph-only public Recipe 的 compile、assembly、Registration 与 installed workflow;
  • profile catalog 不能被 adopter 注入;
  • 同一 target kind 的 owner 冲突必须失败;
  • V1 精确重开与 effect fail-closed;
  • SDK、完整 backend 和既有 Waku/OpenClaw adopter 不回归。

相关验收包括 graph-only installed workflow、聚焦与相邻回归、完整 backend/SDK 回归,以及外部 adopter 的 installed-wheel 回归。它证明的是目标化 Registration 合同成立,不代表任何生产 IAM、容量或大规模 fan-out 性能结论。

这次修复真正解决了什么

修改后,产品只获得注册的能力;未使用的能力不会因 helper 的接口形状进入权威边界。这样,新增 helper 参数时也不会意外扩大产品的访问范围。

我的判断是:可扩展平台的关键不是提供一个越来越大的默认能力包,而是让每个 adopter 能用同一套可信编译链表达不同的最小权威集合。 Target-scoped Evidence dependency profile 把这件事从口头原则变成了可冻结、可验证、可兼容的公共合同。

← 返回文章列表