Orchestrates multi-LLM council sessions by spawning parallel councillor agents, collecting their results, and formatting them for synthesis by the council agent. Implements the Council Pattern to aggregate diverse model perspectives for higher-quality decision making and complex task resolution.
parallel vs serial) for councillor orchestration| Component | Purpose | Type |
|---|---|---|
CouncilManager |
Main orchestrator class | Class |
runCouncil() |
Entry point for council sessions | Method |
runCouncillors() |
Parallel/serial councillor execution | Method |
runAgentSession() |
Single councillor lifecycle management | Method |
runCouncillorWithRetry() |
Retry logic for councillors | Method |
┌─────────────────────────────────────────────────────────────┐
│ CouncilManager │
│ (parentSessionId, prompt, presetName) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ runCouncil() │
│ - Resolve preset (default or named) │
│ - Validate councillor configuration │
│ - Notify parent session (immediate feedback) │
│ - Launch councillors (parallel/serial) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ runCouncillors() │
│ - For each councillor config: │
│ - Spawn child session (session.create) │
│ - Apply depth tracking (if enabled) │
│ - Send prompt with restricted tools │
│ - Extract result (extractSessionResult) │
│ - Cleanup session (session.abort) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ runAgentSession() │
│ - Create session with parentID │
│ - Register child in depth tracker │
│ - Send prompt (promptWithTimeout) │
│ - Extract result with reasoning disabled │
│ - Abort session on completion/cleanup │
└─────────────────────────────────────────────────────────────┘
Promise.allSettled()maxRetries times (provider rate-limiting)PluginConfig from ../config (council presets, timeouts)formatCouncillorPrompt(), formatCouncillorResults() from ../agents/councilextractSessionResult(), promptWithTimeout() from ../utils/sessionlog() from ../utils/loggerSubagentDepthTracker from ../utils/subagent-depth (optional)OpencodeClient from @opencode-ai/plugin (session management)src/index.ts - orchestrates council sessions for complex tasksformatCouncillorResults() for synthesis../config/plugin-config.ts)council: {
default_preset: 'default',
timeout: 180000, // 3 minutes
councillor_execution_mode: 'parallel',
councillor_retries: 3,
presets: {
default: {
architect: { model: 'gpt-4', prompt: 'Think like a software architect' },
critic: { model: 'claude-3', prompt: 'Critique the architect\'s plan' },
implementer: { model: 'gpt-4', prompt: 'Implement the solution' },
},
},
}
ctx.directory)retry_on_empty controls whether to retry empty responsesCouncillors operate with advisory-only tool access:
task - Cannot spawn new subagentsquestion - Cannot ask user questionsedit, write, apply_patch - Cannot modify filesast_grep_replace, bash - Cannot execute commandsread - Can read files for analysisThis ensures councillors provide guidance without side effects.
⎔ Council starting - ${count} councillors launching - ctrl+x ↓ to watchfinally block prevents leaks| Scenario | Behavior | Recovery |
|---|---|---|
| No council config | Return error immediately | User must configure council in plugin config |
| Invalid preset | Return error with available presets | User selects valid preset or uses default |
| Empty preset | Return error about no councillors | User adds councillors to preset |
| All councillors fail | Return error with all failures | Investigate model availability or prompts |
| Timeout | Mark timed_out status | Increase timeout or reduce council size |
| Depth exceeded | Block spawn, return error | Increase maxDepth or simplify task |
| Provider rate-limiting | Retry up to maxRetries | Automatic recovery |