跳到主要内容

open-multi-agent — 这是什么 · 全景 · 阅读地图

30 秒导读: open-multi-agent(简称 OMA)是一个给 TypeScript 后端用的多智能体编排框架。你给它一个目标(一句自然语言),一个"协调者(coordinator)" agent 会在运行时把目标拆成一张任务 DAG(有向无环图),让互不依赖的任务并行跑,最后把各任务结果合成一份答案。一行 runTeam(team, goal) 就跑起来。本篇只建立大盘认知,不深入任何单个子系统——细节路由到各章。


1. 这是什么(零基础也能懂)

一句话定义。 OMA 是一个"你说目标、它排活并干完"的多智能体编排引擎,原生长在 Node.js / TypeScript 里。

解决什么问题。 假设你要让一队 AI 协作完成一件复杂事——"给待办清单做一套 REST API":要先设计接口、再写实现、同时搭测试、最后有人 review。传统"图优先(graph-first)"框架(如 LangGraph)要你开跑前手工画好每个节点和每条边。OMA 反过来:你只描述目标,拆图这件事交给协调者在运行时做。README 把这句话印在最显眼处(README.md:44 Your engineers describe the goal, not the graph.)。

给谁用。 用 TypeScript 写后端、想加一层"多 agent 协作"、又不想为此另起一个 Python 服务的团队(README.md:78 vs. CrewAI 段)。

它能做什么(功能一览):

  • 目标驱动的自动编排:一次 runTeam 完成拆解 → 并行 → 合成。
  • 三种执行模式:单 agent、自动编排团队、显式任务流水线(下面第 2 节)。
  • 混用 13 个内置模型 provider + 任意 OpenAI 兼容端点,一支队伍里自由搭配。
  • 工具系统:6 个内置工具(bash/file_*/grep/glob)默认全部拒绝,按需授权;可自定义工具、接 MCP。
  • 生产控件:token 预算、重试退避、上下文压缩、检查点恢复、观测面板、密钥自动脱敏。

用起来什么样(最小真实用例)。 下面是 README 的官方最小示例,核心就是最后那行 runTeam——建一支队伍,给一个目标,拿回结果(节选自 packages/core/README.md:87):

const orchestrator = new OpenMultiAgent({ defaultProvider: 'openai', defaultModel: model })

const team = orchestrator.createTeam('api-team', { name: 'api-team', agents, sharedMemory: true })

// 给目标,不给图。协调者自己拆任务、并行、合成。
const result = await orchestrator.runTeam(
team,
`Create a REST API for a todo list in ${process.cwd()}/.agent-workspace/todo-api/`,
)
console.log(result.success, result.totalTokenUsage.output_tokens)

一句话直觉/类比。 把 OMA 当一个项目经理:你交给它一句"目标",它自己拆成工单、分给合适的人、能并行的并行、有人卡住就绕过、最后把大家的产出汇成一份交付。你不用画甘特图,它当场排。


2. 顶层全景(它大概怎么转)

三种执行模式:先分清你在用哪一种

OMA 对外的门面类叫 OpenMultiAgent(packages/core/src/orchestrator/orchestrator.ts:1514)。它有三个入口方法,复杂度递增,这是理解全库的第一个岔路口:

模式方法谁来拆任务什么时候用
单 agent 一发入魂runAgent(config, prompt)没有任务,一个 agent 跑一个 prompt简单一次性问答
自动编排团队(招牌功能)runTeam(team, goal)协调者 agent 运行时拆给目标、让它自己规划并执行
显式任务流水线runTasks(team, tasks)你自己写好 dependsOn你已经知道任务图长什么样

三个方法的类文档就写在源码里:runAgent(orchestrator.ts:1595,"single agent, one-shot")、runTeam(orchestrator.ts:1684,标注 KILLER FEATURE)、runTasks(orchestrator.ts:2199,"no coordinator agent is involved")。另有 runConsensus(orchestrator.ts:2240,提议者→裁判校验)是可信度增强,见第 05 章。

runTeamrunTasks 的关键区别:前者多了一个协调者拆解 + 最后合成的环节;后者跳过协调者,你给的任务直接进队列(orchestrator.ts:2192 注释:"Simpler than runTeam: no coordinator agent is involved")。

一张顶层图:runTeam 主线怎么流

这是全库最核心的一条链路。怎么读这张图:从上到下是一次 runTeam 的时间顺序;协调者出现两次(开头拆解、结尾合成),中间是"排活—调度—并行执行—写记忆"的循环。

你的输入: 一个 team(agent 名册) + 一个 goal(自然语言)


┌────────────────────────────────┐
│ OpenMultiAgent (门面 / 编排器) │ orchestrator.ts
│ runTeam / runTasks / runAgent │
└────────────────┬─────────────────┘

