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) andExplore(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"
}
}
}
}
Step 3b: The Markdown way (recommended)
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):
~/.config/opencode/agents/— global agents, available everywhere.opencode/agents/— per-project agents, scoped to a single repo$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@namein 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.0–1.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 |