open-multi-agent/README_zh.md

22 KiB
Raw Blame History

Open Multi-Agent

TypeScript 里的轻量多智能体编排引擎。3 个运行时依赖,零配置,一次 runTeam() 从目标拿到结果。

CrewAI 是 Python。LangGraph 要你自己画图。open-multi-agent 是你现有 Node.js 后端里 npm install 一下就能用的那一层:一支 agent 团队围绕一个目标协作,就这些。

npm version GitHub stars license TypeScript runtime deps codecov

English | 中文

核心能力

  • runTeam(team, "构建一个 REST API") 下去,协调者 agent 会把目标拆成任务 DAG独立任务并行跑再把结果合起来。不用画图不用手动连依赖。
  • 运行时依赖就三个:@anthropic-ai/sdkopenaizod。能直接塞进 Express、Next.js、Serverless 或 CI/CD不起 Python 进程,也不跑云端 sidecar。
  • 同一个团队里的 agent 能挂不同模型:架构师用 Opus 4.6、开发用 GPT-5.4、评审跑本地 Gemma 4 都行。支持 Claude、GPT、Gemini、Grok、MiniMax、DeepSeek、Copilot以及 OpenAI 兼容的本地模型Ollama、vLLM、LM Studio、llama.cpp。用 Gemini 要额外装 @google/genai

还有 MCP、上下文策略、结构化输出、任务重试、human-in-the-loop、生命周期 hook、循环检测、可观测性等下面章节或 examples/ 里都有。

做什么,不做什么

做的事:

  • 一个协调者,把目标拆成任务 DAG。
  • 一个任务队列,独立任务并行跑,失败级联到下游。
  • 共享内存和消息总线,让 agent 之间能看到彼此的输出。
  • 多模型团队,每个 agent 可以挂不同的 LLM provider。

不做的事:

  • Agent handoffsagent A 对话中途把控制权交给 agent B 这种模式不做。要这个用 OpenAI Agents SDK。我们这边一个 agent 从头到尾负责一个任务。
  • 状态持久化 / 检查点:暂时不做。加存储后端会破坏 3 个依赖的承诺,而且我们的工作流是秒到分钟级,不是小时级。真有长时间工作流的需求再说。

A2A 协议在跟踪,观望中,等有人真用再跟。

完整理由见 DECISIONS.md

和其他框架怎么选

如果你在看 LangGraph JS:它是声明式图编排,自己定义节点、边、路由,compile() + invoke()open-multi-agent 反过来,目标驱动:给一个团队和一个目标,协调者在运行时拆 DAG。想完全控拓扑、流程定下来的用 LangGraph想写得少、迭代快、还在探索的选这个。LangGraph 有成熟 checkpoint我们没做。

Python 栈直接用 CrewAI 就行,编排层能力差不多。open-multi-agent 的定位是 TypeScript 原生3 个依赖、直接进 Node.js、不用子进程桥接。按语言选。

Vercel AI SDK 不冲突。AI SDK 是 LLM 调用层,统一的 TypeScript 客户端60+ provider带流式、tool call、结构化输出但不做多智能体编排。要多 agentopen-multi-agent 叠在 AI SDK 上面就行。单 agent 用 AI SDK多 agent 用这个。

谁在用

项目 2026-04-01 发布,目前 5,500+ starsMIT 协议。目前能确认在用的:

  • temodar-agent(约 50 stars。WordPress 安全分析平台,作者 Ali Sünbül。在 Docker runtime 里直接用我们的内置工具(bashfile_*grep)。已确认生产环境使用。
  • 家用服务器 Cybersecurity SOC。 本地完全离线跑 Qwen 2.5 + DeepSeek Coder通过 Ollama在 Wazuh + Proxmox 上搭自主 SOC 流水线。早期用户,未公开。

如果你在生产或 side project 里用了 open-multi-agent请开个 Discussion,我加上来。

快速开始

需要 Node.js >= 18。

npm install @jackchen_me/open-multi-agent

根据用的 provider 设对应 API key。通过 Ollama 跑本地模型不用 keyproviders/ollama

  • ANTHROPIC_API_KEY
  • AZURE_OPENAI_API_KEYAZURE_OPENAI_ENDPOINTAZURE_OPENAI_API_VERSIONAZURE_OPENAI_DEPLOYMENTAzure OpenAImodel 为空时可用 deployment 环境变量兜底)
  • OPENAI_API_KEY
  • GEMINI_API_KEY
  • XAI_API_KEYGrok
  • MINIMAX_API_KEYMiniMax
  • MINIMAX_BASE_URLMiniMax可选选接入端点
  • DEEPSEEK_API_KEYDeepSeek
  • GITHUB_TOKENCopilot

