Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/code-yeongyu/oh-my-opencode/llms.txt

Use this file to discover all available pages before exploring further.

Agents are specialized AI configurations with custom prompts, tool restrictions, and model requirements. Oh My OpenCode includes 11 built-in agents following the factory pattern.

Agent Factory Pattern

All agents follow the createXXXAgent(model) → AgentConfig pattern:
import type { AgentConfig } from "@opencode-ai/sdk"
import type { AgentMode } from "./types"

const MODE: AgentMode = "subagent"

export function createOracleAgent(model: string): AgentConfig {
  return {
    description: "Read-only consultation agent for debugging and architecture",
    mode: MODE,
    model,
    temperature: 0.1,
    prompt: ORACLE_SYSTEM_PROMPT,
    permission: {
      write: "deny",
      edit: "deny",
      task: "deny"
    },
    thinking: { type: "enabled", budgetTokens: 32000 }
  }
}
createOracleAgent.mode = MODE
Source: src/agents/oracle.ts:145

AgentConfig Schema

interface AgentConfig {
  description: string              // Agent purpose (shown in UI)
  mode: AgentMode                  // "primary" | "subagent" | "all"
  model: string                    // Model ID
  temperature?: number             // 0.0-1.0, default 0.1
  maxTokens?: number               // Output token limit
  prompt: string                   // System prompt
  permission?: PermissionConfig    // Tool restrictions
  thinking?: ThinkingConfig        // Extended thinking settings
  reasoningEffort?: "low" | "medium" | "high" | "max" // GPT-specific
  color?: string                   // UI color (hex)
  category?: string                // Category for model resolution
  skills?: string[]                // Auto-loaded skills
  variant?: string                 // Model variant (extended, etc.)
}

type AgentMode = "primary" | "subagent" | "all"

Agent Modes

ModeModel SelectionUse Case
primaryRespects UI-selected model, uses fallback chainMain orchestrators (Sisyphus)
subagentUses own fallback chain, ignores UISpecialized workers (Oracle, Librarian)
allAvailable in both contextsVersatile agents (Sisyphus-Junior)

Permission System

Restrict tool access per agent:
interface PermissionConfig {
  [toolName: string]: "allow" | "deny"
}

const oraclePermissions: PermissionConfig = {
  write: "deny",
  edit: "deny",
  apply_patch: "deny",
  task: "deny",
  call_omo_agent: "deny"
}
Helper Function:
import { createAgentToolRestrictions } from "../shared/permission-compat"

const restrictions = createAgentToolRestrictions([
  "write",
  "edit",
  "task"
])
// Returns: { permission: { write: "deny", edit: "deny", task: "deny" } }
Source: src/agents/oracle.ts:146

Building a Custom Agent

1
Create Agent File
2
Create src/agents/my-agent.ts:
3
import type { AgentConfig } from "@opencode-ai/sdk"
import type { AgentMode } from "./types"
import { createAgentToolRestrictions } from "../shared/permission-compat"

const MODE: AgentMode = "subagent"

const SYSTEM_PROMPT = `You are a specialized agent for [purpose].

<role>
You [core responsibility]. You do NOT [boundaries].
</role>

<workflow>
1. [Step one]
2. [Step two]
3. [Step three]
</workflow>

<constraints>
- [Constraint 1]
- [Constraint 2]
</constraints>`

export function createMyAgent(model: string): AgentConfig {
  const restrictions = createAgentToolRestrictions(["write", "edit"])

  return {
    description: "Brief agent description for user",
    mode: MODE,
    model,
    temperature: 0.1,
    maxTokens: 16000,
    prompt: SYSTEM_PROMPT,
    ...restrictions,
    thinking: { type: "enabled", budgetTokens: 16000 }
  }
}
createMyAgent.mode = MODE
4
Register in Built-in Agents
5
Add to src/agents/builtin-agents.ts:
6
import { createMyAgent } from "./my-agent"

