Agent Orchestrator
Agent Orchestrator
Create autonomous agent teams that coordinate through a shared workspace. The orchestrator is a regular Agent with special tools — no subclass needed.
Quick Start
import { createOrchestrator, Connector, Vendor } from 'oneringai';
Connector.create({
name: 'openai',
vendor: Vendor.OpenAI,
auth: { type: 'api_key', apiKey: process.env.OPENAI_API_KEY! },
});
const orchestrator = await createOrchestrator({
connector: 'openai',
model: 'gpt-4.1',
agentTypes: {
architect: {
systemPrompt: 'You are a senior software architect. Design clean, scalable systems. Use the shared workspace to publish your designs.',
tools: [readFile, writeFile],
},
critic: {
systemPrompt: 'You are a thorough code reviewer. Read artifacts from the workspace, find issues, and post your review back to the workspace.',
tools: [readFile, grep],
},
developer: {
systemPrompt: 'You are a senior developer. Read the plan from the workspace, implement it, and update the workspace with your progress.',
tools: [readFile, writeFile, editFile, bash],
},
},
});
const result = await orchestrator.run('Build an auth module with JWT support');
console.log(result.output_text);
Architecture
┌─────────────────────────────────────────────────────────┐
│ Orchestrator (Agent) │
│ │
│ System prompt: auto-generated from agentTypes │
│ Tools: 5 orchestration tools + workspace store tools │
│ │
├─────────────────────────────────────────────────────────┤
│ SharedWorkspace (shared instance) │
│ - entries: plans, code, reviews, status │
│ - log: team conversation │
│ - All agents read/write via store_*("workspace", ...) │
├─────────────────────────────────────────────────────────┤
│ Worker Agents │
│ - Persistent (remember reasoning across turns) │
│ - Own context + shared workspace │
│ - Receive workspace delta at turn start │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Architect │ │ Critic │ │Developer │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────┘
OrchestratorConfig
interface OrchestratorConfig {
connector: string; // Connector for LLM access
model: string; // Model for orchestrator (default for workers too)
systemPrompt?: string; // Custom prompt (overrides auto-generated)
agentTypes: Record<string, AgentTypeConfig>; // Available worker types
workspace?: Partial<SharedWorkspaceConfig>; // Workspace settings
features?: Partial<ContextFeatures>; // Orchestrator context features
pluginConfigs?: PluginConfigs; // Plugin configurations for the orchestrator
name?: string; // Orchestrator name (default: 'orchestrator')
agentId?: string; // For session persistence
maxIterations?: number; // Max loop iterations (default: 100)
maxAgents?: number; // Max worker agents (default: 20)
skipPlanning?: boolean; // Skip UNDERSTAND/PLAN/APPROVE phases (default: false)
tools?: ToolFunction[]; // Tools available to the orchestrator for DIRECT-route tasks
delegationDefaults?: DelegationDefaults; // Default delegation settings
autoDescribe?: boolean; // LLM-generated descriptions for agent types (default: false)
}
interface AgentTypeConfig {
systemPrompt: string; // Role-defining prompt
tools?: ToolFunction[]; // Role-specific tools
model?: string; // Override model per type
connector?: string; // Override connector per type
features?: Partial<ContextFeatures>; // Worker context features
plugins?: PluginConfigs; // Worker plugin configurations
description?: string; // One-liner for routing (e.g., "Senior dev who writes and tests code")
scenarios?: string[]; // When to use (e.g., ["implementing features", "fixing bugs"])
capabilities?: string[]; // What it can do (e.g., ["read/write files", "run shell commands"])
}
3-Tier Routing
The orchestrator v2 uses a 3-tier routing model:
| Route | When | Behavior |
|---|---|---|
| DIRECT | Simple queries, quick lookups | Orchestrator handles directly using its own tools |
| DELEGATE | User needs extended interaction with a specialist | Hands user-facing session to a sub-agent via delegate_interactive |
| ORCHESTRATE | Complex multi-step tasks | Coordinates multiple workers via assign_turn + workspace |
Orchestration Tools
The orchestrator gets 5 tools automatically:
Task Assignment
| Tool | Description |
|---|---|
assign_turn(agent, type, instruction) |
Assign work to an agent. Auto-creates the agent if it doesn't exist. Always async. Optional autoDestroy to clean up after completion. |
delegate_interactive(agent, type?, monitoring?, reclaimOn?, briefing?) |
Hand the user-facing session to a sub-agent. Supports monitoring (passive/active/event) and reclaimOn conditions (keyword, maxTurns, workspaceKey). |
Team Management
| Tool | Description |
|---|---|
list_agents() |
Returns all workers with name, model, status, plus current delegation state. |
destroy_agent(name) |
Destroy a worker. Auto-reclaims delegation if the destroyed agent was the delegatee. |
Communication
| Tool | Description |
|---|---|
send_message(agent, message) |
Inject a message into an agent's context. If the agent is running, the message appears on its next iteration. If idle, it's seen on the next turn. Uses Agent.inject(). |
Workspace Delta
When a worker starts a turn, its instruction is automatically prepended with a workspace delta showing what changed since that worker's last turn:
[Workspace changes since your last turn]
- NEW: "auth_plan" (v1, by architect) — JWT auth design with refresh tokens
- UPDATED: "requirements" (v1→v2, by orchestrator) — Added rate limiting requirement
Recent log:
[architect] Designed API following RESTful patterns
[orchestrator] Added rate limiting to requirements
Design the authentication module based on the approved plan.
Workflow Examples
Sequential Review Cycle
const orchestrator = await createOrchestrator({
connector: 'openai',
model: 'gpt-4.1',
agentTypes: {
architect: { systemPrompt: 'You are a software architect...', tools: [readFile, writeFile] },
critic: { systemPrompt: 'You are a code reviewer...', tools: [readFile] },
developer: { systemPrompt: 'You are a developer...', tools: [readFile, writeFile, editFile, bash] },
},
});
// The orchestrator LLM naturally follows this pattern:
// 1. assign_turn(agent="arch", type="architect", instruction="Design the auth module")
// → auto-creates "arch" as an architect worker
// 2. assign_turn(agent="rev", type="critic", instruction="Review the architecture plan")
// → auto-creates "rev" as a critic worker
// 3. If issues: assign_turn(agent="arch", instruction="Address reviewer feedback")
// 4. assign_turn(agent="dev", type="developer", instruction="Implement the approved plan")
// 5. assign_turn(agent="rev", instruction="Review the implementation")
// 6. If issues: assign_turn(agent="dev", instruction="Fix review comments")
// 7. Final acceptance → destroy_agent for each worker
const result = await orchestrator.run('Build a JWT auth module with refresh tokens');
Parallel Research
const orchestrator = await createOrchestrator({
connector: 'openai',
model: 'gpt-4.1',
agentTypes: {
researcher: {
systemPrompt: 'You are a research analyst. Search the web, analyze findings, and post results to the workspace.',
tools: [webSearchTool, webFetchTool],
},
synthesizer: {
systemPrompt: 'You are an analyst. Read research findings from the workspace and produce a comprehensive summary.',
},
},
});
// The orchestrator will (all assign_turn calls are async/non-blocking):
// 1. assign_turn(agent="r1", type="researcher", instruction="Research competitor A")
// 2. assign_turn(agent="r2", type="researcher", instruction="Research competitor B")
// 3. assign_turn(agent="r3", type="researcher", instruction="Research competitor C")
// → All 3 run concurrently (assign_turn is always non-blocking)
// 4. When results arrive, assign_turn(agent="synth", type="synthesizer", instruction="Combine all research")
const result = await orchestrator.run('Research the top 3 competitors in the AI agent space');
Async Execution (All assign_turn Calls Are Non-Blocking)
// assign_turn is always async (blocking: false). The orchestrator naturally
// launches multiple agents concurrently:
//
// 1. assign_turn(agent="r1", type="researcher", instruction="Research competitor A")
// → Returns immediately, r1 starts working in background
//
// 2. assign_turn(agent="r2", type="researcher", instruction="Research competitor B")
// → Returns immediately, r2 starts working in background
//
// 3. Orchestrator continues: updates workspace, plans next steps, talks to user
//
// 4. Results arrive via autoContinue (500ms batching window):
// → "r1 completed: Found 5 key insights..."
// → "r2 completed: Analysis complete..."
//
// The orchestrator classifies each result: complete, question, stuck, or partial.
// 3-strike rule: after 3 failed re-assignments, try different agent type or escalate.
Interactive Delegation
// For extended interactive sessions (pair-programming, tutoring, debugging):
//
// delegate_interactive(agent="dev", type="developer",
// monitoring="active", // LLM reviews each turn, can intervene
// reclaimOn={ keyword: "done", maxTurns: 20 },
// briefing="User wants help implementing auth")
//
// User now talks directly to the "dev" agent.
// Orchestrator monitors and can inject guidance via send_message.
// Control returns when user says "done" or after 20 turns.
//
// Monitoring modes:
// passive — exchanges logged to workspace, reviewed when control returns
// active — LLM reviews each turn, can inject intervention messages
// event — notified when a specific workspace key appears
//
// Reclaim conditions:
// keyword — user says a word (regex match, e.g., "done", "back")
// maxTurns — auto-reclaim after N delegation turns
// workspaceKey — reclaim when a specific workspace entry appears
Agent.inject()
The inject() method enables orchestrator-to-worker communication:
// Inject a message into a running or idle agent
agent.inject('Please also consider rate limiting in your design');
agent.inject('Switch to OAuth2 instead of JWT', 'developer'); // 'developer' role
// The message is queued and delivered on the agent's next agentic loop iteration.
// Safe to call while the agent is running.
This is used internally by the send_message orchestration tool, but can also be called directly on any Agent instance.
Worker Agent Lifecycle
Workers are persistent — they remember their reasoning across turns:
- Created via
assign_turn(agent=name, type=type, instruction=...)— auto-creates with system prompt, tools, shared workspace - Assigned turns — each subsequent
assign_turncallsagent.run(instruction)on the same instance - Context accumulates — the worker's context grows with each turn (compaction handles limits)
- Destroyed via
destroy_agent(name)or when the orchestrator is destroyed
Custom System Prompt
Override the auto-generated prompt for specialized workflows:
const orchestrator = await createOrchestrator({
connector: 'openai',
model: 'gpt-4.1',
systemPrompt: `You are a QA team lead. For every task:
1. assign_turn a "developer" to write code
2. assign_turn a "tester" to write tests
3. Both run concurrently (assign_turn is always async)
4. If tests fail, send_message the failure details to the developer
5. assign_turn the developer again to fix, repeat until all tests pass`,
agentTypes: {
developer: { systemPrompt: '...', tools: [writeFile, editFile] },
tester: { systemPrompt: '...', tools: [readFile, bash] },
},
});
Per-Type Configuration
Each agent type can have its own model, connector, and features:
const orchestrator = await createOrchestrator({
connector: 'openai',
model: 'gpt-4.1', // Default
agentTypes: {
planner: {
systemPrompt: 'You are a strategic planner...',
model: 'gpt-4.1', // Use the best model for planning
connector: 'openai',
},
coder: {
systemPrompt: 'You are a fast coder...',
model: 'gpt-4o-mini', // Use a faster/cheaper model for coding
connector: 'openai',
tools: [readFile, writeFile, editFile, bash],
},
reviewer: {
systemPrompt: 'You are a code reviewer...',
model: 'claude-sonnet-4-20250514', // Different provider entirely
connector: 'anthropic',
tools: [readFile, grep],
},
},
});