OpenCode agents: files, frontmatter and four complete examples
| Introduction | |
| Where to put agents | |
| How to build an agent | |
| Real project skeleton | |
| Four complete agents | |
| Commands that select agents | |
| Make the agents run | |
| The agent loop | |
| Tools make the agent | |
| Troubleshooting |
Introduction
This is the OpenCode side of Building AI agents: the exact files, fields and commands. If you only want the role model behind triage, builder and reviewer, read that page first. Here we wire them into .opencode/agents/, pin the free OpenCode model, GPT 6 Luna or Claude Opus 5.5 per role, and prove the roles actually run.
Where to put agents
Same model trio as skills, but here you pin a different model per role. Personal agents go global, team agents go in the repo and get committed.
- Project, recommended: .opencode/agents/<name>.md — nested path becomes id with slash, team/reviewer.md becomes team/reviewer.
- Global, personal: ~/.config/opencode/agents/<name>.md — every project of the user.
- Inline in config: agents map in opencode.jsonc — same fields, body goes to system. Handy for one-line overrides of built-ins.
Built-ins you can override by reusing the id: build (primary coder, default), plan (primary, no project edits), general (subagent research), explore (subagent read-only). Hidden title, summary, compaction do maintenance and cannot be selected. Full tree with links is under Real project skeleton.
How to build an agent
A Markdown agent is frontmatter plus a body. Frontmatter accepts the same fields as the JSON map. The body becomes the system prompt. Example file .opencode/agents/reviewer.md:
mkdir -p .opencode/agents
vi .opencode/agents/reviewer.md
--- description: Reviews changes for correctness and regressions mode: subagent model: opencode/claude-opus-5-5 steps: 8 color: "#ff6b6b" permissions: - action: edit resource: "*" effect: deny --- Review the current changes. List findings in severity order.
Fields that matter in practice:
- description: one line shown to the model that picks subagents. Always set it for subagents.
- mode: primary runs as main session, subagent runs only as child via the subagent tool, all runs both ways. New custom agents default to primary.
- model: provider/model plus optional #variant, for example opencode/gpt-6-luna or opencode/claude-opus-5-5. Empty means inherit the parent session model.
- steps: max model steps before tools are removed and a summary is forced. Use 6 to 10 for reviewers, leave empty for builders.
- permissions: ordered allow, ask, deny rules. Last match wins. Common actions: shell, edit, read, glob, grep, webfetch, websearch, skill, subagent.
- color, hidden, disabled: UI color hex, hide from pickers, remove a built-in at that config layer.
JSON form for quick overrides without an agent file, in opencode.jsonc at the project root:
vi opencode.jsonc
{ "$schema": "https://opencode.ai/config.json", "default_agent": "build", "agents": { "build": { "permissions": [ { "action": "shell", "resource": "git push *", "effect": "deny" } ] } } }
Later configs merge: scalars replace, permission rules append, so global allow plus agent deny yields deny. A subagent uses its own permissions, not a subset of the parent. Control which children a parent may launch, in the same opencode.jsonc:
{ "agents": { "orchestrator": { "permissions": [ { "action": "subagent", "resource": "*", "effect": "deny" }, { "action": "subagent", "resource": "reviewer", "effect": "allow" } ] } } }
Real project skeleton
Agent side of the same demo project from Skills skeleton. Output of tree, every element links to the chapter where it is explained:
my-app/ ├── opencode.jsonc ├── .opencode/agents/ │ ├── reviewer.md │ ├── builder.md │ ├── triage.md │ └── team/orchestrator.md ├── .opencode/skills/ │ ├── api-review/ │ │ └── SKILL.md │ └── test-writer/ │ └── SKILL.md ├── .opencode/commands/ │ ├── review.md │ └── build-feature.md └── AGENTS.md
Read it as roles: reviewer is the Opus-only read-only judge, builder is the Luna daily driver, triage is the free-model inbox sorter, orchestrator fans out to children. Commands select the agent and model in one keystroke. Skills beside them supply the checklists each role loads.
Four complete agents
Four files you can drop into .opencode/agents/ today. They map to the model split from Models that matter: cheap triage, standard build, top review, plus one orchestrator that ties them together. How they share one project with gated skills is shown in Three models, one project.
Example 1 — Opus reviewer, read-only. File .opencode/agents/reviewer.md, id reviewer. Final pass on staged diffs, never edits:
mkdir -p .opencode/agents
vi .opencode/agents/reviewer.md
--- description: Final correctness and security pass over staged diffs mode: subagent model: opencode/claude-opus-5-5 steps: 8 permissions: - action: edit resource: "*" effect: deny - action: shell resource: "*" effect: deny - action: skill resource: "*" effect: deny - action: skill resource: api-review effect: allow --- Review the staged diff. Load api-review first. Report bugs first in severity order with file and line. Verdict: ship, fix first, or block. Do not edit files.
Launch with Use the reviewer subagent to review my staged changes. It loads only api-review, so output stays in rubric form even on large diffs.
Example 2 — Luna builder, daily driver. File .opencode/agents/builder.md, id builder. Cheap, steady, allowed to edit and test but never push:
vi .opencode/agents/builder.md
--- description: Implements small features with tests on GPT 6 Luna mode: primary model: opencode/gpt-6-luna permissions: - action: shell resource: "*" effect: ask - action: shell resource: "git status *" effect: allow - action: shell resource: "git diff *" effect: allow - action: shell resource: "npm test *" effect: allow - action: shell resource: "git push *" effect: deny --- Implement the requested change in small steps. After each edit run the narrowest test command and show the diff. Stop after two failing attempts and report what is missing.
Pair with @test-writer for coverage: With builder, add pagination to orders and cover it with test-writer.
Example 3 — free-model triage, inbox sorter. File .opencode/agents/triage.md, id triage. Free, fast, capped steps, explains code without changing it:
vi .opencode/agents/triage.md
--- description: Explains code and sorts small tasks without editing mode: primary model: opencode/deepseek-v4.1-flash-free steps: 6 permissions: - action: edit resource: "*" effect: deny - action: shell resource: "*" effect: deny --- Explain the relevant code with short examples. Sort the request into docs, small fix, or needs-build. Propose the next agent: builder for fixes, plan for features. Do not edit files. Never handle secrets.
Start every morning on triage, escalate only what needs tools: With triage, explain src/auth.ts login flow and route the refresh bug. Keeps free-tier privacy safe because it never touches .env files.
Example 4 — orchestrator that fans out. File .opencode/agents/team/orchestrator.md, id team/orchestrator. Plans on Luna, delegates review to Opus, research to general:
mkdir -p .opencode/agents/team
vi .opencode/agents/team/orchestrator.md
--- description: Plans a feature then fans out to builder and reviewer mode: primary model: opencode/gpt-6-luna permissions: - action: subagent resource: "*" effect: deny - action: subagent resource: "builder" effect: allow - action: subagent resource: "reviewer" effect: allow - action: subagent resource: "explore" effect: allow --- Plan the feature in three bullets: files, schema, tests. Then ask explore to map unknowns and builder to implement step one. Finish by asking reviewer for a verdict. Report the three results.
Launch with With team/orchestrator, plan cursor pagination for orders. The parent stays usable while background children run, results return to the parent session.
Commands that select agents
File .opencode/commands/review.md pins Opus review in the background, file .opencode/commands/build-feature.md pins Luna build in the current session:
--- description: Review staged changes on Opus agent: reviewer model: opencode/claude-opus-5-5 subagent: true --- Review this diff for bugs, security and missing tests: !`git diff --cached`
--- description: Build one feature step on Luna agent: builder model: opencode/gpt-6-luna subagent: false --- Build $ARGUMENTS in one small step with tests. Show the diff and stop for review.
Run as /review and /build-feature cursor pagination for orders. Command model beats agent model beats session model, so explicit pins always win.
Make the agents run
A correct agent file does nothing by itself. Two more things must happen: the assistant has to load the project config, and a person or command has to select the role. Most tickets titled "agents created, agents unused" are one of those two — or a model id that stopped resolving.
- 1. Start where the config lives. opencode.jsonc, .opencode/agents/ and nested AGENTS.md files are discovered per project directory. A session started in a home directory, one level above the repo, or in a sibling checkout never sees them and quietly runs the built-ins. Launch the assistant from the project root, or move the session there, before expecting the roles to exist.
- 2. Make every model id resolve. model takes provider/model and an optional #variant. The id must exist in the provider catalog: opencode/muse-spark-1.3 ships variants minimal through xhigh, while a retired id such as opencode/muse-spark-1.3-contributor-free resolves nowhere — the agent then falls back to the session model or refuses to start. Check each pick once, then pin the variant you tested; free ids change most often, so check them as in Free OpenCode model.
- 3. Select the primary agent per task. The picker chooses triage for read-only routing, builder for edits, orchestrator when the job fans out. Defining an agent never makes it the default unless default_agent says so, and a subagent runs only when a parent calls it or a command pins agent:.
- 4. Give every role a canary task. Triage explains one flow and names the next agent; builder makes one small edit and shows the diff; reviewer finds one planted bug in a staged diff; orchestrator returns two child results. One pass-fail line per role tells you more than a page of config.
- 5. Read the history, not the folder. Session history records the agent and model that actually ran. If triage never appears there after a week of work, the role is decoration: the task never needed it, or the config was never loaded.
- 6. Batch only independent work. Parallel children are the real win — five read-only checks or five lesson drafts at once. A one-line edit is not: the spawn costs more than the task. Keep the cheap model for reading and the expensive model for review.
Permissions are the trap that looks like a broken model: rules are ordered and the last match wins. An agent denied the one tool its job needs answers with an apology instead of an error, and the model gets the blame. Re-read the rules before the first eval.
The agent loop
Keep the loop explicit and boring: plan one step, execute exactly one
tool call, record the observation in short-term memory, repeat. Cap the
iterations (twenty is plenty for most tasks) and define the stop
conditions up front: done, blocked, or out of budget. The
steps field enforces the cap — on the final step
tools are removed and a text summary is forced.
Log every iteration. When an agent misbehaves, the trace tells you in
seconds whether the planner, a tool, or the instructions failed. Example
trace prompt that works on all three models:
Find where request timeouts are configured, change the default to 30 seconds, run the relevant tests
— typically grep, read, edit, shell in that order.
Tools make the agent
A model with five sharp tools beats a smarter model with one dull tool.
Design tools like APIs for a junior colleague: one purpose per tool,
strict input validation, and error messages that say what to try next.
In OpenCode the fixed core is
read, glob, grep, edit, write, shell, webfetch,
websearch, question, skill, subagent, execute plus
MCP tools named server_tool.
Gate them per role. Example trio: triage denies
edit and shell; builder
allows git status, git diff
and the test command, asks for the rest, denies
git push; reviewer denies
edit and shell and loads
one review skill. The full catalog and MCP wiring live in
MCP: give AI assistants real tools.
Troubleshooting
- Agent does not appear in the picker. Check the file path: project agents live in .opencode/agents/, and the id comes from the path, not the title. A file in the wrong directory is just a text file.
- Model error on start. The model string must match the catalog exactly, including the variant. Remove the variant to test, then pin it back.
- Subagent never selected. The parent picks subagents by description; a vague line such as Helps with code loses to a built-in. Name the trigger: Call after every staged diff.
- Role refuses an allowed action. Permission rules are ordered and the last match wins. Move the allow rule after the broad deny, or narrow the deny.
- Config ignored entirely. The session started outside the project. Start in the repo root; nested AGENTS.md files only load while working inside their directory.
Article author: Arthur Isaev