← All examples
// Start Here

Multi-Agent Team Collaboration

Three specialised agents (architect, developer, reviewer) collaborate on a shared goal. The OpenMultiAgent orchestrator breaks the goal into tasks, assigns them to the right agents, and collects the results.

Enterprise support
01 Run it
OMA APIsOpenMultiAgent
Start Here177 lines

From a clone of the repo — this exact file:

terminal
npx tsx packages/core/examples/basics/team-collaboration.ts
Prerequisites
  • OPENAI_API_KEY env var must be set. Works with any OpenAI-compatible
  • provider: set OPENAI_BASE_URL + OMA_MODEL for Groq, DeepSeek, Ollama, etc.
Open the complete, synchronized source · 177 lines

The complete example, synchronized from the pinned Framework commit.

basics/team-collaboration.ts
/**
* Multi-Agent Team Collaboration
*
* Three specialised agents (architect, developer, reviewer) collaborate on a
* shared goal. The OpenMultiAgent orchestrator breaks the goal into tasks, assigns
* them to the right agents, and collects the results.
*
* Run:
* npx tsx packages/core/examples/basics/team-collaboration.ts
*
* Prerequisites:
* OPENAI_API_KEY env var must be set. Works with any OpenAI-compatible
* provider: set OPENAI_BASE_URL + OMA_MODEL for Groq, DeepSeek, Ollama, etc.
*/
 
import { join } from 'node:path'
import { OpenMultiAgent } from '../../src/index.js'
import type { AgentConfig, OrchestratorEvent } from '../../src/types.js'
 
// Works with any OpenAI-compatible provider. Set OPENAI_API_KEY for OpenAI, or
// OPENAI_BASE_URL + OMA_MODEL for Groq, DeepSeek, Ollama, etc.
const model = process.env.OMA_MODEL ?? 'gpt-5.4'
 
// Built-in filesystem tools are sandboxed to `<cwd>/.agent-workspace` by
// default; the generated API lives under that root so the demo runs
// without disabling the sandbox.
const OUTPUT_DIR = join(process.cwd(), '.agent-workspace', 'express-api')
 
// ---------------------------------------------------------------------------
// Agent definitions
// ---------------------------------------------------------------------------
 
const architect: AgentConfig = {
name: 'architect',
model,
systemPrompt: `You are a software architect with deep experience in Node.js and REST API design.
Your job is to design clear, production-quality API contracts and file/directory structures.
Output concise plans in markdown — no unnecessary prose.`,
tools: ['bash', 'file_write'],
maxTurns: 5,
temperature: 0.2,
}
 
const developer: AgentConfig = {
name: 'developer',
model,
systemPrompt: `You are a TypeScript/Node.js developer. You implement what the architect specifies.
Write clean, runnable code with proper error handling. Use the tools to write files and run tests.`,
tools: ['bash', 'file_read', 'file_write', 'file_edit'],
maxTurns: 12,
temperature: 0.1,
}
 
const reviewer: AgentConfig = {
name: 'reviewer',
model,
systemPrompt: `You are a senior code reviewer. Review code for correctness, security, and clarity.
Provide a structured review with: LGTM items, suggestions, and any blocking issues.
Read files using the tools before reviewing.`,
tools: ['bash', 'file_read', 'grep'],
maxTurns: 5,
temperature: 0.3,
}
 
// ---------------------------------------------------------------------------
// Progress tracking
// ---------------------------------------------------------------------------
 
const startTimes = new Map<string, number>()
 
function handleProgress(event: OrchestratorEvent): void {
const ts = new Date().toISOString().slice(11, 23) // HH:MM:SS.mmm
 
switch (event.type) {
case 'agent_start':
startTimes.set(event.agent ?? '', Date.now())
console.log(`[${ts}] AGENT START → ${event.agent}`)
break
 
case 'agent_complete': {
const elapsed = Date.now() - (startTimes.get(event.agent ?? '') ?? Date.now())
console.log(`[${ts}] AGENT DONE ← ${event.agent} (${elapsed}ms)`)
break
}
 
case 'task_start':
console.log(`[${ts}] TASK START ↓ ${event.task}`)
break
 
case 'task_complete':
console.log(`[${ts}] TASK DONE ↑ ${event.task}`)
break
 
case 'message':
console.log(`[${ts}] MESSAGE • ${event.agent} → (team)`)
break
 
case 'error':
console.error(`[${ts}] ERROR ✗ agent=${event.agent} task=${event.task}`)
if (event.data instanceof Error) {
console.error(` ${event.data.message}`)
}
break
}
}
 
// ---------------------------------------------------------------------------
// Orchestrate
// ---------------------------------------------------------------------------
 
const orchestrator = new OpenMultiAgent({
defaultProvider: 'openai',
defaultModel: model,
defaultBaseURL: process.env.OPENAI_BASE_URL, // unset = OpenAI
maxConcurrency: 1, // run agents sequentially so output is readable
onProgress: handleProgress,
})
 
const team = orchestrator.createTeam('api-team', {
name: 'api-team',
agents: [architect, developer, reviewer],
sharedMemory: true,
maxConcurrency: 1,
})
 
console.log(`Team "${team.name}" created with agents: ${team.getAgents().map(a => a.name).join(', ')}`)
console.log('\nStarting team run...\n')
console.log('='.repeat(60))
 
const goal = `Create a minimal Express.js REST API in ${OUTPUT_DIR}/ with:
- GET /health → { status: "ok" }
- GET /users → returns a hardcoded array of 2 user objects
- POST /users → accepts { name, email } body, logs it, returns 201
- Proper error handling middleware
- The server should listen on port 3001
- Include a package.json with the required dependencies`
 
const result = await orchestrator.runTeam(team, goal)
 
console.log('\n' + '='.repeat(60))
 
// ---------------------------------------------------------------------------
// Results
// ---------------------------------------------------------------------------
 
console.log('\nTeam run complete.')
console.log(`Success: ${result.success}`)
console.log(`Total tokens — input: ${result.totalTokenUsage.input_tokens}, output: ${result.totalTokenUsage.output_tokens}`)
 
console.log('\nPer-agent results:')
for (const [agentName, agentResult] of result.agentResults) {
const status = agentResult.success ? 'OK' : 'FAILED'
const tools = agentResult.toolCalls.length
console.log(` ${agentName.padEnd(12)} [${status}] tool_calls=${tools}`)
if (!agentResult.success) {
console.log(` Error: ${agentResult.output.slice(0, 120)}`)
}
}
 
// Print the developer's final output (the actual code) as a sample
const developerResult = result.agentResults.get('developer')
if (developerResult?.success) {
console.log('\nDeveloper output (last 600 chars):')
console.log('─'.repeat(60))
const out = developerResult.output
console.log(out.length > 600 ? '...' + out.slice(-600) : out)
console.log('─'.repeat(60))
}
 
// Print the reviewer's findings
const reviewerResult = result.agentResults.get('reviewer')
if (reviewerResult?.success) {
console.log('\nReviewer output:')
console.log('─'.repeat(60))
console.log(reviewerResult.output)
console.log('─'.repeat(60))
}
View & edit on GitHub
// Enterprise

Taking this to production?

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.

Enterprise support