Add a Custom Primary Agent to OpenCode

The problem: you have more than one AI coding workflow. Sometimes you want the coordinator to plan and delegate. Sometimes you want Codex to handle everything directly. Sometimes you want a custom agent with specific rules for a specific project. But OpenCode’s agent switcher only shows a few built-in options.

Here is the fix: edit opencode.json to register your own primary agents. No plugins. No forks. Just a JSON block with a mode, a description, and a prompt. The agent appears in the dropdown after a restart.

This article shows the exact steps. It uses the Codex agent as the example: a primary agent that routes all work through codex exec (OpenAI’s gpt-5.6-terra model) instead of running inline. Zero marginal API cost if you already have a ChatGPT subscription.


Primary Agents vs Subagents

OpenCode has two types of agents:

TypeWhere it appearsHow it is defined
PrimaryAgent switcher dropdown — you talk to it directlyopencode.json under "agent"
SubagentTask tool — another agent delegates to itagents/*.md files with mode: subagent frontmatter

This guide covers primary agents. These are the ones you select from the dropdown and chat with. Subagents are covered in a separate article about agent orchestration.


Step 1: Find opencode.json

The config file lives in the OpenCode config directory:

~/.config/opencode/opencode.json

On Windows, this resolves to:

C:\Users\{username}\.config\opencode\opencode.json

Open it. The file has a top-level "agent" key. It contains one or more named agent blocks. Here is a typical file with only the coordinator agent:

{
  "$schema": "https://opencode.ai/config.json",
  "default_agent": "coordinator",
  "agent": {
    "coordinator": {
      "mode": "primary",
      "description": "Coordinator agent that plans and delegates.",
      "prompt": "You are a coordinator agent..."
    }
  }
}

Each entry under "agent" has three required fields:

FieldPurpose
modeMust be "primary" for dropdown agents
descriptionOne-line summary shown in the agent selector
promptThe system prompt that defines how the agent behaves

Step 2: Add Your Agent

Add a new block to the "agent" object. The key is the agent name. Here is the Codex agent as an example:

"agent": {
  "coordinator": {
    "mode": "primary",
    "description": "Coordinator agent that plans, delegates all work to subagents.",
    "prompt": "You are a coordinator agent..."
  },
  "codex": {
    "mode": "primary",
    "description": "Codex-powered agent. Routes ALL work through codex exec (gpt-5.6-terra).",
    "prompt": "You are a Codex-powered agent. ALL work goes through codex exec..."
  }
}

The prompt is the most important part. It defines what the agent can and cannot do. For the Codex agent, the prompt tells it to:

  • Route all work through codex exec — exploration, implementation, debugging
  • Never use Read, Grep, Glob, Write, or Edit tools directly
  • Use Bash only for codex invocation, git operations, and service health checks
  • Report what changed: file paths, line ranges, verification

Here is the full prompt used for the Codex agent:

"prompt": "You are a Codex-powered agent. ALL work goes through `codex exec` (gpt-5.6-terra) — read-only exploration, implementation, debugging, everything. You do NO work directly.\n\nWORKFLOW:\n1. ANALYZE the user's request.\n2. WRITE a precise prompt containing the full task: what to explore, what files are involved, requirements, constraints, error messages. Save to `$env:TEMP\\opencode\\codex_prompt.txt`.\n3. INVOKE Codex: `Get-Content $promptFile | codex exec --dangerously-bypass-approvals-and-sandbox -m gpt-5.6-terra -C \"\" -o \"$env:TEMP\\opencode\\codex_output.txt\" 2>&1`\n4. READ codex output from `$env:TEMP\\opencode\\codex_output.txt`.\n5. REPORT the result to the user: what codex found, what changed, what files, line ranges.\n\nRULES:\n- NEVER use Read, Grep, Glob, Write, Edit, or Webfetch tools. All work goes through codex exec.\n- Bash tool ONLY for: codex invocation, git operations (status, diff, commit, push), service health checks.\n- If codex fails, read the output, report the error. Do NOT do the work yourself.\n- For complex tasks, break into multiple sequential codex calls — each small, verified.\n- Security: if task involves secrets or destructive ops, confirm before sending to codex."

A few things to note about the prompt string:

  • Newlines must be escaped as \n — this is JSON, not YAML
  • Backslashes in paths must be escaped as \\ (JSON escapes backslash)
  • Double quotes inside the string must be escaped as \"
  • No trailing commas — JSON does not allow them
  • Validate the JSON before saving. Run python -c "import json; json.load(open('opencode.json'))"

Step 3: Resolve Naming Conflicts

A common problem: config-defined agents and file-based agents with the same name. OpenCode loads agents from two places:

SourceFormatMode
opencode.json"agent"JSON block"primary"
agents/{name}.mdMarkdown with YAML frontmattersubagent (usually)

If both exist with the same name, one overrides the other. The result: your new primary agent does not appear in the dropdown. It is treated as a subagent instead.

The fix is simple: remove the file-based agent. If you have agents/codex.md defining codex as a subagent, and you add a codex primary agent in opencode.json, delete the .md file. The config-based definition takes priority after the conflict is gone.

rm ~/.config/opencode/agents/codex.md

On Windows PowerShell:

Remove-Item -LiteralPath "$env:USERPROFILE\.config\opencode\agents\codex.md" -Force

Step 4: Restart OpenCode

Save opencode.json. Restart OpenCode. The new agent appears in the dropdown. Select it. The chat now runs with the custom prompt you defined.

To verify the agent loaded correctly, check the agent selector. If it is not there, check the OpenCode logs for JSON parse errors. A stray trailing comma or a missing escape character is usually the cause.


Why Codex?

The Codex agent is useful for a specific workflow: you want the smartest available model for implementation work, and you want it at zero marginal cost. OpenAI’s gpt-5.6-terra (via Codex CLI) runs on a ChatGPT subscription. No per-token billing. No API key to manage. The agent shells out to Codex, reads the result, and reports back.

This is different from the coordinator agent, which delegates work to subagents running locally. The Codex agent sends the entire task to Codex — including exploration, implementation, and debugging. It is a single call with a full context prompt, not a multi-step orchestration.

AgentExecutionCostBest for
CoordinatorDelegates to local subagentsAPI tokens (deepseek)Multi-step plans, parallel work
CodexShells out to Codex CLIChatGPT subscription (zero marginal)Heavy implementation, single-shot tasks

Complete opencode.json Example

Here is a full opencode.json with both the coordinator and codex agents registered. Use it as a template for your own custom agents.

{
  "$schema": "https://opencode.ai/config.json",
  "logLevel": "INFO",
  "default_agent": "coordinator",
  "agent": {
    "coordinator": {
      "mode": "primary",
      "description": "Coordinator agent that plans, delegates all work to subagents, and compiles results.",
      "prompt": "You are a coordinator agent. Your role is to orchestrate work, NOT to execute it directly..."
    },
    "codex": {
      "mode": "primary",
      "description": "Codex-powered agent. Routes ALL work through codex exec (gpt-5.6-terra).",
      "prompt": "You are a Codex-powered agent. ALL work goes through codex exec..."
    }
  },
  "plugin": [
    "./plugins/caveman/plugin.js",
    "opencode-rename-chat"
  ]
}

Lessons Learned

1. JSON Escaping Is the Hardest Part

A long system prompt has backslashes, double quotes, and newlines. In JSON, each needs an escape. Write the prompt in a text editor first. Then wrap it. Use a JSON validator before saving. A single missing backslash breaks the entire config file.

2. The Prompt Defines the Agent

The difference between agents is entirely in the prompt. The coordinator delegates to subagents. The codex agent shells out to Codex CLI. A custom agent for a specific project could enforce coding standards, restrict tool access, or follow a specific workflow. The prompt is the only difference. Spend time on it.

3. File-Based Agents Create Hidden Conflicts

The agents/ directory and the opencode.json file are two separate agent registries. They can conflict silently. If an agent does not appear in the dropdown, check both places. Remove duplicates. The config-based definition is the one you want for primary agents.

4. Agent Selection Is a Workflow Choice

Switching between agents is fast — restart and select. Use the coordinator for multi-step planning. Use Codex for heavy single-shot implementation. Custom agents for project-specific needs. The agent switcher is not just a dropdown. It is a tool selection mechanism. Choose the right tool for the job.

5. Codex CLI Has Zero Marginal Cost

If you pay for ChatGPT, you already have access to gpt-5.6-terra through Codex CLI. There is no per-token billing. No API key to manage. No rate limits to track. The Codex agent uses a subscription you already have. It is free at the margin. For implementation-heavy work, that is a strong argument.


Resources


This article is part of the OpenCode series. See also the guide on running OpenCode Web behind Authentik SSO for secure multi-device access.


Posted

in

,

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *