Defines agent personalities (Orchestrator, Explorer, Librarian, etc.) and manages their configuration lifecycle. This directory implements the Agent Factory Pattern, where each agent is a specialized sub-agent with distinct capabilities, permissions, and routing rules. The Orchestrator agent (src/agents/index.ts) coordinates task delegation to these specialists.
Each agent is a prompt-driven specialist with a factory function that creates an AgentDefinition:
| Agent | Factory | Role | Permissions | Model Default |
|---|---|---|---|---|
| orchestrator | createOrchestratorAgent() |
Workflow manager that delegates tasks to specialists | Primary agent with full tool access | Resolved from config or runtime preset |
| explorer | createExplorerAgent() |
Fast codebase search and pattern matching | Read-only (glob, grep, ast_grep_search) | DEFAULT_MODELS.explorer |
| librarian | createLibrarianAgent() |
External documentation and library research | Read-only (context7, gh_grep, websearch) | DEFAULT_MODELS.librarian |
| oracle | createOracleAgent() |
Strategic technical advisor and code reviewer | Read-only (read, glob, grep, ast_grep_search) | DEFAULT_MODELS.oracle |
| designer | createDesignerAgent() |
UI/UX design, review, and implementation | Read/write (read, glob, grep, write, edit) | DEFAULT_MODELS.designer |
| fixer | createFixerAgent() |
Fast implementation specialist for bounded tasks | Read/write (read, glob, grep, write, edit) | DEFAULT_MODELS.fixer |
| observer | createObserverAgent() |
Visual analysis specialist (images, PDFs, diagrams) | Read-only (read, glob, grep, ast_grep_search) | DEFAULT_MODELS.observer |
| council | createCouncilAgent() |
Multi-LLM consensus engine for high-stakes decisions | Read-only + council_session tool | DEFAULT_MODELS.council |
| councillor | createCouncillorAgent() |
Read-only council advisor (internal use only) | Read-only (read, glob, grep, ast_grep_search) | Inherited from council |
explorer.ts, oracle.ts)~/.config/opencode/oh-my-opencode-slim.json via loadAgentPrompt()applyDefaultPermissions() in index.ts_modelArray) for runtime fallbackgetSkillPermissionsForAgent()createAgents(config) instantiates all agents with merged configurationapplyDefaultPermissions() sets read/write permissions based on agent type@agent mentions to user-configured display namesgetAgentConfigs() converts AgentDefinition to OpenCode SDK format with classification metadata// 1. Gather sub-agent definitions with custom prompts
const protoSubAgents = Object.entries(SUBAGENT_FACTORIES)
.filter(([name]) => !disabled.has(name))
.map(([name, factory]) => {
const customPrompts = loadAgentPrompt(name, config?.preset);
return factory(getModelForAgent(name), customPrompts.prompt, customPrompts.appendPrompt);
});
// 2. Apply overrides and default permissions
const builtInSubAgents = protoSubAgents.map((agent) => {
const override = getAgentOverride(config, agent.name);
if (override) applyOverrides(agent, override);
applyDefaultPermissions(agent, override?.skills, config?.disabled_skills);
return agent;
});
// 3. Create Orchestrator (with its own overrides and custom prompts)
const orchestrator = createOrchestratorAgent(
orchestratorModel,
orchestratorPrompts.prompt,
orchestratorPrompts.appendPrompt,
disabled,
);
applyDefaultPermissions(orchestrator, orchestratorOverride?.skills, config?.disabled_skills);
// 4. Collect display names and inject into orchestrator prompt
const displayNameMap = new Map<string, string>();
// ... populate from orchestrator and all subagents ...
injectDisplayNames(orchestrator, displayNameMap);
// 5. Return agents array [orchestrator, ...allSubAgents]
return [orchestrator, ...allSubAgents];
export function getAgentConfigs(config?: PluginConfig): Record<string, SDKAgentConfig> {
const agents = createAgents(config);
const applyClassification = (name: string, sdkConfig: SDKAgentConfig) => {
if (name === 'council') {
sdkConfig.mode = 'all'; // Primary + subagent
} else if (name === 'councillor') {
sdkConfig.mode = 'subagent';
sdkConfig.hidden = true; // Internal only
} else if (isSubagent(name)) {
sdkConfig.mode = 'subagent';
} else if (name === 'orchestrator') {
sdkConfig.mode = 'primary';
}
};
// Build SDK config with classification and MCP permissions
const entries: Array<[string, SDKAgentConfig]> = [];
for (const a of agents) {
const sdkConfig = { ...a.config, description: a.description };
applyClassification(a.name, sdkConfig);
// Handle display names: create both displayName and hidden alias
if (a.displayName) {
entries.push([normalizeDisplayName(a.displayName), sdkConfig]);
entries.push([a.name, { ...sdkConfig, hidden: true }]);
} else {
entries.push([a.name, sdkConfig]);
}
}
return Object.fromEntries(entries);
}
model is configured as an array in user config, it's stored as _modelArrayThe main plugin entry point (src/index.ts) consumes the agent system:
import { createAgents, getAgentConfigs, getDisabledAgents } from './agents';
// During plugin initialization:
const disabledAgents = getDisabledAgents(config);
const agentDefs = createAgents(config);
const agents = getAgentConfigs(config);
// Register with OpenCode SDK
return {
name: 'oh-my-opencode-slim',
agent: agents, // SDK agent configs
tool: tools, // Tools including council tools
mcp: mcps, // MCP servers
config: async (opencodeConfig) => { /* merge agent configs */ },
event: async (input) => { /* session tracking, TUI state */ },
};
task() with subagent_type to delegate to specialistssessionAgentMap tracks which agent owns each session for TUI promptsmcps listThe orchestrator's system prompt contains dynamic routing rules that reference agent capabilities:
These rules are filtered based on disabled agents and injected into the orchestrator's prompt at startup.
index.ts - Main agent factory and configuration systemorchestrator.ts - Orchestrator agent definition and prompt builderexplorer.ts - Fast codebase search specialistlibrarian.ts - Documentation and library research specialistoracle.ts - Architecture and code review specialistdesigner.ts - UI/UX design specialistfixer.ts - Implementation execution specialistobserver.ts - Visual analysis specialistcouncil.ts - Multi-LLM council agentcouncillor.ts - Read-only council advisor (internal)permissions.ts - Permission factory for read-only agentsAgentDefinitionsessionAgentMap and event handlers