【open-multi-agent】核心架构与设计原理深度解析只描述目标不画任务图的运行时多 Agent 编排框架
【open-multi-agent】核心架构与设计原理深度解析只描述目标不画任务图的运行时多 Agent 编排框架
一、引子:从「画图」到「说目标」的范式跃迁
如果你让 5 个 LLM Agent 协作完成「对比三种 TypeScript ORM 框架并给出推荐」,传统做法是:
flowchart LR
A[开发者] --> B[手画 LangGraph StateGraph]
B --> C[researcher 节点]
B --> D[analyst 节点]
B --> E[writer 节点]
C --> E
D --> E
E --> F[最终输出]每加一个「还要支持性能基准」的需求,你都要回到画板重新编辑 StateGraph 的边。这是一种「图优先(Graph-First)」的范式:用编排图把执行流程「钉死」,LLM 只是图上的填空器。
2026 年 4 月,一个名为 open-multi-agent(以下简称 OMA)的项目提出了截然相反的口号——「Describe the goal, not the graph」(只描述目标,不画任务图):
flowchart LR
A[开发者] --> B[一句话目标]
B --> C[Coordinator<br/>运行时生成 DAG]
C --> D[确定性 Scheduler]
D --> E[AgentPool 并发执行]
E --> F[可回放的数据]OMA 让 Coordinator 在运行时把一个目标分解为任务 DAG,由确定性调度器分派给团队执行,整个运行过程始终是「可审查、可审批、可回放」的数据。这是 2026 H2 多 Agent 框架里最被低估的范式转变——它把「图」从开发期的硬编码产物变成了运行时的派生数据。
本文将基于 open-multi-agent/open-multi-agent 仓库(⭐6,783、MIT 协议、2026-08-17 最新提交)的真实源码,从 Coordinator 调度、5 种调度策略、命名空间共享内存、Durable Approval、评估闭环、OpenTelemetry 兼容等 6 大维度展开深度分析。
二、项目定位与核心价值
2.1 一句话定义
open-multi-agent(OMA) 是一个面向 TypeScript 后端的多智能体编排框架,可以直接 npm install @open-multi-agent/core 嵌入任意 Node.js 应用。它运行的是「动态工作流(Dynamic Workflows)」:Coordinator 在运行时将目标分解为任务 DAG,由确定性 Scheduler 分派给团队执行,整个运行过程始终是可审查、可审批、可回放的数据。
2.2 能力矩阵
| 维度 | 能力 |
|---|---|
| 运行时模式 | runAgent() 单 Agent / runTeam() 动态多 Agent / runTasks() 显式任务管道 |
| 模型支持 | Claude / OpenAI / Gemini / DeepSeek / Copilot / Bedrock / Azure OpenAI / 自定义 OpenAI 兼容 + AI SDK |
| 多进程后端 | Process 后端 + ACP 后端(Agent Control Protocol) 把 Claude Code / Gemini CLI / Codex 接到同一任务图 |
| 共享内存 | 命名空间 SharedMemory(<agentName>/<key>)+ 可插拔 MemoryStore |
| 工具系统 | defineTool() Zod schema + 默认拒绝(default-deny)+ Tool Presets + MCP 集成 |
| 调度策略 | 5 种:round-robin / least-busy / capability-match / dependency-first / composite |
| 持久化 | Checkpoint + 恢复 + Durable Approval + 共识校验(refute/lens)+ 计划冻结与回放 |
| 评估 | 8 类 Scorer(cost / relevancy / dependency / duplicate-work / no-progress / structured-output / tool-call)+ EvalSet + Eval Gate(CI 卡点) |
| 可观测性 | 稳定 RunIdentity + Execution Receipts + Span 瀑布 + 离线 Run Viewer + OpenTelemetry 适配器 |
| 安全 | 工具 default-deny + 调用门控 + Telemetry 隐私控制 + 出站策略(Egress Policy) |
2.3 仓库统计
1 | # 来自 https://api.github.com/repos/open-multi-agent/open-multi-agent |
关键事实:OMA 在 4 个月内冲到 ⭐6.8k,是国内 + 海外双社区共同推动的项目——README 同时提供英文与中文版本,且描述里明确写了「natively integrated Chinese providers」。
三、整体架构
OMA 的 6 层架构可以用下面这张图完整呈现:
flowchart TB
subgraph L1[第 1 层:用户 API]
A1[OpenMultiAgent.runAgent]
A2[OpenMultiAgent.runTeam]
A3[OpenMultiAgent.runTasks]
end
subgraph L2[第 2 层:编排核心]
B1[Coordinator<br/>目标分解]
B3[DeterministicRouter<br/>混合路由]
B2[TaskProfiler<br/>语义画像]
end
subgraph L3[第 3 层:调度与执行]
C1[Scheduler<br/>5 种策略]
C2[TaskQueue<br/>DAG 依赖感知]
C3[AgentPool<br/>信号量限流]
end
subgraph L4[第 4 层:Agent 循环]
D1[AgentRunner<br/>while end_turn]
D2[ToolExecutor<br/>并行调用]
D3[LoopDetector<br/>循环检测]
end
subgraph L5[第 5 层:横切能力]
E1[SharedMemory<br/>命名空间]
E2[ApprovalGate<br/>Durable]
E3[Eval Scorer × 8]
E4[TraceRuntime<br/>v2 records]
end
subgraph L6[第 6 层:基础设施]
F1[LLM Adapter<br/>7+ Provider]
F2[MCP Client]
F3[ACP Backend<br/>CLI 桥接]
F4[Process Backend<br/>本地子进程]
end
L1 --> L2 --> L3 --> L4 --> L5
L4 --> L63.1 顶层类关系
1 | // 来自 packages/core/src/orchestrator/orchestrator.ts:1-50 |
3.2 npm create oma-app 生成的项目结构
1 | my-oma/ |
启动后内置的 Run Viewer Dashboard 会自动打开一个本地 Web 页面,把每一次运行的 DAG 与 Span 瀑布可视化——这是「可回放」承诺的工程化兑现。
四、三种运行模式
OMA 故意提供三种粒度递增的 API,让用户在不同阶段按需切换:
flowchart LR
subgraph M1[显式任务图]
T1[runTasks explicit DAG]
end
subgraph M2[动态编排]
T2[runTeam 自动分解]
end
subgraph M3[单 Agent]
T3[runAgent 直接调用]
end
M1 --> M2 --> M34.1 runAgent() —— 最简单的入口
1 | // 来自 packages/core/src/index.ts:13-19 |
4.2 runTeam() —— 杀手特性
1 | // 来自 packages/core/src/index.ts:21-35 |
注意这段代码里完全没有 DAG——runTeam() 内部会动态启动一个临时的「coordinator agent」,让它把「Write a guide on TypeScript generics」分解为若干任务,再分派给 researcher 和 writer。
4.3 runTasks() —— 退路
当你已经知道明确的依赖关系、想跳过 Coordinator 这一步,可以直接用 runTasks() 提交显式任务数组:
1 | await orchestrator.runTasks([ |
这三种 API 共用一套底座(TaskQueue + Scheduler + AgentPool),所以切换的成本极低。
五、核心引擎一:Coordinator —— 把目标翻译成任务 DAG
Coordinator 是 OMA 最具差异化的子系统。当 runTeam() 被调用时:
sequenceDiagram
participant U as User
participant C as Coordinator
participant L as LLM
participant T as TaskQueue
participant S as Scheduler
participant P as AgentPool
U->>C: runTeam(team, goal)
C->>L: 系统提示 + 团队 roster + 输出格式 schema
L-->>C: JSON 数组(任务列表 + dependsOn)
C->>C: validateTaskDependencies()<br/>检测循环依赖
C->>T: 入队所有 pending 任务
loop 每轮
T->>S: 暴露 ready 任务(依赖全 resolved)
S->>S: autoAssign(strategy)
S->>P: 派发到空闲 Agent
P-->>T: 任务完成 + 产物
end
C->>L: 合成最终答案
C-->>U: TeamRunResult + agentResults + totalTokenUsage5.1 Coordinator 提示词组装
1 | // 来自 packages/core/src/orchestrator/coordinator.ts:60-80 |
关键设计:Coordinator 输出强 schema 的 JSON 数组而非自然语言。extractJSON() 解析后 validateTaskDependencies() 会检测循环依赖。
5.2 验证任务依赖的循环检测
1 | // 来自 packages/core/src/task/task.ts |
5.3 合成最终答案
任务全部跑完后,Coordinator 会再做一次「合成 LLM 调用」,把各 Agent 的产物整合成最终答复:
1 | // 来自 packages/core/src/orchestrator/coordinator.ts (synthesis 段) |
六、核心引擎二:Scheduler —— 5 种任务-智能体匹配策略
OMA 的 Scheduler 不只是「把任务扔给空闲的 Agent」这么简单,它封装了 5 种策略:
1 | // 来自 packages/core/src/orchestrator/scheduler.ts:1-15 |
6.1 5 种策略选择
flowchart TB
Start[autoAssign 入口] --> Q{策略?}
Q -->|round-robin| RR[轮询 cursor++]
Q -->|least-busy| LB[选 active 任务最少 Agent]
Q -->|capability-match| CM[requires 过滤 + 关键词打分]
Q -->|dependency-first| DP[选 critical path 头节点]
Q -->|composite| CO[关键度 × 能力 × 负载 加权]6.2 capability-match 示例
1 | // 来自 packages/core/src/orchestrator/scheduler.ts (capability-match 段) |
6.3 默认调度:composite
大多数场景下,composite 是默认策略——它把任务的关键度(被依赖的子孙越多越关键)、能力匹配度、当前负载三件事加权成单一分数:
1 | const score = |
这是 OMA 的「承认不确定」哲学——它不试图用一个万能公式,而是让用户按需切换 5 种策略。
七、核心引擎三:AgentPool + AgentRunner
7.1 AgentPool —— 信号量限流 + Per-Agent Mutex
1 | // 来自 packages/core/src/agent/pool.ts:1-50 |
两个关键设计:
- 全局信号量 控制所有 Agent 的并发上限(避免打爆 LLM API 限流)。
- Per-Agent Mutex 保证同一个 Agent 实例的两条任务严格串行——否则两个任务同时往
this.messages推会破坏 LLM 上下文。
7.2 AgentRunner —— 经典 while-end_turn 主循环
1 | // 来自 packages/core/src/agent/runner.ts (核心循环) |
关键工程细节:
- 工具调用并行执行(
executeAll),而不是串行——大幅缩短 latency。 - LoopDetector 检测重复模式(同一组 tool call 出现 ≥ N 次),防止 Agent 陷入死循环。
- Token 预算硬约束,超额直接抛
TokenBudgetExceededError——让「Agent 烧光所有 token」不可能发生。
八、共享内存:Namespaced SharedMemory
OMA 的 SharedMemory 设计非常优雅——每个 Agent 写入时使用自己的命名空间,但读取时不受限制:
1 | // 来自 packages/core/src/memory/shared.ts:30-60 |
flowchart LR
R[researcher] -->|write 'findings', 'TS 5.5 ships X'| M[(SharedMemory Store)]
W[writer] -->|read 'researcher/findings'| M
W -->|write 'draft', v1| M
E2[editor] -->|read 'researcher/findings'| M
E2 -->|read 'writer/draft'| M8.1 MemoryStore 抽象
1 | // 来自 packages/core/src/memory/store.ts |
生产场景可以替换为 Redis 或 SQLite 后端——只要满足同一接口。MemoryStore 的存在让 SharedMemory 既能在 demo 中零依赖跑通,也能在生产中横向扩展。
8.2 为什么是「命名空间」而不是「共享扁平 KV」
如果所有 Agent 都写到一个全局 KV,多个 Agent 同时写 findings 会互相覆盖。命名空间化后:
- 可归属:每条 entry 都能溯源到具体 Agent。
- 可隔离:同名 key 不会冲突。
- 可观察:
getSummary()能按 Agent 分组生成自然语言摘要。
九、Durable Approval —— 内容绑定的持久化审批
OMA 的 Approval 子系统是为「LLM 真的要做危险动作」的场景设计的。它不只是一个布尔开关,而是绑定具体内容 + 持久化 + 可恢复的完整审批协议。
sequenceDiagram
participant A as Agent
participant G as ApprovalGate
participant S as MemoryStore
participant H as Human Reviewer
A->>G: requestApproval({tool: 'bash', args: 'rm -rf /tmp/build'})
G->>S: 写入 ApprovalRecord<br/>key=__oma_approval__/<uuid>
S-->>H: 通知(webhook/CLI/email)
H->>S: writeDecision({requestId, decision: 'reject', reason})
G->>S: 读取决策 + sha256 校验
G-->>A: ApprovalDecisionRecord
A->>A: 仅在 decision === 'approve' 时执行9.1 内容绑定(Content Binding)
1 | // 来自 packages/core/src/approval/durable.ts:30-50 |
关键点:每个审批请求的 SHA-256 指纹基于完整内容计算。这意味着即使人类审批时延迟了 5 分钟,Agent 不能中途偷偷修改请求内容——任何修改都会让指纹失效,决策被拒绝。
9.2 6 类错误码
1 | // 来自 packages/core/src/approval/durable.ts |
这套显式错误码让运维可以精准报警「Approval 冲突 vs 完整性错误 vs 决策延迟」是完全不同的根因。
十、可观测性:v2 Trace Records + 离线 Run Viewer
10.1 稳定 RunIdentity
OMA 给每次运行分配一个 稳定的 RunIdentity,整个运行期间的所有 span、receipt、approval 都用同一 ID 关联:
1 | // 来自 packages/core/src/observability/runtime.ts |
10.2 v2 TraceRecord 流
1 | // 来自 packages/core/src/observability/runtime.ts |
关键工程细节:
safeEmit(sink, record)用 try/catch 包住 sink 回调——遥测永远不能改变执行语义(即使 sink 抛错也不能让 Agent 崩溃)。- CompositeSink 支持多个 sink 并行(本地文件 + OTLP + 控制台)。
10.3 离线 Run Viewer
1 | // 来自 packages/core/src/dashboard/render-run-viewer.ts |
这是 OMA 与所有同类框架的最大差异之一:你离线打开浏览器就能回放任意一次运行——不需要服务器、不需要数据库、不需要登录。这种「自带 Dashboard」的设计哲学,让调试多 Agent 系统从「翻日志」变成「看时间线」。
十一、ACP 后端:把 Claude Code / Codex 接到 OMA 任务图
这是 OMA 最具野心的设计——通过 Agent Control Protocol(ACP) 把第三方 CLI Agent 接到 OMA 的统一任务图:
flowchart LR
subgraph OMA[OMA Runtime]
Q[TaskQueue]
S[Scheduler]
end
subgraph ACP[ACP Backend]
P1[claude-code 子进程]
P2[gemini-cli 子进程]
P3[codex 子进程]
end
Q --> S
S -->|runTask| P1
S -->|runTask| P2
S -->|runTask| P3
P1 -->|stdout JSONL| S
P2 -->|stdout JSONL| S
P3 -->|stdout JSONL| S意义:OMA 让一个团队既能包含「自己写的 LLM Agent」,也能包含「Claude Code 这种成品 CLI」——它们共享同一个任务 DAG、同一份共享内存、同一套 token 预算。这是「多 Agent 跨形态」的开山之作。
十二、Eval 系统:8 类 Scorer + Eval Gate
1 | // 来自 packages/core/src/eval/index.ts |
12.1 Eval Gate —— CI 卡点
1 | // 来自 packages/core/src/eval/gate.ts |
实战用法:
1 | # eval-gate.yml |
每次 PR 把 EvalSet 跑一遍,evaluateGate() 决定是否合并。这是 OMA 把「多 Agent 评估」从「研究 demo」变成「工程红线」的关键机制。
十三、端到端数据流
把上面所有模块串起来的完整时序:
sequenceDiagram
participant U as User
participant O as OpenMultiAgent
participant C as Coordinator
participant L as LLM
participant Q as TaskQueue
participant S as Scheduler
participant P as AgentPool
participant R as AgentRunner
participant M as SharedMemory
participant T as TraceRuntime
participant V as Run Viewer
U->>O: runTeam(team, goal)
O->>T: start runId=abc123
O->>C: 分解目标
C->>L: coordinator prompt
L-->>C: JSON 任务数组
C->>Q: enqueue + validateTaskDependencies
loop 每轮 ready 任务
Q->>S: 暴露 ready
S->>S: composite 评分
S->>P: 派发
P->>R: AgentRunner.run
R->>L: chat
L-->>R: tool_use
R->>M: write 'researcher/findings'
R-->>P: AgentRunResult
P-->>Q: 任务 completed
end
C->>L: synthesize prompt
L-->>C: 最终答案
O->>T: end runId=abc123
O-->>V: 写入 .oma/runs/abc123.json
O-->>U: TeamRunResult十四、与同类项目对比
OMA 不是「又一个 LangGraph」,它代表了多 Agent 框架的第三种范式:
| 维度 | LangGraph | MetaGPT | OpenAI Agents SDK | OMA |
|---|---|---|---|---|
| 范式 | 静态 StateGraph | SOP 流水线 | Handoff 协议 | 动态 DAG |
| 入口 | 开发者画图 | RFC 协议驱动 | tool call 编排 | 只说目标 |
| 执行模式 | 显式 transition | 按顺序执行角色 | 显式 handoff | 自动分解 + 并发 |
| 调度策略 | 由图决定 | 由 RFC 决定 | 由开发者编排 | 5 种运行时策略 |
| 共享内存 | 节点间显式传 | 三层 Memory | Conversation 上下文 | Namespaced SharedMemory |
| 审批 | 需自己写 | 需自己写 | 需自己写 | Durable Approval 内置 |
| 评估 | LangSmith | 无 | 无 | 8 类 Scorer + Eval Gate |
| 可视化 | LangGraph Studio | 无 | 无 | 离线 Run Viewer |
| 后端 | Python | Python | Python | TypeScript + ACP 多后端 |
核心差异:
- LangGraph 是「静态编排图」:开发者画好边,LLM 跑。
- MetaGPT 是「SOP 流水线」:17 个角色按 RFC 协议串起来。
- OpenAI Agents SDK 是「Handoff 协议」:Agent 之间用 handoff 转交控制权。
- OMA 是「动态 DAG」:Coordinator 运行时生成图,确定性 Scheduler 执行。
OMA 真正解决了什么:当目标频繁变化、你不愿每次都回去改 StateGraph 时,OMA 让「Coordinator 替你画图」——这是 2024 年以来多 Agent 框架里**第一个严肃落地「运行时编排」**的项目。
十五、优缺点分析
15.1 架构简洁性 vs 性能复杂度
| 维度 | 优势 | 代价 |
|---|---|---|
| 运行时 DAG | 开发者不用画图 | 每次运行都要 Coordinator LLM 调用(增加延迟与 token) |
| 5 种调度策略 | 灵活选择 | 需要理解「composite vs capability-match」差异 |
| Namespaced Memory | 可归属、可隔离 | 多写一次 <agentName>/ 前缀 |
| Durable Approval | 内容绑定、可恢复 | 需要原子 MemoryStore 后端 |
| 离线 Run Viewer | 零依赖调试 | 不能跨机器共享回放(除非同步 .oma/ 目录) |
| ACP 后端 | 多形态 Agent 协同 | 子进程 stdout 解析成本 |
| TypeScript 优先 | 嵌入 Node.js 后端无门槛 | Python AI 生态(DSPy/LlamaIndex)需要桥接 |
15.2 扩展性 vs 维护性
| 维度 | 优势 | 代价 |
|---|---|---|
| MemoryStore 抽象 | 任意后端(Redis/SQLite/PG) | 自定义实现需保证原子性 |
| LLM Adapter 抽象 | 7+ Provider + AI SDK | 每次新增 Provider 要写格式转换 |
| Tool 框架 | Zod schema + 默认拒绝 | 工具多时审批矩阵变复杂 |
| Eval Scorer | 8 类内置 + 可扩展 | 需要持续运营 EvalSet |
| OpenTelemetry 适配 | 兼容现有监控 | 与自研 TraceRuntime 有概念重叠 |
十六、实践 / 快速开始
16.1 安装
1 | # 来自 https://github.com/open-multi-agent/open-multi-agent |
16.2 第一个团队
1 | import { OpenMultiAgent } from '@open-multi-agent/core' |
16.3 自定义工具
1 | import { z } from 'zod' |
16.4 添加 Eval Gate
1 | import { runEvalSet, evaluateGate } from '@open-multi-agent/core' |
十七、趋势 + 总结
17.1 三大趋势判断
「运行时编排」将成为多 Agent 框架的事实标准 —— OMA 把「图是派生的不是手画的」这一原则落地后,未来 12 个月我们很看到 LangGraph、MetaGPT、Autogen 都增加「Coordinator 自动分解」模式。「画图」是开发期负担,「说目标」才是产品期能力。
ACP 后端让「Coding Agent CLI」成为一等公民 —— Claude Code / Gemini CLI / Codex 在 2026 H2 将不再只是「独立终端工具」,而是 OMA 这类调度器的可调用组件。多 Agent 跨形态 = LLM Agent + Coding Agent CLI + Computer-Use Agent。
Durable Approval + Eval Gate 是多 Agent 上生产的必要条件 —— 「让 Agent 自动做事」容易,「让 Agent 自动做事且能审计、能回滚、能评估」很难。OMA 把这 3 件事做成框架级基础设施,是 2026 H2 多 Agent 工程化的最关键架构进步。
17.2 工程经验提炼
- 「图是派生的」原则:不要在开发期硬编码执行流程,让 LLM 在运行时生成图——但必须有确定性 Scheduler 兜底(OMA 的
composite策略就是兜底)。 - 「每个跨进程边界都是稳定 ID」:RunIdentity、SpanId、ApprovalId 必须稳定可关联,否则无法做后置分析。
- 「遥测永远不能改变执行语义」:所有 sink emit 都要 try/catch 包住——OMA 的
safeEmit()是教科书级别的范式。 - 「命名空间化共享内存」:直接共享扁平 KV 会冲突,按 Agent 命名空间化是最低成本的方案。
17.3 一句话总结
open-multi-agent(OMA)以「Describe the goal, not the graph」为口号,用 Coordinator 运行时生成任务 DAG + 5 种调度策略 + Namespaced SharedMemory + Durable Approval + 8 类 Eval Scorer + 离线 Run Viewer + ACP 多后端桥接,在 TypeScript 后端上构建了 2026 H2 最完整的多智能体生产框架。
附录:关键资源
核心源文件引用清单:
packages/core/src/orchestrator/orchestrator.ts—— OpenMultiAgent 主类(124K 字符)packages/core/src/orchestrator/coordinator.ts—— 目标分解 + 合成(30K 字符)packages/core/src/orchestrator/scheduler.ts—— 5 种调度策略packages/core/src/agent/runner.ts—— while-end_turn LLM 循环(71K 字符)packages/core/src/agent/pool.ts—— AgentPool 信号量限流packages/core/src/team/team.ts—— Team 实体(11K 字符)packages/core/src/task/task.ts—— Task 工厂 + 循环依赖检测packages/core/src/memory/shared.ts—— Namespaced SharedMemory(20K 字符)packages/core/src/approval/durable.ts—— Durable Approval(18K 字符)packages/core/src/observability/runtime.ts—— TraceRuntime v2(8K 字符)packages/core/src/dashboard/render-run-viewer.ts—— 离线 Run Viewerpackages/core/src/eval/index.ts—— 8 类 Scorer 入口