包里还自带一个叫 oma 的命令行工具,给 shell 和 CI 场景用,输出都是 JSON。oma runoma taskoma provider、退出码、文件格式都在 docs/cli.md 里。

下面用三个 agent 协作做一个 REST API

import { OpenMultiAgent } from '@jackchen_me/open-multi-agent'
import type { AgentConfig } from '@jackchen_me/open-multi-agent'

const architect: AgentConfig = {
  name: 'architect',
  model: 'claude-sonnet-4-6',
  systemPrompt: 'You design clean API contracts and file structures.',
  tools: ['file_write'],
}

const developer: AgentConfig = { /* 同样结构tools: ['bash', 'file_read', 'file_write', 'file_edit'] */ }
const reviewer: AgentConfig = { /* 同样结构tools: ['file_read', 'grep'] */ }

const orchestrator = new OpenMultiAgent({
  defaultModel: 'claude-sonnet-4-6',
  onProgress: (event) => console.log(event.type, event.agent ?? event.task ?? ''),
})

const team = orchestrator.createTeam('api-team', {
  name: 'api-team',
  agents: [architect, developer, reviewer],
  sharedMemory: true,
})

// 描述一个目标,框架负责拆解成任务并编排执行
const result = await orchestrator.runTeam(team, 'Create a REST API for a todo list in /tmp/todo-api/')

console.log(`Success: ${result.success}`)
console.log(`Tokens: ${result.totalTokenUsage.output_tokens} output tokens`)

执行过程:

agent_start coordinator
task_start architect
task_complete architect
task_start developer
task_start developer              // 无依赖的任务并行执行
task_complete developer
task_complete developer
task_start reviewer               // 实现完成后自动解锁
task_complete reviewer
agent_complete coordinator        // 综合所有结果
Success: true
Tokens: 12847 output tokens

三种运行模式

模式 方法 适用场景
单智能体 runAgent() 一个智能体,一个提示词,最简入口
自动编排团队 runTeam() 给一个目标,框架自动规划和执行
显式任务管线 runTasks() 你自己定义任务图和分配

要 MapReduce 风格的 fan-out 但不需要任务依赖,直接用 AgentPool.runParallel()。例子见 patterns/fan-out-aggregate

示例

examples/ 按类别分了 basics、providers、patterns、integrations、production。完整索引见 examples/README.md,几个值得先看的:

跑脚本用 npx tsx examples/basics/team-collaboration.ts

架构

┌─────────────────────────────────────────────────────────────────┐
│  OpenMultiAgent (Orchestrator)                                  │
│                                                                 │
│  createTeam()  runTeam()  runTasks()  runAgent()  getStatus()   │
└──────────────────────┬──────────────────────────────────────────┘
                       │
            ┌──────────▼──────────┐
            │  Team               │
            │  - AgentConfig[]    │
            │  - MessageBus       │
            │  - TaskQueue        │
            │  - SharedMemory     │
            └──────────┬──────────┘
                       │
         ┌─────────────┴─────────────┐
         │                           │
┌────────▼──────────┐    ┌───────────▼───────────┐
│  AgentPool        │    │  TaskQueue             │
│  - Semaphore      │    │  - dependency graph    │
│  - runParallel()  │    │  - auto unblock        │
└────────┬──────────┘    │  - cascade failure     │
         │               └───────────────────────┘
┌────────▼──────────┐
│  Agent            │
│  - run()          │    ┌──────────────────────┐
│  - prompt()       │───►│  LLMAdapter          │
│  - stream()       │    │  - AnthropicAdapter  │
└────────┬──────────┘    │  - OpenAIAdapter     │
         │               │  - CopilotAdapter    │
         │               │  - GeminiAdapter     │
         │               │  - GrokAdapter       │
         │               │  - MiniMaxAdapter    │
         │               │  - DeepSeekAdapter   │
         │               └──────────────────────┘
┌────────▼──────────┐
│  AgentRunner      │    ┌──────────────────────┐
│  - conversation   │───►│  ToolRegistry        │
│    loop           │    │  - defineTool()      │
│  - tool dispatch  │    │  - 6 built-in tools  │
└───────────────────┘    └──────────────────────┘

内置工具

工具 说明
bash 跑 Shell 命令。返回 stdout + stderr。支持超时和工作目录设置。
file_read 按绝对路径读文件。支持偏移量和行数限制,能读大文件。
file_write 写入或创建文件。自动创建父目录。
file_edit 按精确字符串匹配改文件。
grep 用正则搜文件内容。优先走 ripgrep没有就 fallback 到 Node.js。
glob 按 glob 模式查找文件。返回按修改时间排序的匹配路径。

