很多关系模型只有一个 active=true。它看起来简单,却同时混合了至少三个问题:这条关系是否经过治理批准、它现在是否处于有效时间区间、它是否已经写进产品 Graph。
这三个问题一旦混在一起,就会产生危险的误读。例如:
- “用户将在下个月加入项目 A”已被 owner 批准,但今天不应出现在 current projection;
- “用户曾属于团队 B”是真实历史,但不应被当前授权逻辑使用;
- Foundation 已批准一条 Relation,不代表产品 Neo4j 已经同步;
- 一条自然语言里提到某个人名,不代表实体已经被可靠解析。
Agent Foundation 的做法是把 Relation 的治理生命周期、时间投影与 Graph 应用状态拆开。
查看 Agent Foundation 项目总览 · 打开本文交互图
第一层:模型只能提交 typed candidate
Relation 不是从句子里抓到两个名词就直接写库。adopter 必须显式提供 typed V2 proposal,包括 allowlisted predicate、主体和客体的 binding references、时间区间以及当前 Observation/route。
Foundation 随后执行共享的零写 preflight:
- 当前 Registration 是否启用了
personal-safe-relations; - 实际 principal 是否拥有准确 scope;
- binding refs 是否能在 Registration 范围内重新解析;
- predicate 和 operation 是否属于冻结策略;
- Evidence、route 和 request identity 是否仍是当前状态。
自然语言 mention 不是实体权威。无法解析的候选返回 item-level unresolved,Relation 写入为零;如果同一 turn 还包含安全的 Memory,Memory 可以继续成功,不会被 Relation provider 的失败回滚。
第二层:personal-safe-relations 的 Runtime 候选都进入 owner review
通过 admission 的候选不是 active Relation,而是 pending_owner。ReviewDecision 的目标是冻结的 formation;reviewer 可以批准或拒绝,却不能在审批时悄悄改端点、时间或 action。
这条规则避免了一种常见的“审批漂移”:界面上批准的是 A→B,执行时却因为重新解析或请求体改写变成 A→C。
批准后 Relation 的治理生命周期进入 active;拒绝会形成不可变的 denied 事实,并从可用投影中排除。
技术解释图:横向是 candidate 到 owner approval;右侧是独立的 upcoming/current/historical 时间投影;下方是不解析、拒绝和 provider 降级。
第三层:active 不等于 current
active 回答的是:这条 Relation 是否已经完成治理并被接受。
current 回答的是:在查询时刻,它的有效区间是否覆盖现在。
因此一条未来关系可以同时满足:
lifecycle_state = active temporal_projection = upcoming
它不会出现在默认 current projection。到达 valid_from 后,投影变为 current;越过 valid_until 后,生命周期历史仍被保留,但默认投影变为 historical。
这些状态分别记录“批准过”“现在有效”和“历史存在”,避免用一个布尔值同时表达三个不同事实。
第四层:Relation 仍然不是产品 Graph
AF-C04 的 Relation bridge 只调用现有 Relation planning 与 temporal propose/confirm/reject primitives,不调用 RelationEvolution.apply(...),也不持有产品 Graph port。
因此返回状态始终明确包含:
graph_state = not_applied
这意味着 Foundation Relation 可以被治理、审核和时间投影,但不会凭空修改 adopter 的产品 Graph。需要 Graph mutation 时,必须走另一条 Graph Proposal → ReviewDecision → durable outbox → independent executor 链路。
把两者分开有两个好处:
- Relation 审核不会因为产品 Graph 暂时不可用而失去审计事实;
- 产品不会把“Foundation 接受了语义关系”误解为“真实数据面已经完成变更”。
为什么没有复用 Memory 的自动应用策略
低风险、owner-explicit 的偏好 Memory 在 sealed local development 中可以按严格规则审计式 auto-apply。Relation 的风险不同:它通常连接多个业务实体,可能影响权限、推荐、组织结构或时间判断。
因此当前 personal-safe-relations Runtime 合同中的 Relation candidate 全部进入 owner review,没有把“看起来像普通关系”的模型分类当作自动写入依据。敏感内容、实体未解析、策略缺失或 provider 降级都 fail closed。
exact replay 与 semantic duplicate
同一 request identity 的 exact replay 不应重复创建 candidate、ReviewDecision 或 temporal event。Foundation 通过稳定 identity 和 receipt 返回同一结果。
新的 semantic duplicate 可以保留必要的 Observation/Formation 审计,但不会因此把产品 Graph 写两次。这里需要继续区分“请求重放”“语义相似”和“真实 Graph 幂等 marker”,它们不是同一个去重层。
采用方仍然拥有产品语义
Foundation 不拥有全局 ontology,也不会把两个自由文本名字猜成同一个实体。adopter 决定:
- 哪些 predicate 被允许;
- binding reference 指向哪些产品实体;
- 时间字段的业务含义;
- 谁是 represented owner;
- 哪些 approved Relation 需要进一步生成 Graph Proposal。
Foundation 拥有的是 admission、身份重验、冻结候选、ReviewDecision、temporal state 与 receipt,而不是产品世界观。
已验证到哪里
当前本地版本化基线已经验证:
- typed Relation capability 和 shared preflight;
- unresolved entity、capability 缺失与 provider degraded 的 item-level 结果;
- owner approve/reject 与 exact replay;
- future Relation 的
active + upcoming,以及默认 current read 不可见; - SQLite 与 PostgreSQL temporal Relation 路径;
- Relation/Graph Evidence dependency convergence;
- Graph 写方法 fail-fast spy 调用数为零。
仍然没有由这条链证明:
- 产品 Graph 已同步;
- 大规模时间图查询性能;
- 生产 IAM、TLS、HA/DR;
- 模型能可靠地自动抽取所有 Relation;
- Relation 的业务正确性优于 adopter 自有策略。
最终原则很简单:治理批准、时间有效和数据面应用必须分别可证明。 只有这样,“这条关系存在过”“它现在有效”“它已经写入产品系统”才不会在 Agent 时代被一个模糊的 active=true 混为一谈。