export function createBuiltinAgents(deps: BuildAgentDeps) {
  const agents: Record<string, AgentConfig> = {}

  // ... existing agents

  if (!deps.disabledAgents.has("my-agent")) {
    agents["my-agent"] = buildAgent(
      createMyAgent,
      deps.model,
      deps.categories,
      deps.gitMasterConfig,
      deps.browserProvider,
      deps.disabledSkills
    )
  }

  return agents
}
7
Add to Configuration Schema
8
Register in src/config/schema/agents.ts:
9
export const AgentNameSchema = z.enum([
  // ... existing agents
  "my-agent",
])

export type AgentName = z.infer<typeof AgentNameSchema>
10
Configure Model Requirements
11
Define fallback chain in src/shared/model-requirements.ts:
12
export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
  // ... existing agents
  "my-agent": {
    requiredCapabilities: ["reasoning", "tool-use"],
    fallbackChain: ["claude-opus-4-6", "gpt-5.2", "gemini-3-pro"],
    minimumTier: "tier-2"
  }
}

Agent Builder

The buildAgent() function composes agent configurations:
import { buildAgent } from "./agents/agent-builder"

const agent = buildAgent(
  createMyAgent,           // Factory function
  "claude-opus-4-6",       // Model
  categories,              // Category configs
  gitMasterConfig,         // Git configuration
  browserProvider,         // Browser automation
  disabledSkills           // Skill filter
)
Source: src/agents/agent-builder.ts:14

Agent Builder Logic

export function buildAgent(
  source: AgentSource,
  model: string,
  categories?: CategoriesConfig,
  gitMasterConfig?: GitMasterConfig,
  browserProvider?: BrowserAutomationProvider,
  disabledSkills?: Set<string>
): AgentConfig {
  const base = isFactory(source) ? source(model) : { ...source }
  const categoryConfigs = mergeCategories(categories)

  // Apply category config
  if (base.category) {
    const categoryConfig = categoryConfigs[base.category]
    if (categoryConfig) {
      if (!base.model) base.model = categoryConfig.model
      if (base.temperature === undefined) {
        base.temperature = categoryConfig.temperature
      }
    }
  }

  // Inject skills
  if (base.skills?.length) {
    const { resolved } = resolveMultipleSkills(base.skills, {
      gitMasterConfig,
      browserProvider,
      disabledSkills
    })
    if (resolved.size > 0) {
      const skillContent = Array.from(resolved.values()).join("\n\n")
      base.prompt = skillContent + (base.prompt ? "\n\n" + base.prompt : "")
    }
  }

  return base
}
Source: src/agents/agent-builder.ts:14

Dynamic Prompt Building

Sisyphus demonstrates dynamic prompt construction:
function buildDynamicSisyphusPrompt(
  model: string,
  availableAgents: AvailableAgent[],
  availableTools: AvailableTool[],
  availableSkills: AvailableSkill[],
  availableCategories: AvailableCategory[],
  useTaskSystem: boolean
): string {
  const keyTriggers = buildKeyTriggersSection(availableAgents, availableSkills)
  const toolSelection = buildToolSelectionTable(availableAgents, availableTools, availableSkills)
  const delegationTable = buildDelegationTable(availableAgents)
  const taskManagement = buildTaskManagementSection(useTaskSystem)

  return `<Role>
You are "Sisyphus"...
</Role>

${keyTriggers}
${toolSelection}
${delegationTable}
${taskManagement}`
}
Source: src/agents/sisyphus.ts:151 Pattern: Build prompts from available context (agents, tools, skills).

Model-Specific Configuration

Adjust settings per model family:
export function createMyAgent(model: string): AgentConfig {
  const base = {
    description: "My agent",
    mode: "subagent" as AgentMode,
    model,
    temperature: 0.1,
    prompt: SYSTEM_PROMPT
  }

  // GPT models: use reasoning effort
  if (isGptModel(model)) {
    return { ...base, reasoningEffort: "medium" }
  }

  // Claude/Gemini: use extended thinking
  return { ...base, thinking: { type: "enabled", budgetTokens: 32000 } }
}
Model Detection Helpers:
import { isGptModel, isGeminiModel, isClaudeModel } from "./types"

function isGptModel(model: string): boolean {
  return /gpt-[0-9]/.test(model.toLowerCase())
}

