门户首页
插件化 Agent 架构系列 · 3 / 4 · 空间维度

Spatial Composability:依赖可声明可反应(Reactive Coeffects)

空间维度 = 组件间依赖能不能显式声明 + 反应式协调。论文核心机制:Reactive Coeffects—— 每个组件声明它需要什么 coeffect(co- = 共同 / 一起 / 反向 effect),依赖变化时自动通知, 3 种反应分类:activate / deactivate / neutral。

生成时间:2026-09-02 19:54 · 生成 Agent:MiniMax Code (LLM: MiniMax-M3) · 载体:agentsoft-research-platform teaching-web-platform

概览

3
关键属性
3
反应类型
1
反应时序图
2
agent 落地场景
本系列 4 页进度
#页状态
1overview✅ 回顾
2temporal✅ 回顾
3spatial👉 本页
4unified末篇

第一篇 · Spatial Composability 是什么

Part 1 · 2 卡:定义 + 机制
"空间"问的不是"组件能不能找到依赖",而是"依赖变化时,依赖者能不能自动被通知"。
第 3 讲 · 1 定义 + 3 属性

什么是 Spatial Composability(论文 §1.1)

论文定义:spatial composability 是"components must be able to declare, discover, and resolve their dependencies on one another in a structured and verifiable manner"。换种说法——

组件声明"我要 X"——runtime 在上下文里找 X——找到就把 X 注入,找不到就保持 inactive;X 变化时,runtime 主动通知所有声明 X 的组件。
3 个关键属性
  • 显式声明(declarative):依赖以 typed coeffect 形式在组件 metadata 里声明,不需要手写查找代码
  • 反应式协调(reactive):依赖变化时,所有声明该依赖的组件自动被通知——不需要组件自己"轮询"或"监听"
  • 生命周期联动:依赖者的 active/inactive 状态由其依赖的满足状态决定——provider 不在 → consumer 自动 inactive;provider 来了 → consumer 自动 reload
Coeffect vs Effect:effect 描述"组件对世界做了什么"(外向);coeffect 描述"组件需要世界提供什么"(内向)。一个 tool 加载时向 registry 注册(effect),同时依赖一个 logger(coeffect)——两面同时存在。
← 返回入口 下一卡:机制 回 §2 时间 基础:Shi et al. 2026 §1.1, §3.2
第 3 讲 · 1 时序图 + 3 反应类型

机制:Reactive Coeffects(论文 §3.2)

核心思想:coeffect 是"声明 + 反应式通知",变化触发 3 种反应:

3 种反应(论文 Definition 26)
反应类型 触发条件 consumer 行为
activate 依赖由"未满足"变"已满足" consumer reload(重新 instantiate)
deactivate 依赖由"已满足"变"未满足" consumer unload(撤销 effects)
neutral 依赖已满足,但是同一个 provider 的等价更新 无动作(依赖者不被打扰)
3 种反应的时序(截图:provider 来了 / 走了 / 等价更新)
sequenceDiagram autonumber participant P as Provider 组件 participant R as Runtime participant C as Consumer 组件 Note over R: 初始:依赖 X 未满足 C->>R: 我声明 coeffect X(激活等待) Note over P,R: 1) Provider 加载 P->>R: ctx.set(X, value1) R->>R: notify: 满足状态变化 R->>C: activate (X 满足) C->>C: reload → 进入 ACTIVE Note over P,R: 2) Provider 卸载 P->>R: ctx.set(X, ⊥) via dispose R->>R: notify: 满足状态变化 R->>C: deactivate (X 不再满足) C->>C: unload → 撤销 effects → INACTIVE Note over P,R: 3) Provider 等价更新(自己改自己绑的 value) P->>R: ctx.set(X, value2)(same provider uid) R->>R: 同一个 provider 重新装 R-->>C: neutral(uid 没变,target digest 不变) Note over C: 无动作(连续性保持) Note over P,R: 4) Provider 替换(new uid) P->>P: 卸载旧 + 装新(uid 变) R->>C: activate → deactivate → activate
(uid digest 变化触发 reload)
图 1 · 3 种反应:activate(依赖到位)/ deactivate(依赖消失)/ neutral(uid 不变则不动)
关键设计:uid 而非 value(论文 §5.1.3 原文)——一个 coeffect 变化是否触发 reload,不是看 value 是否变化,而是看绑定的 provider 的 uid是否变化。uid 是单调生成的,永不复用——所以"同一个 provider 的等价更新"会被识别为 neutral,不会打扰依赖者;"新 provider 替换"会被识别为 activate-deactivate-activate 序列(这是 4 种 reaction 中的第 4 种 trigger)。
← 返回入口 跳到 §3 落地 末篇:Context 范式 基础:Shi et al. 2026 §3.2, §5.1.2, §5.1.3

第二篇 · 落地:多 agent 协作 + 工具发现

Part 2 · 1 卡:把机制套到 agent 架构
2 个具体场景:单 agent 内的工具发现 / 多 agent 之间的能力依赖。
第 3 讲 · 2 场景 + 1 对比

应用到 agent 架构:2 个场景

场景 1 · 单 agent 内的工具发现("coeffect 即 capability")
  • 传统:agent 启动时手动注册工具列表;想加新工具?重启 agent
  • Cordis 化:每个工具是 component,ctx.set("web_search", impl) 注册;consumer agent 声明 inject: ["web_search"]——工具就位自动 activate,工具下线自动 deactivate
  • agent 价值:长跑 agent 在不停服务的同时能动态加载新能力——论文 §1.2.2 提到的 "self-evolving harness" 的空间维度基础
场景 2 · 多 agent 协作("agent-as-coeffect")
  • 传统:agent A 调 agent B,需要 A 硬编码 B 的 endpoint / 等 A 自己 poll B 的状态
  • Cordis 化:B 把自己注册为 ctx.set("summarizer_agent", impl);A 声明 inject: ["summarizer_agent"]——B 升级 / 重启 / 替换时,A 自动 reload;B 下线时,A 自动降级为"无 summarizer"模式(而不是报错)
  • agent 价值:多 agent 拓扑变化时,不需要任何 agent 写容错代码——runtime 替你协调
对比:传统 DI 框架 vs Reactive Coeffects
维度 传统 DI(Spring / Guice / Angular) Reactive Coeffects(Cordis)
注入时机初始化时一次性依赖变化时反应式
provider 替换consumer 不会被通知consumer 自动 reload
provider 卸载consumer 持有旧引用,调用时炸consumer 自动 deactivate
依赖图管理靠 DI 容器配置runtime 自动遍历
agent 时代的适应性差(provider 频繁变化的场景)强(为 provider 频繁变化设计)
跟我们仓 swebench-exp-web/ 的连接:本仓 Web 平台已经做了多 agent 协作(参考本仓 wiki 中"过程洞察"子模块)。把每个 agent 子模块视作 component、每个子模块的输入视作 coeffect,就能用 Cordis 视角审视当前实现——会发现很多"agent 找不到依赖"的错误,本质是 spatial composability 没做。
← 返回入口 末篇:Context 范式 回 §2 时间 对比:Fowler 2004, "Inversion of Control Containers and the Dependency Injection pattern"