工具配置

三层叠起来用preset预设、tools白名单、disallowedTools黑名单

工具预设

三种内置 preset

const readonlyAgent: AgentConfig = {
  name: 'reader',
  model: 'claude-sonnet-4-6',
  toolPreset: 'readonly',  // file_read, grep, glob
}

const readwriteAgent: AgentConfig = {
  name: 'editor',
  model: 'claude-sonnet-4-6',
  toolPreset: 'readwrite',  // file_read, file_write, file_edit, grep, glob
}

const fullAgent: AgentConfig = {
  name: 'executor',
  model: 'claude-sonnet-4-6',
  toolPreset: 'full',  // file_read, file_write, file_edit, grep, glob, bash
}

高级过滤

const customAgent: AgentConfig = {
  name: 'custom',
  model: 'claude-sonnet-4-6',
  toolPreset: 'readwrite',        // 起点file_read, file_write, file_edit, grep, glob
  tools: ['file_read', 'grep'],   // 白名单:与预设取交集 = file_read, grep
  disallowedTools: ['grep'],      // 黑名单:再减去 = 只剩 file_read
}

解析顺序: preset → allowlist → denylist → 框架安全护栏。

自定义工具

装一个不在内置集里的工具,有两种方式。

配置时注入。 通过 AgentConfig.customTools 传入。编排层统一挂工具的时候用这个。这里定义的工具会绕过 preset 和白名单,但仍受 disallowedTools 限制。

import { defineTool } from '@jackchen_me/open-multi-agent'
import { z } from 'zod'

const weatherTool = defineTool({
  name: 'get_weather',
  description: '查询某城市当前天气。',
  schema: z.object({ city: z.string() }),
  execute: async ({ city }) => ({ content: await fetchWeather(city) }),
})

const agent: AgentConfig = {
  name: 'assistant',
  model: 'claude-sonnet-4-6',
  customTools: [weatherTool],
}

运行时注册。 agent.addTool(tool)。这种方式加的工具始终可用,不受任何过滤规则影响。

工具输出控制

工具返回太长会快速撑大对话和成本。两个开关配合着用。

截断。 把单次工具结果压成 head + tail 摘要(中间放一个标记):

const agent: AgentConfig = {
  // ...
  maxToolOutputChars: 10_000, // 该 agent 所有工具的默认上限
}

// 单工具覆盖(优先级高于 AgentConfig.maxToolOutputChars
const bigQueryTool = defineTool({
  // ...
  maxOutputChars: 50_000,
})

消费后压缩。 agent 用完某个工具结果之后,把历史副本压缩掉,后续每轮就不再重复消耗输入 token。错误结果不压缩。

const agent: AgentConfig = {
  // ...
  compressToolResults: true,                 // 默认阈值 500 字符
  // 或compressToolResults: { minChars: 2_000 }
}

MCP 工具Model Context Protocol

可以连任意 MCP 服务器,把它的工具直接给 agent 用。

import { connectMCPTools } from '@jackchen_me/open-multi-agent/mcp'

const { tools, disconnect } = await connectMCPTools({
  command: 'npx',
  args: ['-y', '@modelcontextprotocol/server-github'],
  env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN },
  namePrefix: 'github',
})

// 把每个 MCP 工具注册进你的 ToolRegistry然后在 AgentConfig.tools 里引用它们的名字
// 用完别忘了清理
await disconnect()

注意事项:

  • @modelcontextprotocol/sdk 是 optional peer dependency只在用 MCP 时才要装。
  • 当前只支持 stdio transport。
  • MCP 的入参校验交给 MCP 服务器自己(inputSchemaz.any())。

完整例子见 integrations/mcp-github

上下文管理

长时间运行的 agent 很容易撞上输入 token 上限。在 AgentConfig 里设 contextStrategy,控制对话变长时怎么收缩:

const agent: AgentConfig = {
  name: 'long-runner',
  model: 'claude-sonnet-4-6',
  // 选一种:
  contextStrategy: { type: 'sliding-window', maxTurns: 20 },
  // contextStrategy: { type: 'summarize', maxTokens: 80_000, summaryModel: 'claude-haiku-4-5' },
  // contextStrategy: { type: 'compact', maxTokens: 100_000, preserveRecentTurns: 4 },
  // contextStrategy: { type: 'custom', compress: (messages, estimatedTokens, ctx) => ... },
}
策略 什么时候用
sliding-window 最省事。只保留最近 N 轮,其余丢弃。
summarize 老对话发给摘要模型,用摘要替代原文。
compact 基于规则:截断过长的 assistant 文本块和 tool 结果,保留最近若干轮。不额外调用 LLM。
custom 传入自己的 compress(messages, estimatedTokens, ctx) 函数。

