Orchestration
@baleybots/orchestration coordinates multiple Baleybots processors as a team. Team is the front door — one roster of members, three topologies per call.
Philosophy
A team is a roster of members, each backed by a Processable (typically a Baleybot). From that roster you pick how agents work together:
- Direct dispatch — you assign tickets to members. Full programmatic control.
- Coordinator — you state a goal; a coordinator decomposes it into tickets, delegates, and synthesizes results.
- Group chat — members talk to each other as peers in a shared thread.
All three share the same ticket/run engine, EventBus, CostTracker, and RunManager underneath.
Install
bun add @baleybots/orchestration @baleybots/core zod ai
Build a team
import { createTeam } from '@baleybots/orchestration';
import { Baleybot } from '@baleybots/core';
const team = createTeam({
members: [
{
name: 'architect',
role: 'Software Architect',
capabilities: ['design', 'planning'],
processable: Baleybot.create({ name: 'architect', goal: 'Design software architecture' }),
},
{
name: 'coder',
role: 'TypeScript Developer',
capabilities: ['typescript', 'implementation'],
processable: Baleybot.create({ name: 'coder', goal: 'Write TypeScript code' }),
},
],
});
1. Direct dispatch
You create work and assign it. createAndDispatch is create-and-run in one call.
team.events.on('ticket.completed', ({ ticket }) => console.log('done', ticket.id));
const run = await team.createAndDispatch({
title: 'Add OAuth login',
description: 'Implement Google OAuth in the desktop app',
assignee: 'coder',
});
console.log(run.status); // 'completed' | 'paused' | 'failed'
2. Coordinator
State a goal; a coordinator decomposes and delegates. Returns a live CrewSession you can chat with while workers execute.
const session = await team.chat('Plan and ship the auth migration');
session.onUpdate((msg) => console.log('[update]', msg));
const reply = await session.send('How is it going?');
const result = await session.stop();
console.log(result.summary);
3. Group chat
Members discuss as peers. Returns a GroupSession; subscribe to per-agent events and start() the conversation.
const session = team.groupChat({ maxTurns: 8 });
session.on('agent-stream-complete', ({ agentName, content }) =>
console.log(`${agentName}: ${content}`),
);
await session.start('Where should we host the migration runbook?');
groupChat() requires every selected member's processable to be a Baleybot instance. Use members: ['architect', 'coder'] to restrict the roster.
Events and cost tracking
Every topology emits typed events on team.events:
team.events.on('run.event', ({ runId, event, agentName }) => {
if (event.type === 'text-delta') process.stdout.write(event.content);
});
team.events.on('agent.budget_exceeded', ({ agent, spent, limit }) => {
console.warn(`${agent.name} over budget: $${spent}/$${limit}`);
});
Built-in pricing covers common models; pass customPricing on Orchestrator for overrides.
Primitives underneath
When the three topologies don't fit, reach for lower-level exports:
| Export | Role |
|---|---|
Orchestrator | Explicit ticket/run engine |
Crew / createCrew() | Coordinator machinery behind team.chat() |
EventBus, AgentRegistry, Scheduler, RunManager | Infrastructure |
createOrchestrationTools() / createWorkerTools() | Zod tools for agent self-management |
createOrchestrationMCPServer() / createCrewMCPServer() | Expose orchestration via MCP |
Group chat exports (groupSession, personality) live at @baleybots/orchestration/ensemble.
Related
- Composition — single-processor pipelines in core
- Packages — where orchestration fits in the monorepo
- Package README — full API reference