模式矩阵 /模式白皮书/C6

C6 · Choreography · 编舞

坐标 协作 Collaboration × 编舞 Choreography(新兴拓扑,编排的去中心化孪生)
成本 高(多 agent、事件驱动,链路长、可观测开销高)
模式组 协作模式
模式简介 多个 agent 之间没有中央指挥,各自订阅事件、各自反应、各自再发出新事件,整体协作行为从局部规则里涌现出来。

它解决什么问题

编排(Orchestration)模式有一个中央指挥,挨个命令每个 agent "你做这步、再做那步"。这套结构在大多数场景下是对的,但它有两个会顶到天花板的硬约束:中央指挥本身是单点,它挂了整条流程就停;每加一个新 agent,都要回去改中央指挥的逻辑。当 agent 的数量和种类不断增长、业务边界又分属不同团队时,这个中央点会从协调者变成瓶颈。

编舞解决的就是这种规模下的耦合问题。它把中央指挥拿掉,让每个 agent 成为一个自治单元:它只订阅自己关心的事件,事件来了就反应,反应完把结果作为新事件发回到共享的事件流里,不向任何中心汇报。系统的整体行为不再写在某一处的流程图里,而是从所有 agent 的局部"订阅—反应—发布"规则中涌现出来。加一个新 agent,只要让它订阅该订阅的事件,其余 agent 一行都不用改。

这件事值得单独成一个模式,是因为它不是编排的一个参数变体,而是协作拓扑的另一极:控制权从集中变成了分散。它跟扇出聚合、层级委派这些有中心的协作模式,在结构取向上是相反的。

为什么坐标是「协作 × 编舞」

这是协作模块里第一个不落在核心 6 拓扑列上的模式,需要专门说清楚,就像行动模块的最简工具集(A4)落在"约束"而非具体拓扑列上一样。

  • 纵轴 · 协作:编舞描述的是多个 agent 怎么协同,没有单个 agent 的版本,所以纵轴稳稳落在协作模块。
  • 横轴 · 编舞(新兴拓扑,不是核心 6 列之一):核心的 6 个拓扑(链式、路由、并行、循环、层级、编排)有一个共同的隐含前提——存在一个可设计的控制点。链有顺序、路由有路由器、并行有 fan-out/gather、循环有迭代器、层级有经理、编排有指挥。编舞的定义特征就是取消这个控制点。所以它不是核心轴上的第 7 个取值,而是"控制权在不在中心"这根维度的负极。它和编排是一对孪生:编排由指挥协调,编舞由事件协调。

为什么暂时把它放在扩展环、不升为核心第 7 列,有一条清楚的判据:一个拓扑要配当核心列,必须能横切多个认知功能。 链式、路由、并行、循环、层级都铺在好几行上。编舞目前几乎只在协作这一行密集成立,往外只有微弱的回声——记忆行的 event sourcing、推理行的黑板式推理、治理行的事件审计,都沾边但还不密。再加上到 2026 年,绝大多数上了生产的多 agent 系统仍是编排式的,纯编舞的事件驱动 swarm 多在研究与少数去中心化系统里。证据还不够厚,所以先登记为编外扩展模式。升列路径写死:当协作之外能再找到两三行都有生产级实例时,编舞就横切够了,那时和编排成对放进核心轴。

核心机制

编舞由四件工程要素构成:

  1. 共享事件介质:一条事件总线(pub/sub)、一块共享黑板、或一种留痕机制(stigmergy)。所有 agent 通过它间接通信,互相不直接点对点调用。
  2. 自治的订阅—反应单元:每个 agent 声明自己订阅哪些事件,事件到达时判断要不要动、怎么动,动完把结果作为新事件发布回去。它不知道、也不需要知道下一个该谁接。
  3. 涌现的全局行为:没有任何一处持有完整流程。整体协作是所有局部规则在事件流上跑出来的结果。这是编舞的全部威力,也是它全部的麻烦来源。
  4. 显式的终止与可观测:因为没有中心来宣布"任务完成了",必须用显式的终止事件(terminal event)或编排式 saga 的补偿链来界定边界;同时每个事件必须带关联 ID(correlation ID),否则出了问题无法回溯因果链。

适合的生产场景

  • agent 种类多、分属不同团队、要独立演进的生态:每个团队拥有自己的 agent,订阅总线即可加入,不需要去改一个全公司共用的中央编排器。
  • 高吞吐事件流、中央编排会成瓶颈或单点的场景:风控、内容审核、监控告警这类持续有事件涌入、又要求高可用的系统。
  • 环境高度动态、流程无法预先固定的场景:你事先列不全"该走哪些步骤",只能让 agent 各自对当下的事件做反应。
  • 要求弹性、不能有中央故障点的场景:没有中央指挥可挂,单个 agent 失效只损失它那一块职能。

容易出错的地方

  • 没有可观测就上编舞:涌现行为没有中央 trace,出了问题无从查起。编舞强依赖可观测性(G5)——每个事件必须带关联 ID、可按因果链 replay。先有 Observability Harness 再上编舞,顺序反了必踩坑。
  • 事件风暴 / 无限回环:A 发事件触发 B,B 反应又发事件触发 A,循环不收敛。必须做幂等、加事件 TTL、做回环检测。
  • 完成态无人宣布:去中心化之后,"这个任务到底结束没有"变成一个没人能直接回答的问题。要用显式终止事件或 saga 补偿来界定,不能含糊。
  • 拿编舞当万金油:绝大多数系统的默认应该是编排,编舞只在规模、耦合、可用性顶到天花板时才挣得到它的位置。为了"先进"而上编舞,等于用最难调试的拓扑解一个本来一个编排器就够的问题。
  • 想在编舞上强加全局约束:去中心化和治理是天然对冲的。需要强一致的审批、配额、合规约束时,要么保留一个薄的中央 gate(混合式),要么承认编舞不适合这一段。