function isGeminiModel(model: string): boolean {
  return /gemini/.test(model.toLowerCase())
}
Source: src/agents/types.ts

Subagent Invocation

Agents are invoked via the task or call_omo_agent tools:
task({
  subagent_type: "my-agent",     // Agent name
  run_in_background: false,      // Sync execution
  description: "Analyze code",
  prompt: "Analyze the auth implementation for security issues"
})

Via call_omo_agent Tool

call_omo_agent({
  subagent_type: "my-agent",
  run_in_background: true,       // Async execution
  description: "Background analysis",
  prompt: "Review all authentication handlers"
})

Agent Prompt Metadata

Document agent usage patterns:
import type { AgentPromptMetadata } from "./types"

export const MY_AGENT_METADATA: AgentPromptMetadata = {
  category: "specialist",           // Category classification
  cost: "MODERATE",                 // CHEAP | MODERATE | EXPENSIVE
  promptAlias: "MyAgent",           // Display name
  triggers: [
    {
      domain: "Security Analysis",
      trigger: "Authentication, authorization, or encryption questions"
    },
    {
      domain: "Code Review",
      trigger: "Security-focused code review requests"
    }
  ],
  useWhen: [
    "Security vulnerability assessment",
    "Authentication flow review",
    "Encryption implementation validation"
  ],
  avoidWhen: [
    "General code review (use Oracle)",
    "Performance optimization (use Hephaestus)",
    "Trivial security questions (answer directly)"
  ]
}

Built-in Agent Examples

Oracle Agent

Purpose: Read-only strategic advisor for complex decisions Key Features:
  • Tool restrictions: No write/edit/task tools
  • High thinking budget: 32000 tokens
  • Structured response format: Bottom line → Action plan → Rationale
  • Effort estimation: Quick/Short/Medium/Large tags
Source: src/agents/oracle.ts:145

Sisyphus Agent

Purpose: Main orchestrator with delegation capabilities Key Features:
  • Dynamic prompt building from available agents/tools/skills
  • Intent verbalization before classification
  • Mandatory todo/task management for multi-step work
  • Model-specific overlays (Gemini tool mandate)
  • Parallel execution default
Source: src/agents/sisyphus.ts:550

Hephaestus Agent

Purpose: Autonomous deep worker for complex implementation Key Features:
  • GPT-5.3-codex requirement (no fallback)
  • High reasoning effort
  • No subagent delegation (works independently)
  • Focus on implementation depth
Source: src/agents/hephaestus.ts

Agent Configuration Override

Users can override agent settings via oh-my-opencode.jsonc:
{
  "agents": {
    "my-agent": {
      "model": "claude-opus-4-6",
      "temperature": 0.2,
      "disabled": false
    }
  }
}
The agent builder merges user overrides with defaults.

Agent Resolution

The session agent resolver determines which agent owns a session:
import { resolveSessionAgent } from "../plugin/session-agent-resolver"

const agent = await resolveSessionAgent({
  sessionID: "ses_123",
  client: ctx.client,
  directory: ctx.directory
})

if (agent === "my-agent") {
  // Apply agent-specific logic
}
Source: src/plugin/session-agent-resolver.ts

Testing Agents

Test agent factories:
import { describe, test, expect } from "bun:test"
import { createMyAgent } from "./my-agent"

describe("createMyAgent", () => {
  test("returns valid AgentConfig", () => {
    const config = createMyAgent("claude-opus-4-6")

    expect(config.model).toBe("claude-opus-4-6")
    expect(config.mode).toBe("subagent")
    expect(config.permission?.write).toBe("deny")
  })

  test("uses reasoning effort for GPT models", () => {
    const config = createMyAgent("gpt-5.2")

    expect(config.reasoningEffort).toBe("medium")
    expect(config.thinking).toBeUndefined()
  })
})
  • Agent Builder: src/agents/agent-builder.ts
  • Agent Types: src/agents/types.ts
  • Built-in Agents: src/agents/builtin-agents.ts
  • Agent Registry: src/agents/index.ts
  • Session Agent Resolver: src/plugin/session-agent-resolver.ts
  • Model Requirements: src/shared/model-requirements.ts

Build docs developers (and LLMs) love