opencode-config

This repo was driven by the question:

How do we create a council of AI experts, with defined personas, using opencode?

Motivation

Oh My OpenAgent

oh-my-openagent is a tool that creates different developer personas and assembles them into a super-team where work is effectively delegated.

However, it is highly opinionated, and designed for software developers. So we set about figuring out how to divorce oh-my-openagent functionality from its personas, so we can build our own highly opinionated team.

What Oh My OpenAgent Actually Does

To understand what you'd be leaving behind—or needing to replicate—it helps to separate Oh My OpenAgent's architecture from its personas:

  • Parallel Execution: It fires off utility agents like Librarian (for web research) and Explore (for local file reading) simultaneously to gather context fast.
  • Gatekeeping: It forces execution plans through a "Critic" agent before any actual bash commands or code edits happen.
  • Session Continuity: It maintains a strict state tracker so interrupted work can resume exactly where it left off.

If you don't need highly complex, multi-agent parallel orchestration right out of the gate, you don't need Oh My OpenAgent.


Building Your Scientific Council

OpenCode lets you define custom agents — each with its own model, system prompt, and tool permissions. We'll keep these in a version-controlled repository and use the OPENCODE_CONFIG_DIR environment variable to point OpenCode at it, keeping the council completely isolated from your default OpenCode config.

Step 1: Find your available model strings

Model strings are provider-specific and must exactly match what OpenCode knows about. Run this to see yours:

opencode models

You'll get a list like amazon-bedrock/anthropic.claude-opus-4-6-v1, amazon-bedrock/anthropic.claude-haiku-4-5-20251001-v1:0, etc. Pick one for each agent and note the exact strings — you'll need them in Step 3.

Step 2: Create the config repo

mkdir -p ~/my-opencode-council
cd ~/my-opencode-council
git init

OpenCode requires a tui.json file in the config directory, even if you have no TUI customizations. Create an empty one:

echo '{}' > ~/my-opencode-council/tui.json

Step 3: Create the agent config

You have two options here: JSON or Markdown. We strongly recommend Markdown — writing multi-paragraph system prompts inside escaped JSON strings is a miserable experience, and you will be writing multi-paragraph prompts. The JSON approach is shown first only because it puts everything in one file, which is easier to explain. Skip ahead to Step 3b if you value your sanity.

Step 3a: The JSON way

Create ~/my-opencode-council/opencode.json with your agent definitions. We define three agents — a PI for strategy, a researcher for literature, and a bioinformatician for execution.

Replace the model strings below with ones from your opencode models output.

{
  "$schema": "https://opencode.ai/config.json",
  "default_agent": "pi",
  "agent": {
    "pi": {
      "mode": "primary",
      "description": "Principal Investigator (Strategy & Planning)",
      "model": "amazon-bedrock/anthropic.claude-opus-4-6-v1",
      "prompt": "You are the Principal Investigator. Your job is to orchestrate research, debate methodology, and plan the bioinformatics approach. Do NOT write code or execute terminal commands. Ask clarifying questions, challenge assumptions, and synthesize findings until a solid methodology is formed.",
      "permission": {
        "edit": "deny",
        "bash": "deny",
        "read": "allow",
        "webfetch": "allow"
      }
    },
    "researcher": {
      "mode": "subagent",
      "description": "Literature Researcher (Fast Context Gathering)",
      "model": "amazon-bedrock/anthropic.claude-haiku-4-5-20251001-v1:0",
      "prompt": "You are the Literature Researcher. Your job is to find academic papers, read documentation, and summarize findings. Use your available web search tools to gather context and provide thorough academic summaries.",
      "permission": {
        "edit": "deny",
        "bash": "deny",
        "websearch": "allow",
        "webfetch": "allow"
      }
    },
    "bio": {
      "mode": "primary",
      "description": "Bioinformatician (Execution & Scripting)",
      "model": "amazon-bedrock/qwen.qwen3-coder-480b-a35b-v1:0",
      "prompt": "You are the Bioinformatician. Your job is to write data pipelines, format datasets, and execute scripts in the terminal. You have full permission to edit files and run bash commands. Prioritize clean, reproducible code.",
      "permission": {
        "edit": "allow",
        "bash": "allow",
        "read": "allow"
      }
    }
  }
}

Instead of cramming prompts into JSON strings, you can define each agent as a standalone Markdown file. YAML frontmatter at the top holds the metadata (model, permissions, mode), and the entire body of the file becomes the system prompt — with full Markdown formatting, no escaping, no pain.

How discovery works

OpenCode automatically scans for .md files in an agents/ subdirectory of any config directory it knows about. You don't register them in opencode.json — you just drop them in the folder and they exist. Specifically, OpenCode checks these locations (in order, later ones override earlier ones):

  1. ~/.config/opencode/agents/ — global agents, available everywhere
  2. .opencode/agents/ — per-project agents, scoped to a single repo
  3. $OPENCODE_CONFIG_DIR/agents/ — if you set the env var (which we do in Step 4)

The filename becomes the agent name. pi.md creates an agent called pi. researcher.md creates researcher. That's how you reference them with @researcher or set "default_agent": "pi" — the name comes from the file, not from anything inside it.

What to put in opencode.json

With Markdown agents, your opencode.json shrinks to just global settings. You no longer define agents in it — the .md files replace that entirely. All you need is:

{
  "$schema": "https://opencode.ai/config.json",
  "default_agent": "pi"
}

The default_agent value must match a filename (minus .md) in your agents/ directory.

Create the agents

mkdir -p ~/my-opencode-council/agents

Your config repo now looks like this:

