Go to file
JackChen 9f9f4e95d4 docs: highlight auto task decomposition, add run modes table, move contributors up
- Rewrite headline to emphasize automatic goal-to-task decomposition
- Add "Auto Task Decomposition" as first item in Why section
- Add "Three Ways to Run" table (runAgent / runTeam / runTasks)
- Move Contributors section higher for visibility
- Bust star-history cache to refresh chart
2026-04-02 21:55:04 +08:00
examples feat: add GitHub Copilot as LLM provider 2026-04-02 01:45:43 +02:00
src feat: add baseURL and apiKey support for OpenAI-compatible APIs 2026-04-02 19:33:10 +08:00
.gitignore Bust GitHub cache for star history chart, ignore non-tech dirs 2026-04-02 00:56:15 +08:00
LICENSE Initial release: open-multi-agent v0.1.0 2026-04-01 04:33:15 +08:00
README.md docs: highlight auto task decomposition, add run modes table, move contributors up 2026-04-02 21:55:04 +08:00
README_zh.md docs: highlight auto task decomposition, add run modes table, move contributors up 2026-04-02 21:55:04 +08:00
package-lock.json Initial release: open-multi-agent v0.1.0 2026-04-01 04:33:15 +08:00
package.json Publish to npm as @jackchen_me/open-multi-agent 2026-04-01 13:44:23 +08:00
tsconfig.json Initial release: open-multi-agent v0.1.0 2026-04-01 04:33:15 +08:00

README.md

Open Multi-Agent

Build AI agent teams that decompose goals into tasks automatically. Define agents with roles and tools, describe a goal — the framework plans the task graph, schedules dependencies, and runs everything in parallel.

GitHub stars license TypeScript

English | 中文

Why Open Multi-Agent?

  • Auto Task Decomposition — Describe a goal in plain text. A built-in coordinator agent breaks it into a task DAG with dependencies and assignees — no manual orchestration needed.
  • Multi-Agent Teams — Define agents with different roles, tools, and even different models. They collaborate through a message bus and shared memory.
  • Task DAG Scheduling — Tasks have dependencies. The framework resolves them topologically — dependent tasks wait, independent tasks run in parallel.
  • Model Agnostic — Claude, GPT, and local models (Ollama, vLLM, LM Studio) in the same team. Swap models per agent via baseURL.
  • In-Process Execution — No subprocess overhead. Everything runs in one Node.js process. Deploy to serverless, Docker, CI/CD.

Quick Start

npm install @jackchen_me/open-multi-agent

Set ANTHROPIC_API_KEY (and optionally OPENAI_API_KEY or GITHUB_TOKEN for Copilot) in your environment.

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

const orchestrator = new OpenMultiAgent({ defaultModel: 'claude-sonnet-4-6' })

// One agent, one task
const result = await orchestrator.runAgent(
  {
    name: 'coder',
    model: 'claude-sonnet-4-6',
    tools: ['bash', 'file_write'],
  },
  'Write a TypeScript function that reverses a string, save it to /tmp/reverse.ts, and run it.',
)

console.log(result.output)

Multi-Agent Team

This is where it gets interesting. Three agents, one goal:

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 = {
  name: 'developer',
  model: 'claude-sonnet-4-6',
  systemPrompt: 'You implement what the architect designs.',
  tools: ['bash', 'file_read', 'file_write', 'file_edit'],
}

const reviewer: AgentConfig = {
  name: 'reviewer',
  model: 'claude-sonnet-4-6',
  systemPrompt: 'You review code for correctness and clarity.',
  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,
})