①简单目标就短路,直接派给最合适的 agent(不拆)
│ isSimpleGoal() 命中?
▼ 否 → 走完整编排
┌────────────────────────────────┐
│ Coordinator(临时协调者 agent) │ ②拆解
│ 收「目标 + 名册」→ 吐一个 JSON │
│ 任务数组(标题/描述/负责人/依赖)│
└────────────────┬─────────────────┘
│ 解析 JSON,标题依赖 → 任务 ID

┌────────────────────────────────┐
│ TaskQueue(依赖感知队列) │ task/queue.ts
│ pending → blocked → ready │
│ 某任务完成 → 自动解锁下游 │
│ 某任务失败 → 级联标记下游 │
└───────┬──────────────────┬───────┘
│ 谁没指定负责人? │ 哪些任务 ready?
▼ ▼
┌───────────────────┐ ┌──────────────────────┐
│ Scheduler(调度) │ │ AgentPool(并发池) │ agent/pool.ts
│ 4 种分配策略 │ │ Semaphore 限并发 │
│ 给任务挑 agent │ │ 独立任务并行跑 │
└───────────────────┘ └──────────┬───────────┘
│ 每个被选中的 agent

┌──────────────────────────┐
│ Agent loop(对话循环) │ agent/runner.ts
│ 调模型 → 抽工具调用 → │
│ 执行工具 → 回填 → 再循环 │
│ 直到 end_turn │
└──────────┬────────────────┘
│ 任务产出

┌──────────────────────────┐
│ SharedMemory(共享内存) │ memory/shared.ts
│ <agentName>/<key> 命名空间 │
│ 下游 agent 读上游的产出 │
└──────────┬────────────────┘
│ 所有任务跑完

┌────────────────────────────────┐
│ Coordinator(再登场) │ ③合成
│ 读全部任务产出 → 合成最终答案 │ runCoordinatorSynthesis()
└────────────────┬─────────────────┘

返回 TeamRunResult(含最终答案 + token 用量)

部件一句话职责

部件干什么在哪(相对 packages/core/)
OpenMultiAgent顶层门面,三种执行模式的入口src/orchestrator/orchestrator.ts:1514
Coordinator(协调者)runTeam 里临时起的 agent,负责拆解合成同上,runTeam / runCoordinatorSynthesis(orchestrator.ts:2531)
Teamagent 名册 + MessageBus + SharedMemory 的绑定src/team/team.ts
TaskQueue依赖感知队列:自动解锁下游、失败级联src/task/queue.ts:55
Scheduler给没指定负责人的任务挑 agent(4 种策略)src/orchestrator/scheduler.ts
AgentPoolSemaphore 限并发,让独立任务并行src/agent/pool.ts:58
Agent / AgentRunner单个 agent 的对话循环:调模型 ↔ 执行工具src/agent/agent.ts:95src/agent/runner.ts
LLMAdapter统一 chat/stream 接口,13 个 provider 懒加载src/llm/adapter.ts
SharedMemory命名空间 KV,agent 之间传产出src/memory/shared.ts
ToolRegistrydefineTool() 注册、内置工具、MCP 桥src/tool/framework.ts
Dashboard把跑完的任务 DAG 渲染成纯 HTMLsrc/dashboard/

主线走一遍(高层,不进代码)

  1. 入口。 你调 runTeam(team, goal)。若目标够简单(短、无多步/协作信号),会短路——直接派给最匹配的 agent,不请协调者(orchestrator.ts:1702,isSimpleGoal)。这一步的判定规则见 01 章
  2. 拆解。 否则起一个临时协调者 agent,把"目标 + agent 名册"喂给它,让它吐一个 JSON 任务数组(标题、描述、负责人、dependsOn)。
  3. 建图。 任务进 TaskQueue,标题形式的依赖被解析成任务 ID;队列据此把任务标成 pending/blocked/ready
  4. 调度。 没写负责人的任务,由 Scheduler 按策略挑 agent(默认 dependency-first)。
  5. 并行执行。 AgentPool 用信号量限并发,ready 的独立任务并行跑;每个 agent 进自己的对话循环(调模型 → 执行工具 → 回填 → 循环)。
  6. 传产出。 每个任务完成,结果写进 SharedMemory,下游 agent 能读到;完成事件让队列自动解锁下游任务。
  7. 合成。 全部任务跑完,协调者再登场,读所有产出合成最终答案。
  8. 返回。 得到 TeamRunResult(成功与否、最终答案、总 token 用量)。

3. 巧妙之处速览(这一章只点名,细节在各章)

这些是 OMA "值得带走"的设计决策。每条一句话点破"妙在哪",然后指向深入的章节。

计划是数据,不是硬编码的图。 协调者产出的不是代码控制流,而是一段 JSON 任务数组,交给一个确定性调度器执行。因此计划可预览(planOnly)、可固化成工件(createPlanArtifact,orchestrator.ts:1999)、可重放(runFromPlan,orchestrator.ts:2034)——同一张图不必再请协调者就能重跑。README 的定位句:"the plan is inspectable and replayable"(README.md:46)。→ 01 章