~/my-opencode-council/
├── opencode.json          # just {"default_agent": "pi"} + schema
├── tui.json               # required, can be empty {}
└── agents/
    ├── pi.md              # → agent "pi"
    ├── researcher.md      # → agent "researcher"
    └── bio.md             # → agent "bio"

Now create the three agent files. Replace the model strings with ones from your opencode models output.

agents/pi.md:

---
description: Principal Investigator (Strategy & Planning)
mode: primary
model: amazon-bedrock/anthropic.claude-opus-4-6-v1
permission:
  edit: deny
  bash: deny
  read: allow
---
You are the Principal Investigator. Your job is to orchestrate research, debate methodology, and plan the bioinformatics approach.

Do NOT write code or execute terminal commands.

Ask clarifying questions, challenge assumptions, and synthesize findings until a solid methodology is formed. Focus specifically on ensuring statistical rigor in experimental design.

agents/bio.md:

---
description: Bioinformatician (Execution & Scripting)
mode: primary
model: amazon-bedrock/qwen.qwen3-coder-480b-a35b-v1:0
permission:
  edit: allow
  bash: allow
  read: allow
---
You are the Bioinformatician. Your job is to write data pipelines, format datasets, and execute scripts in the terminal.

You have full permission to edit files and run bash commands. Prioritize clean, reproducible code and ensure any python or R dependencies are correctly managed in the environment.

agents/researcher.md:

---
description: Literature Researcher (Fast Context Gathering)
mode: subagent
model: amazon-bedrock/anthropic.claude-haiku-4-5-20251001-v1:0
permission:
  edit: deny
  bash: deny
  websearch: allow
  webfetch: allow
---
You are the Literature Researcher. Your job is to find academic papers, read documentation, and summarize findings.

Use your available web search tools to gather context and provide thorough academic summaries.

The frontmatter supports all the same fields as the JSON agent config: description, mode, model, temperature, steps, permission, etc. Full documentation: https://opencode.ai/docs/agents/.

Step 4: Create the shell alias

OpenCode doesn't have a --config flag. Instead, use the OPENCODE_CONFIG_DIR environment variable to point OpenCode at your repo.

Open your ~/.bashrc (or ~/.zshrc) and add:

alias council="OPENCODE_CONFIG_DIR=~/my-opencode-council opencode --pure"

Then source ~/.bashrc.

The --pure flag tells OpenCode to skip loading external plugins (like oh-my-openagent), so the council runs in a clean environment.

Step 5: Verify the agents loaded

council

Once the TUI launches, check the status bar at the bottom — it should show Pi as the active agent (because of "default_agent": "pi" in the config). You can also quit and run:

OPENCODE_CONFIG_DIR=~/my-opencode-council opencode agent list

You should see pi, researcher, and bio alongside the built-in agents (build, plan, etc.).

Step 6: Test the PI agent

Type a question:

What's the best approach for analyzing differential gene expression in a small-sample RNA-seq experiment?

The PI should talk strategy — ask clarifying questions, debate methodology — without writing or executing code.

Step 7: Test the researcher

While chatting, type this directly in the chat input:

@researcher Find the most recent papers on batch effect correction methods for scRNA-seq data.

The @researcher prefix hands the message to the researcher subagent. It runs on Haiku (fast and cheap), uses its web search tools to find papers, and returns a summary into your conversation.

Step 8: Test the bioinformatician

Press Tab to cycle through primary agents. You'll see the agent name change in the TUI status bar. Tab until you land on bio, then type:

Write a Python script that prints hello world and run it.

The bioinformatician has full bash and edit permissions, so it should write the script and execute it.


How Agents Work

Agent modes

The mode field controls how you interact with each agent:

  • "primary" — The agent appears in the Tab cycle in the TUI. You switch to it by pressing Tab until its name shows in the status bar. In our council, PI and Bio are primary agents because you want to actively switch between planning and execution.

  • "subagent" — The agent does not appear in the Tab cycle. You invoke it by typing @name in the chat input, either yourself or by another agent delegating to it. In our council, the Researcher is a subagent because you call on it for specific tasks (@researcher find papers on X) rather than switching to it as your main conversational partner.

  • "all" (the default) — Both. It appears in Tab and can be invoked via @name.

If you want to change a subagent into a Tab-switchable agent (or vice versa), just change its mode field in the config and restart OpenCode.

Agent config fields

Field Type Default Description
description string required Explains what the agent does
mode string "all" "primary", "subagent", or "all"
model string global model Provider/model ID (must match opencode models output)
prompt string System prompt (supports {file:path/to/prompt.txt} to load from file)
temperature float model default 0.01.0
steps int Max agentic iterations
permission object Per-tool permission overrides

Permissions

The permission object enforces what tools the agent can actually use — this is not a suggestion to the LLM, it's a hard gate. Setting "bash": "deny" on the PI means it physically cannot run terminal commands.

Three levels: "allow" (no confirmation), "ask" (user approves each use), "deny" (tool unavailable).

For fine-grained bash control, use pattern matching:

"bash": {
  "*": "ask",
  "git *": "allow",
  "python *": "allow",
  "rm *": "deny"
}

Available permission keys: read, edit, bash, glob, grep, task, webfetch, websearch, and others.

Commands vs agents

OpenCode also has a command system ("command" key in config), but commands are reusable prompt templates invoked with /name — think of them as macros, not personas. Agents are the right mechanism for personas with distinct models and permissions.

Quick reference

What you want to do How
Switch between primary agents Press Tab in the TUI
Invoke a subagent Type @name in your message
Set the default starting agent "default_agent" in config, --agent flag, or OPENCODE_AGENT env var
Point OpenCode at a custom config OPENCODE_CONFIG_DIR=path opencode
Skip plugins Add --pure to the command
List available agents opencode agent list
List available models opencode models
Description
No description provided
Readme 56 KiB