// Describe a goal — the framework breaks it into tasks and orchestrates execution
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`)

Three Ways to Run

Mode Method When to use
Single agent runAgent() One agent, one prompt — simplest entry point
Auto-orchestrated team runTeam() Give a goal, framework plans and executes
Explicit pipeline runTasks() You define the task graph and assignments

Contributors

More Examples

Task Pipeline — explicit control over task graph and assignments
const result = await orchestrator.runTasks(team, [
  {
    title: 'Design the data model',
    description: 'Write a TypeScript interface spec to /tmp/spec.md',
    assignee: 'architect',
  },
  {
    title: 'Implement the module',
    description: 'Read /tmp/spec.md and implement the module in /tmp/src/',
    assignee: 'developer',
    dependsOn: ['Design the data model'], // blocked until design completes
  },
  {
    title: 'Write tests',
    description: 'Read the implementation and write Vitest tests.',
    assignee: 'developer',
    dependsOn: ['Implement the module'],
  },
  {
    title: 'Review code',
    description: 'Review /tmp/src/ and produce a structured code review.',
    assignee: 'reviewer',
    dependsOn: ['Implement the module'], // can run in parallel with tests
  },
])
Custom Tools — define tools with Zod schemas
import { z } from 'zod'
import { defineTool, Agent, ToolRegistry, ToolExecutor, registerBuiltInTools } from '@jackchen_me/open-multi-agent'

const searchTool = defineTool({
  name: 'web_search',
  description: 'Search the web and return the top results.',
  inputSchema: z.object({
    query: z.string().describe('The search query.'),
    maxResults: z.number().optional().describe('Number of results (default 5).'),
  }),
  execute: async ({ query, maxResults = 5 }) => {
    const results = await mySearchProvider(query, maxResults)
    return { data: JSON.stringify(results), isError: false }
  },
})

const registry = new ToolRegistry()
registerBuiltInTools(registry)
registry.register(searchTool)

const executor = new ToolExecutor(registry)
const agent = new Agent(
  { name: 'researcher', model: 'claude-sonnet-4-6', tools: ['web_search'] },
  registry,
  executor,
)

const result = await agent.run('Find the three most recent TypeScript releases.')
Multi-Model Teams — mix Claude, GPT, and local models in one workflow
const claudeAgent: AgentConfig = {
  name: 'strategist',
  model: 'claude-opus-4-6',
  provider: 'anthropic',
  systemPrompt: 'You plan high-level approaches.',
  tools: ['file_write'],
}

const gptAgent: AgentConfig = {
  name: 'implementer',
  model: 'gpt-5.4',
  provider: 'openai',
  systemPrompt: 'You implement plans as working code.',
  tools: ['bash', 'file_read', 'file_write'],
}

// Any OpenAI-compatible API — Ollama, vLLM, LM Studio, etc.
const localAgent: AgentConfig = {
  name: 'reviewer',
  model: 'llama3.1',
  provider: 'openai',
  baseURL: 'http://localhost:11434/v1',
  apiKey: 'ollama',
  systemPrompt: 'You review code for correctness and clarity.',
  tools: ['file_read', 'grep'],
}

const team = orchestrator.createTeam('mixed-team', {
  name: 'mixed-team',
  agents: [claudeAgent, gptAgent, localAgent],
  sharedMemory: true,
})

const result = await orchestrator.runTeam(team, 'Build a CLI tool that converts JSON to CSV.')
Streaming Output
import { Agent, ToolRegistry, ToolExecutor, registerBuiltInTools } from '@jackchen_me/open-multi-agent'

const registry = new ToolRegistry()
registerBuiltInTools(registry)
const executor = new ToolExecutor(registry)

const agent = new Agent(
  { name: 'writer', model: 'claude-sonnet-4-6', maxTurns: 3 },
  registry,
  executor,
)

for await (const event of agent.stream('Explain monads in two sentences.')) {
  if (event.type === 'text' && typeof event.data === 'string') {
    process.stdout.write(event.data)
  }
}

Architecture

┌─────────────────────────────────────────────────────────────────┐
│  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    │
         │               └──────────────────────┘
┌────────▼──────────┐
│  AgentRunner      │    ┌──────────────────────┐
│  - conversation   │───►│  ToolRegistry        │
│    loop           │    │  - defineTool()      │
│  - tool dispatch  │    │  - 5 built-in tools  │
└───────────────────┘    └──────────────────────┘

Built-in Tools

Tool Description
bash Execute shell commands. Returns stdout + stderr. Supports timeout and cwd.
file_read Read file contents at an absolute path. Supports offset/limit for large files.
file_write Write or create a file. Auto-creates parent directories.
file_edit Edit a file by replacing an exact string match.
grep Search file contents with regex. Uses ripgrep when available, falls back to Node.js.

Contributing

Issues, feature requests, and PRs are welcome. Some areas where contributions would be especially valuable:

  • LLM Adapters — Anthropic, OpenAI, and Copilot are supported out of the box. Any OpenAI-compatible API (Ollama, vLLM, LM Studio, etc.) works via baseURL. Additional adapters for Gemini and other providers are welcome. The LLMAdapter interface requires just two methods: chat() and stream().
  • Examples — Real-world workflows and use cases.
  • Documentation — Guides, tutorials, and API docs.

Star History

Star History Chart

License

MIT