OMA owns the workflow
The coordinator decomposes the goal, assigns the external member a task, schedules dependencies, shares upstream results, and cascades failure to dependent tasks.
Use ACP or a local process as one team member, while OMA keeps ownership of planning, scheduling, shared memory, and failure propagation.
import path from 'node:path'
import { OpenMultiAgent } from '@open-multi-agent/core'
// npm install @open-multi-agent/core@^1.11.0 @agentclientprotocol/sdk
// Set ANTHROPIC_API_KEY. Keep this directory narrower than your repository root.
const projectDir = path.resolve(
process.env.OMA_ACP_PROJECT_DIR ?? './scratch-project',
)
const oma = new OpenMultiAgent({
defaultProvider: 'anthropic',
defaultModel: 'claude-sonnet-4-6',
})
const team = oma.createTeam('hybrid-audit', {
name: 'hybrid-audit',
agents: [
{
name: 'planner',
systemPrompt: 'Plan a focused repository audit. Do not edit files.',
},
{
name: 'repo-auditor',
systemPrompt: 'Inspect the project and report evidence. Do not edit files.',
backend: {
kind: 'acp',
command: 'npx',
args: ['-y', '@agentclientprotocol/claude-agent-acp'],
cwd: projectDir,
// OMA defaults to 'auto-approve'. This example starts read-only instead.
permission: ({ kind }) => kind === 'read',
},
},
{
name: 'reviewer',
systemPrompt: 'Challenge the audit findings and summarize residual risk.',
},
],
sharedMemory: true,
})
const result = await oma.runTeam(
team,
'Audit the authentication module for error-handling gaps, then review the evidence.',
)
console.log(result.success, result.totalTokenUsage) Set AgentConfig.backend instead of a model for the external member. kind: 'acp' starts a long-lived Agent Client Protocol session; kind: 'process' starts a generic command for each run and maps stdout, stderr, exit status, and cancellation into a normal agent result. ACP is an optional peer loaded only when used. OMA is the ACP client: it launches the configured subprocess, sends prompts, receives tool and usage updates, and folds the result into the same task DAG and shared memory as its LLM-backed agents. Claude Code does not speak ACP natively; the example uses the official @agentclientprotocol/claude-agent-acp adapter.
OMA coordinates the run; the external agent remains an independent runtime with its own tools and context.
The coordinator decomposes the goal, assigns the external member a task, schedules dependencies, shares upstream results, and cascades failure to dependent tasks.
Its CLI chooses tools, maintains its own session context, and performs work with the local process permissions you launched it with. OMA does not replace that runtime.
Text deltas, tool-call updates, stop reasons, cancellation, and reported usage become a normal OMA result, so hybrid teams do not need a separate scheduler.
Treat an ACP backend as a local subprocess you are deliberately authorizing—not as an isolated OMA tool.
permission defaults to 'auto-approve', preferring one-time approval when the agent offers it. Use 'reject' or a callback for each deployment; the read-only callback above is a starting policy, not a universal one.
The subprocess accesses cwd directly; OMA does not proxy ACP file operations through its filesystem sandbox. Scope cwd, command, args, and inherited environment to the minimum needed. The process backend has no protocol permission prompts.
ACP reports cumulative context tokens, not an input/output split. OMA converts readings into per-turn increments for maxTokenBudget; an agent that sends no usage update reports zero and is not token-gated. ACP cost is not wired into maxCostBudget.
OMA is client-only; it does not expose OMA agents to editors as ACP agents. Orchestrated ACP subprocesses live until process exit; use createAcpBackend() with dispose() when explicit teardown is required.
open-multi-agent is MIT-licensed and free to run yourself. When you need it delivered, integrated, or supported on a deadline, 元定义科技 (YuanASI) offers commercial delivery and support.