A Complete Tutorial for Open Multi-Agent (OMA): A TypeScript Multi-Agent Orchestration Framework from Goal to Task DAG
A Complete Tutorial for Open Multi-Agent (OMA)
TL;DR: OMA is a TypeScript-native multi-Agent orchestration framework. Its core selling point is Goal-First: you give it a goal, the Coordinator Agent automatically decomposes it into a Task DAG, executes independent tasks in parallel, and finally synthesizes the result. v1.8.0 adds Checkpoint resume and Consensus verification.
Why Is OMA Worth Watching?
The Agent framework market in 2026 is already highly mature:
| Framework | Language | Stars | Core Positioning |
|---|---|---|---|
| LangGraph | Python + JS | 120K+ | Graph-First, precise control |
| CrewAI | Python | 52.8K | Role-Based, rapid prototyping |
| Mastra | TypeScript | 24.8K | Native TS, Vercel deployment |
| OMA | TypeScript | 6.4K | Goal-First, automatic DAG |
OMA's differentiation lies in its Goal-First design: you do not need to predefine nodes and edges; you only describe the goal, and the framework generates the task graph automatically.
Core Concepts
Goal-First vs Graph-First
Graph-First (LangGraph approach):
You define Node A → Node B → Node C → compile → execute
Pros: precise control, predictable
Cons: need to know all steps in advance
Goal-First (OMA approach):
You describe the goal → Coordinator automatically generates a DAG → execute in parallel → synthesize results
Pros: flexible, highly adaptable
Cons: non-deterministic (decomposition may differ each time)
Architecture Panorama
┌─────────────────────────────────────────────────────────┐
│ OpenMultiAgent │
│ │
│ ┌──────────────┐ ┌──────────────────────────────┐ │
│ │ Coordinator │────▶│ TaskQueue │ │
│ │ (Temporary Agent) │ │ - dependency graph │ │
│ │ - Decompose goals │ │ - auto unblock │ │
│ │ - Generate DAG │ │ - maxConcurrency (default: 5) │ │
│ └──────────────┘ └──────────────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────────────────────┐ │
│ │ AgentPool │ │ SharedMemory │ │
│ │ - Semaphore │ │ - Cross-Agent data sharing │ │
│ │ - Parallel execution │ │ - MemoryStore interface │ │
│ └──────────────┘ └──────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
Quick Start
Installation
npm install @open-multi-agent/core
# Or run directly with npx
npx oma run --goal "Build a REST API" --team team.json
There are only 3 runtime dependencies: anthropic-ai/sdk, openai, and zod. The entire codebase is 27 source files, readable in an afternoon.
Your First Single Agent
import { OpenMultiAgent } from '@open-multi-agent/core'
const orchestrator = new OpenMultiAgent({
defaultModel: 'deepseek-v4-flash',
defaultProvider: 'deepseek',
})
const result = await orchestrator.runAgent(
{
name: 'assistant',
systemPrompt: 'You are a helpful TypeScript expert.',
},
'Explain TypeScript generics in 3 sentences'
)
console.log(result.output)
// TypeScript generics allow you to write reusable code by parameterizing types,
// enabling functions and classes to work with any data type while maintaining
// type safety. They use angle bracket syntax (<T>) to declare type variables...
Your First Multi-Agent Team
import { OpenMultiAgent, type AgentConfig } from '@open-multi-agent/core'
const orchestrator = new OpenMultiAgent({
defaultModel: 'deepseek-v4-flash',
defaultProvider: 'deepseek',
})
// Define team members
const researcher: AgentConfig = {
name: 'researcher',
provider: 'deepseek',
model: 'deepseek-v4-pro',
systemPrompt: 'You research topics and gather concrete facts with sources.',
}
const writer: AgentConfig = {
name: 'writer',
provider: 'anthropic',
model: 'claude-sonnet-4-6',
systemPrompt: 'You turn research notes into clear, engaging prose.',
}
// Create team (enable shared memory)
const team = orchestrator.createTeam('content-team', {
name: 'content-team',
agents: [researcher, writer],
sharedMemory: true, // Key! Lets writer see researcher's findings
})
// Done in one call
const result = await orchestrator.runTeam(team, 'Write a guide on TypeScript decorators')
console.log(result.success) // true
console.log(result.totalTokenUsage) // { input_tokens: 2847, output_tokens: 1203 }
What happened?
- The Coordinator received the goal and decomposed it into 3 research tasks + 1 writing task
- The 3 research tasks executed in parallel (no dependencies)
- The writing task waited for all research to finish before starting
- The Coordinator finally synthesized the final answer
Three Run Modes
Mode 1: runAgent(), Single Agent
The simplest entry point. One Agent, one prompt.
const result = await orchestrator.runAgent(agent, 'Your prompt here')
Mode 2: runTeam(), Automatic Orchestration
Give it a goal, and the framework plans automatically.
const result = await orchestrator.runTeam(team, 'Build a REST API with auth')
Note: the Coordinator is an LLM, so the decomposition may differ each time. If you need determinism, use runTasks().
Mode 3: runTasks(), Explicit Pipeline
You define the task graph yourself, fully controllable.
const result = await orchestrator.runTasks(team, [
{
title: 'Design schema',
description: 'Design the database schema for a blog.',
assignee: 'architect',
},
{
title: 'Implement API',
description: 'Build REST endpoints based on the schema.',
assignee: 'developer',
dependsOn: ['Design schema'], // wait for schema to complete
},
{
title: 'Write tests',
description: 'Write unit tests for all endpoints.',
assignee: 'tester',
dependsOn: ['Implement API'],
},
])
Provider Support (10+ Built-In)
OMA supports mixing different providers within the same team:
const team = orchestrator.createTeam('mixed-team', {
name: 'mixed-team',
agents: [
// Anthropic Claude
{ name: 'architect', provider: 'anthropic', model: 'claude-opus-4-7',
systemPrompt: 'You design systems.' },
// OpenAI GPT
{ name: 'developer', provider: 'openai', model: 'gpt-4o',
systemPrompt: 'You write code.' },
// DeepSeek (cheap and easy to use)
{ name: 'reviewer', provider: 'deepseek', model: 'deepseek-v4-flash',
systemPrompt: 'You review code.' },
// MiniMax (domestic pride)
{ name: 'documenter', provider: 'minimax', model: 'MiniMax-M3',
systemPrompt: 'You write docs.' },
// Local model (Ollama)
{ name: 'helper', provider: 'openai', model: 'llama3',
baseURL: 'http://localhost:11434/v1',
apiKey: 'ollama',
systemPrompt: 'You help with tasks.' },
],
sharedMemory: true,
})
Full Provider List
| Provider | Config | Default Model | Notes |
|---|---|---|---|
| Anthropic | provider: 'anthropic' | claude-sonnet-4-6 | Strongest reasoning |
| OpenAI | provider: 'openai' | gpt-4o | General purpose |
| DeepSeek | provider: 'deepseek' | deepseek-v4-flash | King of cost-performance |
| MiniMax | provider: 'minimax' | MiniMax-M3 | Top domestic choice |
| Gemini | provider: 'gemini' | gemini-2.5-pro | Google ecosystem |
| Grok | provider: 'grok' | grok-3 | xAI |
| Bedrock | provider: 'bedrock' | - | AWS enterprise-grade |
| Azure | provider: 'azure-openai' | - | Microsoft cloud |
| Copilot | provider: 'copilot' | - | GitHub |
| Ollama | provider: 'openai' + baseURL | Custom | Free and local |
Deep Dive into v1.8.0's New Features
1. Checkpoint & Resume
Long-running tasks can recover after a crash:
import { OpenMultiAgent, InMemoryStore } from '@open-multi-agent/core'
// Method 1: shorthand (using team's sharedMemoryStore)
const result = await orchestrator.runTeam(team, goal, {
checkpoint: true,
})
// Method 2: specify an independent store
const result = await orchestrator.runTeam(team, goal, {
checkpoint: {
enabled: true,
runId: 'production-run-001', // must be provided
store: new RedisStore(), // Redis / Postgres / custom
},
})
// Recovery after crash
const restored = await orchestrator.restore({
team,
runId: 'production-run-001',
})
// Completed task will be skipped, only the remaining part will be executed
Technical details:
- Based on the
MemoryStoreinterface, sharing the same storage layer as SharedMemory - Each completed task writes a snapshot (JSON format)
- On resume, the Coordinator synthesis runs again
- Task-level granularity recovery (an interrupted task restarts from the beginning, not mid-task)
Limitations:
- Snapshot-based, not event-sourced (each snapshot overwrites the previous one)
- If the checkpoint store and the sharedMemory store are the same, serialization is not duplicated (avoiding O(N²) writes)
2. Consensus Verification
A multi-Judge consensus verification mechanism that guards against a single Agent's errors:
const result = await orchestrator.runTeam(team, goal, {
verifyJudges: [
{
name: 'critic-1',
provider: 'anthropic',
model: 'claude-opus-4-7',
systemPrompt: 'You are a strict code reviewer. Find bugs and security issues.',
},
{
name: 'critic-2',
provider: 'openai',
model: 'gpt-4o',
systemPrompt: 'You verify factual accuracy and completeness.',
},
],
})
Workflow:
- The Proposer Agent generates an answer
- The Judge Agents try to refute it
- If quorum is reached (majority agreement) → it passes
- If not → changes are required and verification repeats
3. CLI Dashboard
npx oma run --goal "Build a REST API" --team team.json --dashboard
Generates a static HTML page showing:
- The Task DAG visualization
- The execution time of each task
- Token usage
- The Agent assignment
CLI Usage (the oma binary)
OMA's CLI is designed JSON-first, suited to CI/CD integration:
# Installation
npm install -g @open-multi-agent/core
# Run
npx oma run --goal "Your goal" --team team.json
# Output to file
npx oma run --goal "..." --team team.json > result.json
# Pretty output
npx oma run --goal "..." --team team.json --pretty
# Include full message history
npx oma run --goal "..." --team team.json --include-messages
Team JSON Format
{
"name": "my-team",
"agents": [
{
"name": "researcher",
"provider": "deepseek",
"model": "deepseek-v4-pro",
"systemPrompt": "You research topics thoroughly."
},
{
"name": "writer",
"provider": "anthropic",
"model": "claude-sonnet-4-6",
"systemPrompt": "You write clear, engaging content."
}
],
"sharedMemory": true
}
Exit Codes
| Code | Meaning | CI/CD Handling |
|---|---|---|
| 0 | Success | Continue |
| 1 | Run completed but failed | Check result.json |
| 2 | Input/file error | Fix the configuration |
| 3 | Crash or API error | Retry or alert |
GitHub Actions Integration
name: AI Code Review
on: [pull_request]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install @open-multi-agent/core
- run: |
npx oma run \
--goal "Review the code changes in this PR for bugs, security issues, and style violations" \
--team review-team.json \
--pretty > review-result.json
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
- run: |
cat review-result.json | jq '.agentResults.coordinator.output'
Field Examples
Example 1: Contract Review DAG
import { OpenMultiAgent, type TaskConfig } from '@open-multi-agent/core'
const orchestrator = new OpenMultiAgent({
defaultModel: 'claude-sonnet-4-6',
defaultProvider: 'anthropic',
})
const team = orchestrator.createTeam('contract-review', {
name: 'contract-review',
agents: [
{ name: 'extractor', systemPrompt: 'Extract clauses from contracts.' },
{ name: 'compliance', systemPrompt: 'Check regulatory compliance.' },
{ name: 'summarizer', systemPrompt: 'Generate executive summaries.' },
{ name: 'notifier', systemPrompt: 'Generate final reports.' },
],
sharedMemory: true,
})
const tasks: TaskConfig[] = [
{
title: 'extract-clauses',
description: 'Extract all clauses from the contract into structured JSON.',
assignee: 'extractor',
},
{
title: 'compliance-check',
description: 'Check each clause for regulatory compliance.',
assignee: 'compliance',
dependsOn: ['extract-clauses'],
maxRetries: 2,
retryDelayMs: 500,
retryBackoff: 2, // exponential backoff
},
{
title: 'summary',
description: 'Generate executive summary.',
assignee: 'summarizer',
dependsOn: ['extract-clauses'],
},
{
title: 'final-report',
description: 'Compile all analysis into a Markdown report.',
assignee: 'notifier',
dependsOn: ['compliance-check', 'summary'],
},
]
const result = await orchestrator.runTasks(team, tasks)
// Task 2 (compliance) and Task 3 (summary) will run in parallel!
Example 2: Incident Postmortem
const team = orchestrator.createTeam('sre-team', {
name: 'sre-team',
agents: [
{ name: 'log-analyzer', systemPrompt: 'Analyze log patterns.' },
{ name: 'deploy-checker', systemPrompt: 'Check recent deployments.' },
{ name: 'impact-assessor', systemPrompt: 'Assess user impact.' },
{ name: 'hypothesizer', systemPrompt: 'Form root cause hypotheses.' },
{ name: 'writer', systemPrompt: 'Write postmortem documents.' },
],
sharedMemory: true,
})
const result = await orchestrator.runTeam(team, `
Analyze the incident logs from 2026-06-25 14:00-14:30 UTC.
Correlate with recent deployments and produce a postmortem.
`)
// Coordinator automatically generates a DAG of 5 tasks
// The first 3 run in parallel → hypothesizer waits → writer last
Example 3: Cost-Tiered Pipeline
// Cheap models handle classification, expensive models handle creative work
const team = orchestrator.createTeam('cost-optimized', {
name: 'cost-optimized',
agents: [
{ name: 'classifier', provider: 'openai', model: 'gpt-4o-mini',
systemPrompt: 'Classify support tickets by urgency.' },
{ name: 'responder', provider: 'anthropic', model: 'claude-opus-4-7',
systemPrompt: 'Draft detailed responses for urgent tickets.' },
{ name: 'qa', provider: 'deepseek', model: 'deepseek-v4-flash',
systemPrompt: 'Review responses for accuracy.' },
],
})
// Cost per 100 runs drops from $450 (all Opus) to ~$57
A Deep Dive into SharedMemory
SharedMemory is the core mechanism for communication between Agents:
// Method 1: In-memory storage (default)
const team = orchestrator.createTeam('team', {
name: 'team',
agents: [agent1, agent2],
sharedMemory: true, // Use InMemoryStore
})
// Method 2: Persistent storage (Redis)
class RedisStore implements MemoryStore {
async get(key: string): Promise<string | null> { /* ... */ }
async set(key: string, value: string): Promise<void> { /* ... */ }
async list(prefix: string): Promise<string[]> { /* ... */ }
async delete(key: string): Promise<void> { /* ... */ }
async clear(): Promise<void> { /* ... */ }
}
const team = orchestrator.createTeam('durable-team', {
name: 'durable-team',
agents: [agent1, agent2],
sharedMemoryStore: new RedisStore(), // Takes precedence over sharedMemory: true
})
How it works:
- After each task completes, its result is written to SharedMemory
- The prompt of a downstream task automatically includes the upstream results
- Key format:
<teamId>/<key>, with namespace isolation
Production Checklist
Before deploying OMA to production, confirm the following configuration:
| Concern | Config Item | Location |
|---|---|---|
| Limit conversation length | maxTurns + contextStrategy | AgentConfig |
| Limit tool output | maxToolOutputChars | AgentConfig |
| Failure retry | maxRetries, retryDelayMs, retryBackoff | TaskConfig |
| Budget control | maxTokenBudget | OrchestratorConfig |
| Loop detection | loopDetection + onLoopDetected | OrchestratorConfig |
| Trace and audit | onTrace | OrchestratorConfig |
| Checkpoint resume | checkpoint: true | RunTeamOptions |
Comparison with Loop Engineering
As OpenClaw users, we built our own Loop Engineering system. Here is a comparison of the two:
| Dimension | OMA | Loop Engineering |
|---|---|---|
| Task decomposition | Automatic DAG (LLM-driven) | Seven-phase enforced engine |
| Verification mechanism | Consensus (LLM Judge) | External Supervisor |
| Permission control | None | Permission Matrix |
| Crash recovery | ✅ Checkpoint | ❌ None |
| Shared memory | ✅ MemoryStore | ❌ Agent isolation |
| CLI | oma binary | loop_engine.py |
| Language | TypeScript | Python |
| Ecosystem | npm | OpenClaw |
Conclusion: OMA's Checkpoint and Consensus designs are worth borrowing, but Loop Engineering's External Supervisor is stronger in verification reliability.
Summary
| Feature | Rating |
|---|---|
| Design philosophy | ⭐⭐⭐⭐⭐ Goal-First is very elegant |
| Code quality | ⭐⭐⭐⭐⭐ 27 files, extremely readable |
| Provider support | ⭐⭐⭐⭐⭐ 10+ built-in, usable in combination |
| Production readiness | ⭐⭐⭐⭐ Checkpoint + Retry + Loop Detection |
| Community ecosystem | ⭐⭐⭐ 6.4K stars, growing |
| Documentation quality | ⭐⭐⭐⭐ Complete examples + official docs |
Who is it for?
- TypeScript backends that need multi-Agent orchestration
- Those who do not want to predefine all steps
- Those who need to mix multiple LLM providers
- Those who need CLI/CI integration
Who is it not for?
- Those who need precise control over every step (use LangGraph)
- The Python ecosystem (use CrewAI)
- Those who need full enterprise-grade governance (use LangGraph + LangSmith)
Reference Links
- GitHub: open-multi-agent/open-multi-agent
- Official site: open-multi-agent.com
- npm: @open-multi-agent/core
- CLI docs: docs/cli.md
- Checkpoint docs: docs/checkpoint.md
- Provider setup: docs/providers.md
More in Evidence
- A Reality Check on Decision Models: Why They Seem Miraculous Online but We Measured Only 54%: A Full Comparison of JEV / LAYA / KEV / CLM-8B and a Deployment Formula
- The "Non-Text-Generating Model": Jev and the New System One Category, and How Agent Architecture Changes When AI Only Answers Multiple Choice
- WeChat Open Source WeMM-Embedding Deep Dive: The Multimodal Embedding Model Topping MMEB-v2, Can It Run on Your Mac?
- A Source-Level Architectural Dissection of DeepSeek Harness: How an Everything-Is-a-Plugin Agent Framework Is Built