关键指标

  • 事件可追溯率(健康区 > 95%):能从关联 ID 的事件日志里完整重建一条因果链的比例。这是编舞能不能上生产的前置闸门,直接绑定 G5 可观测性。
  • 收敛率 / 事件风暴率(健康区:失控回环 < 1%):一段协作里正常到达终止事件、而非陷入无限回环的比例。
  • 耦合影响面(健康区 ≈ 0):新增或下线一个 agent,需要改动的其他 agent 数量。这个数趋近于零,正是上编舞的核心收益,也是检验它有没有做对的最直接指标。
  • 端到端延迟(健康区:与编排版可比):去中心化不应该用大幅延迟换弹性,否则得重新评估值不值。

最小实现骨架

# 编排(对照组):中心持有完整计划,挨个命令
orchestrator.run(task):
    for step in plan(task):
        result = agents[step].execute()      # 中心调度
        state.update(result)                 # 中心收口
    return state.result

# 编舞:无中心,各自订阅 + 反应 + 发事件
bus = EventBus()                             # 共享事件介质

class ChoreographedAgent:
    subscribes_to = [...]                    # 我只关心这些事件
    def on_event(self, e):
        if self.should_act(e):               # 自治判断
            out = self.act(e)
            bus.publish(out, correlation_id=e.cid)  # 反应完发新事件,不回报中心

for a in agents:
    bus.subscribe(a.subscribes_to, a.on_event)
bus.publish(initial_event)                   # 点火,之后全靠涌现
# 完成 = 某个 terminal 事件出现;回溯 = 按 correlation_id 串起整条因果链

四个工程要点对应四件要素:EventBus 是共享事件介质;subscribes_to 加 on_event 是自治的订阅—反应单元;没有任何一处持有 plan 是涌现;correlation_id 加 terminal 事件是显式终止与可观测。

企业落地示例

某内容风控平台,第一版用一个中央编排器把每条内容按固定步骤路由:先查垃圾、再查欺诈、再过策略、再决定是否升级人工。业务跑了一年,检测维度从 4 个涨到 20 多个,而且分属垃圾、欺诈、合规、品牌四个团队,每加一个检测器都要去改那个全公司共用的编排器,排期越拖越长,编排器也成了所有内容必经的单点。第二版改成编舞:搭一条内容事件总线,每个检测 agent 订阅 content.received,各自并行反应、各自发出 flag.spam / flag.fraud 这类事件;策略 agent 订阅各种 flag 事件做综合;升级 agent 订阅高危事件、发出 case.opened。新上一个深伪检测器,只要把它订阅到总线,其余 agent 一行不用改,四个团队各自迭代各自的 agent 互不阻塞。

代价也很诚实:他们先补齐了可观测性,每个事件强制带 correlation ID、可按 case 全链路 replay,否则涌现行为根本没法查;并且在最后一段"案件是否彻底处置完"上,保留了一个薄薄的编排式 saga 来界定完成态,因为纯编舞回答不了"这个 case 结没结"。这正是生产里最常见的形态——编舞为主、关键收口处留一个薄编排的混合式,而不是非此即彼。当代主流框架里,AutoGen 在 0.4 版把运行时重构为事件驱动的 actor 模型,是这种编舞倾向最接近主流工程的一个实现;A2A 协议(已捐给 Linux Foundation)也在把多 agent 互操作往事件驱动方向带。

与其他模式的关系

  • 可观测性(G5):硬前置依赖。编舞没有中央 trace,全靠关联 ID 的事件日志回溯因果。没有 G5,编舞不可调试、不可上生产。
  • 编排(散落在层级 / 治理):一对孪生,互为对立面。编排由指挥协调、控制集中;编舞由事件协调、控制分散。生产系统多是两者的混合,而非纯种。
  • 扇出聚合(C2):形似而神不同。扇出有中心负责 fan-out 和 gather,worker 并行但要回到中心收口;编舞连这个中心都没有,反应结果直接进事件流。扇出是有中心的并行,编舞是无中心的协作。
  • 失败日记(记忆模块 M4):event sourcing 是编舞在记忆行的回声——把状态变化记成不可变事件流,本质同源。
  • 爆炸半径控制(G2)/ 审批门(G1):与编舞天然对冲。需要强治理约束的链路,要么保留薄中央 gate,要么不在那一段用编舞。

该模式的启发

编舞看上去是"把编排的指挥撤掉",本质是把协作的控制权从一个中心,下放到每个 agent 的局部规则里——指挥棒换成了事件流,整支舞从没有总谱的各自起舞中跳出队形。它给你弹性和解耦,向你索取的是可观测性和对涌现行为的敬畏。

蓝皮书 · 企业落地实践

我们希望收集这个模式在真实企业系统里如何落地。一个模式可以挂多篇实践,下面是已落档的案例切片。

虚位以待 · 你手上有把这个模式做深的真实系统?欢迎 补一篇企业落地实践 →


本页属于 ADPS 模式白皮书。返回 模式矩阵与白皮书目录, 或查看配套 可运行代码目录