// TypeScript multi-agent orchestration

From a goal to a task DAG, automatically.

3 runtime deps·any model·runs anywhere
Quick Start
input · team.tsgoal
runTeam()
const team = oma.createTeam('api-team', { agents })
 
// one call: goal → task DAG → result
const result = await oma.runTeam(
team,
"Build a REST API for a todo list: design the data model and routes, implement the CRUD endpoints, generate a test suite, and review it for security.",
)
decomposes into
#91d351c7
Design data model and API routes
STATUS: DONE (5.6s)
architect stable
#8400663f
Implement CRUD endpoints
STATUS: DONE (17.8s)
developer stable
parallel
#a62da761
Generate test suite for CRUD endpoints
STATUS: DONE (19.1s)
developer stable
#32347388
Perform security review of implementation
STATUS: DONE (19.7s)
reviewer stable
real runTeam() · deepseek-v4-flash · 4 tasks · 72s
01 How it works

An agent runtime, not a graph builder.

Goal-first, not graph-first. You describe the outcome; OMA owns the decomposition, the parallelism, and the synthesis.

01Goal-driven coordinator

You pass a goal, not a graph. A coordinator agent decomposes it into a task DAG, parallelizes independent nodes, and synthesizes the result.

02Mix any model in one team

Each agent names its own model — Anthropic, OpenAI, a local Ollama, or a self-hosted endpoint — and they cooperate inside a single team.

03Tools and MCP, default-deny

An agent gets only the tools it lists. Connect Model Context Protocol servers to expose external systems under the same opt-in contract.

04Streaming and structured output

Stream tokens and node-state transitions as the DAG fills, or await a typed, schema-validated object at the end of the run.

05Cross-provider reasoning

One thinking config maps to Anthropic thinking, Gemini thinkingConfig, and OpenAI reasoning_effort — reasoning streams as events, with opt-in preservation across a provider switch.

team.ts
import { OpenMultiAgent, type AgentConfig } from '@open-multi-agent/core'
 
const agents: AgentConfig[] = [
{ name: 'architect', model: 'claude-sonnet-4-6', tools: ['file_write'] },
{ name: 'developer', model: 'claude-sonnet-4-6', tools: ['bash', 'file_read', 'file_write', 'file_edit'] },
{ name: 'reviewer', model: 'claude-sonnet-4-6', tools: ['file_read', 'grep'] },
]
 
const oma = new OpenMultiAgent({ defaultModel: 'claude-sonnet-4-6' })
const team = oma.createTeam('api-team', { name: 'api-team', agents })
 
// coordinator plans the DAG, runs independents in parallel, synthesizes
const result = await oma.runTeam(team, 'Create a REST API for a todo list')
One call
runTeam() returns when the whole DAG resolves — no manual node wiring, no scheduler to maintain.
02 Reliability

Built to run in production.

Handing real work to autonomous agents raises three fair questions: do they run off the rails, burn the budget, or fail where you can't see it? Each one has an answer in the API.

won't run away
You stay in the loop

Inspect the plan before any agent runs with onPlanReady, then approve each round with onApproval. A proposer→judge pass (runConsensus) has one agent check another's output, and loop detection halts an agent that starts repeating itself.

won't burn the budget
Spend where it counts

Route planning to a flagship model and the leaf tasks to cheap ones with modelRouting. maxTokenBudget caps a run's spend — cross it and the orchestrator stops issuing calls instead of running up the bill.

debug any run
Inspect, replay, resume

Stream every LLM and tool call to your tracing stack with onTrace, or open a self-contained HTML dashboard after the run (oma run --dashboard). Checkpoints resume a crashed run from its last completed task, and secrets are redacted from traces and dashboards on a best-effort basis.

Post-run dashboard replaying a completed team run: the task DAG with per-node assignee, status, token breakdown, and the agent output log.
And when something does slip, every run can render an auditable dashboard — the task DAG, per-node assignee and status, token breakdown, and the agent output log. Observability
04 Integrations

Works with your stack.

OMA composes with the providers, protocols, and servers already in your backend — no platform to migrate to.

Providers
Anthropic, Gemini, OpenAI, Bedrock, Azure, DeepSeek — or any OpenAI-compatible endpoint
13 built-in
MCP
Connect Model Context Protocol servers as tools
native
Vercel AI SDK
Bridge to 60+ AI SDK providers and hosts
compatible
Express
Mount runTeam() behind a route handler
drop-in
Any Node.js
No daemon, no sidecar — three runtime deps
Node 18+
06 FAQ

Mechanism, not marketing.

How the runtime actually behaves. The full reference lives in the docs.

A coordinator agent plans the work: it breaks the goal into discrete tasks, infers dependencies between them, and emits a directed acyclic graph. Independent nodes run concurrently; dependent nodes wait on their inputs. Pass planOnly to inspect the DAG before any agent executes.
Yes. Each agent declares its own model, so a single team can mix a frontier cloud model, a self-hosted endpoint, and a local Ollama instance. The coordinator routes each task to the agent — and therefore the model — assigned to it.
Default-deny. An agent only has the tools it explicitly lists in its tools array; everything else is unavailable. External systems are connected through MCP servers under the same opt-in contract.
A failed node is retried under its policy; persistent failures surface on the node with FAILED state and an error, and downstream dependents are held. The rest of the DAG keeps running, so one failure does not abort the whole run.
Layered controls, all opt-in. onPlanReady hands you the decomposed plan to inspect before any agent runs, and onApproval gates each round; return false and the remaining tasks are skipped. runConsensus adds a proposer→judge check that a second agent must accept, and loop detection halts an agent that keeps repeating the same tool call or output.
Two levers. modelRouting sends planning and synthesis to a flagship model while leaf tasks run on a cheaper one, so you pay frontier rates only where they matter. maxTokenBudget is a hard ceiling on cumulative tokens: cross it and the orchestrator stops issuing calls and skips the remaining tasks instead of running up the bill.
Both. You can stream tokens and node-state transitions as the DAG fills, or simply await runTeam() for a typed, schema-validated result object once the graph resolves.
view all questions
// get started

Start with one goal.
Let the team figure out the work.

Quick Start