和上面的 compressToolResultsmaxToolOutputChars 搭着用效果更好。

支持的 Provider

Provider 配置 环境变量 状态
Anthropic (Claude) provider: 'anthropic' ANTHROPIC_API_KEY 已验证
OpenAI (GPT) provider: 'openai' OPENAI_API_KEY 已验证
Azure OpenAI provider: 'azure-openai' AZURE_OPENAI_API_KEY, AZURE_OPENAI_ENDPOINT(可选:AZURE_OPENAI_API_VERSIONAZURE_OPENAI_DEPLOYMENT 已验证
Grok (xAI) provider: 'grok' XAI_API_KEY 已验证
MiniMax全球 provider: 'minimax' MINIMAX_API_KEY 已验证
MiniMax国内 provider: 'minimax' + MINIMAX_BASE_URL MINIMAX_API_KEY 已验证
DeepSeek provider: 'deepseek' DEEPSEEK_API_KEY 已验证
GitHub Copilot provider: 'copilot' GITHUB_TOKEN 已验证
Gemini provider: 'gemini' GEMINI_API_KEY 已验证
Ollama / vLLM / LM Studio provider: 'openai' + baseURL 已验证
Groq provider: 'openai' + baseURL GROQ_API_KEY 已验证
llama.cpp server provider: 'openai' + baseURL 已验证

Gemini 需要 npm install @google/genaioptional peer dependency

已验证支持 tool-calling 的本地模型:Gemma 4(见 providers/gemma4-local)。

OpenAI 兼容的 API 都能用 provider: 'openai' + baseURLMistral、Qwen、Moonshot、Doubao 等。Groq 在 providers/groq 里验证过。Grok、MiniMax、DeepSeek 直接用 provider: 'grok'provider: 'minimax'provider: 'deepseek',不用配 baseURL

本地模型 Tool-Calling

Ollama、vLLM、LM Studio、llama.cpp 跑的本地模型也能 tool-calling走的是这些服务自带的 OpenAI 兼容接口。

已验证模型: Gemma 4、Llama 3.1、Qwen 3、Mistral、Phi-4。完整列表见 ollama.com/search?c=tools

兜底提取: 本地模型如果以文本形式返回工具调用,而不是 tool_calls 协议格式thinking 模型或配置不对的服务常见),框架会自动从文本里提取。

超时设置。 本地推理可能慢。在 AgentConfig 里设 timeoutMs,避免一直卡住:

const localAgent: AgentConfig = {
  name: 'local',
  model: 'llama3.1',
  provider: 'openai',
  baseURL: 'http://localhost:11434/v1',
  apiKey: 'ollama',
  tools: ['bash', 'file_read'],
  timeoutMs: 120_000, // 2 分钟后中止
}

常见问题:

  • 模型不调用工具?先确认它在 Ollama 的 Tools 分类 里,不是所有模型都支持。
  • 把 Ollama 升到最新版(ollama update),旧版本有 tool-calling bug。
  • 代理挡住了?本地服务用 no_proxy=localhost 跳过代理。

LLM 配置示例

const grokAgent: AgentConfig = {
  name: 'grok-agent',
  provider: 'grok',
  model: 'grok-4',
  systemPrompt: 'You are a helpful assistant.',
}

(设好 XAI_API_KEY 就行,不用配 baseURL。)

const minimaxAgent: AgentConfig = {
  name: 'minimax-agent',
  provider: 'minimax',
  model: 'MiniMax-M2.7',
  systemPrompt: 'You are a helpful assistant.',
}

设好 MINIMAX_API_KEY。端点用 MINIMAX_BASE_URL 选:

  • https://api.minimax.io/v1 全球端点,默认
  • https://api.minimaxi.com/v1 中国大陆端点

也可以直接在 AgentConfig 里传 baseURL,覆盖环境变量。

const deepseekAgent: AgentConfig = {
  name: 'deepseek-agent',
  provider: 'deepseek',
  model: 'deepseek-chat',
  systemPrompt: '你是一个有用的助手。',
}

设好 DEEPSEEK_API_KEY。两个模型:deepseek-chatDeepSeek-V3写代码选这个deepseek-reasoner(思考模式)。

参与贡献

Issue、feature request、PR 都欢迎。特别想要:

  • 生产级示例。 端到端跑通的真实场景工作流。收录条件和提交格式见 examples/production/README.md
  • 文档。 指南、教程、API 文档。

贡献者

Star 趋势

Star History Chart

许可证

MIT