简单目标短路。 不是所有目标都值得起一个协调者。isSimpleGoal()(orchestrator.ts:165)用一组保守的正则(COMPLEXITY_PATTERNS,orchestrator.ts:114)判断目标是否含"多步/协作/并行"信号,不含就直接派单个 agent,省掉一趟拆解 + 合成。→ 01 章

失败不炸整局,而是级联标记下游。 一个任务失败,直接把依赖它的下游任务级联标为失败(cascadeFailure,queue.ts:259),但互不依赖的任务照跑。这条"优雅失败"写在类文档里(orchestrator.ts:37)。→ 02 章

工具默认全拒绝(default-deny)。 内置工具默认一个都不给;agent 只拿到它在 tools/toolPreset 里明列的。这是把"读/执行权限"从默认开变成默认关的安全姿态(CLAUDE.md:65)。→ 03 章

依赖懒加载,核心只三个运行时依赖。@open-multi-agent/core 只拉进 @anthropic-ai/sdkopenaizod 三个。Gemini、Bedrock、MCP、AI SDK 桥都是可选 peer,通过动态 import() 懒加载,不用就不装(CLAUDE.md:31)。→ 04 章

跨 provider 的推理保留。 一个 thinking 配置映射到 Anthropic thinking / Gemini thinkingConfig / OpenAI reasoning_effort;换 provider 时推理块默认会被丢弃,除非显式开 preserveReasoningAsText(CLAUDE.md:68)。→ 04 章

密钥自动脱敏。 API key、token、Authorization 头会从 trace、bash 输出、面板载荷里自动抹掉(utils/redaction.ts,CLAUDE.md:70)。→ 05 章


4. 阅读地图(这套文档怎么读)

这是一套多文件文档。本篇(index)建立大盘认知,细节分在五章。建议顺序就是章节编号顺序——它按"由浅入深、跟着数据流走"排:

你在这里


index.md ──────► 这是什么 · 全景 · 阅读地图(先读,建立大盘)

├──► 01 Coordinator 模式:从目标到任务 DAG
│ 协调者怎么拆解、简单目标短路、依赖解析、Scheduler 的 4 种分配策略

├──► 02 任务图的调度执行
│ TaskQueue 的 pending/blocked/ready 状态机、自动解锁、失败级联、重试退避

├──► 03 单个 Agent 怎么跑
│ 对话循环(调模型↔执行工具)、工具默认拒绝、文件系统沙箱、delegate 委派

├──► 04 对接模型
│ 懒加载适配器、OpenAI 兼容端点、跨 provider 推理 round-trip、上下文压缩

└──► 05 协作与可信
共享内存、MessageBus、runConsensus 共识校验、检查点恢复、观测/面板

按需跳读:

你想弄清直接去
"给个目标怎么就变成任务图了"01
"任务之间的依赖、失败、重试怎么处理"02
"一个 agent 内部一轮一轮怎么调模型和工具"03
"怎么接不同模型 / 本地模型 / 控制上下文长度"04
"agent 之间怎么共享数据 / 怎么保证结果可信 / 怎么观测"05

5. 代码地图(导航索引)

按符号名 grep 比按行号更抗漂移。下面是先读这几个入口就能摸到大盘的关键符号(路径相对 packages/core/):

主题文件符号
顶层门面 / 公共 APIsrc/orchestrator/orchestrator.tsOpenMultiAgent
三种执行模式src/orchestrator/orchestrator.tsrunAgent / runTeam / runTasks
简单目标短路判定src/orchestrator/orchestrator.tsisSimpleGoal / COMPLEXITY_PATTERNS
协调者合成最终答案src/orchestrator/orchestrator.tsrunCoordinatorSynthesis
计划工件 / 重放src/orchestrator/orchestrator.tscreatePlanArtifact / runFromPlan
共识校验src/orchestrator/orchestrator.tsrunConsensus
公共导出面src/index.tsexport { OpenMultiAgent, Agent, Team, ... }
任务队列(状态机 + 级联)src/task/queue.tsTaskQueue / unblockDependents / cascadeFailure
调度策略src/orchestrator/scheduler.tsScheduler / SchedulingStrategy
并发池src/agent/pool.tsAgentPool / Semaphore / runParallel
单 agent 对话循环src/agent/runner.tsAgentRunner(resolveTools 决定工具授权)
agent 门面src/agent/agent.tsAgent(run / prompt / stream)
模型适配器工厂src/llm/adapter.tscreateAdapter / SupportedProvider
共享内存src/memory/shared.tsSharedMemory(write / read / getSummary)
工具框架src/tool/framework.tsdefineTool / ToolRegistry
密钥脱敏src/utils/redaction.ts(脱敏助手)

锁定源码提交: 本页所有引用 as-of commit fdcdd0c6561c163a4d72cae204c262dc0241bd28