caft/blog

An OpenCode agent team on caft

Set up OpenCode with fourteen agents across six model families on one caft key: cheap models write the code, other families review it, and a monthly plan covers most of the traffic.

One model for everything is the easy setup, and the wasteful one. Most of an agent's tokens go to reading code, writing small changes and running tests: work a fast, cheap model does well. The expensive judgment is in planning and review, and review works best when the reviewer isn't the model that wrote the code, since it tends to share that model's blind spots.

This is the OpenCode setup we use to build caft, moved onto caft models only. Twelve models from six families (GPT, Gemini, GLM, Kimi, DeepSeek and Qwen) run as fourteen agents, all on one API key.

The team

AgentJobModelPaid by
build (primary)Small, clear changes, test firstGLM 5.3 Flash, highPlan
plan (primary)Specs and implementation plansKimi K3, highPlan
orchestrator (primary)Runs a plan: dispatches implementers and reviewersGLM 5.3, highPlan
architect (primary)High-stakes design: money, keys, authGPT-6 Astra, highBalance
exploreSearch the codebase, read many filesGemini 3.8 Flash, lowPlan
implementerOne plan task with a complete spec, 1–3 filesGLM 5.3 Flash, highPlan
implementer-plusMulti-file work, or a task the implementer couldn't finishKimi K2.7, highPlan
debuggerRoot cause of a bug or failing testQwen 3.8 Max, highPlan
verifierRun tests and lint; report only failuresDeepSeek V4.1 Flash, lowPlan
plan-reviewerCheck a plan against its spec before work startsGemini 3.1 Pro, highPlan
code-reviewerReview each task, and the whole branch at the endGPT-6 Sol, highBalance
re-reviewerCheck that a fix resolves earlier findingsGPT-5.6 Terra, mediumBalance
security-reviewerBranches that touch auth, secrets, payments or inputGPT-6 Astra, highBalance
adversarial-reviewerTry to break a branch that already passed reviewGemini 3.1 Pro, highPlan

Three choices shape it:

The primary agents are the ones you switch between in OpenCode: plan for specs and plans, orchestrator to run a plan, build for small jobs, and architect when a mistake would be expensive. The rest are subagents, which a primary agent dispatches. OpenCode can't pass a model in a dispatch, so each subagent always runs on its own model, and choosing an agent is choosing a model. When you switch to a primary agent, check the model shown beside it and pick the one in the table if it differs.

1. Add caft as a provider

Put your caft API key in CAFT_API_KEY and merge this into ~/.config/opencode/opencode.json. It adds every model the team uses and sets the built-in agents' models. A #high or #low suffix picks the reasoning effort.

JSON
{
  "$schema": "https://opencode.ai/config.json",
  "model": "caft/glm-5.3-flash#high",
  "small_model": "caft/gpt-6-luna",
  "instructions": ["~/.config/opencode/agent-routing.md"],
  "providers": {
    "caft": {
      "name": "caft",
      "package": "aisdk:@ai-sdk/openai-compatible",
      "settings": {
        "baseURL": "https://api.caft.dev/v1",
        "apiKey": "{env:CAFT_API_KEY}"
      },
      "models": {
        "gpt-6-astra": { "name": "GPT-6 Astra" },
        "gpt-6-sol": { "name": "GPT-6 Sol" },
        "gpt-6-luna": { "name": "GPT-6 Luna" },
        "gpt-5.6-terra": { "name": "GPT-5.6 Terra" },
        "gemini-3.1-pro": { "name": "Gemini 3.1 Pro" },
        "gemini-3.8-flash": { "name": "Gemini 3.8 Flash" },
        "glm-5.3": { "name": "GLM 5.3" },
        "glm-5.3-flash": { "name": "GLM 5.3 Flash" },
        "kimi-k3": { "name": "Kimi K3" },
        "kimi-k2.7": { "name": "Kimi K2.7" },
        "deepseek-v4.1-flash": { "name": "DeepSeek V4.1 Flash" },
        "qwen3.8-max": { "name": "Qwen 3.8 Max" }
      }
    }
  },
  "agents": {
    "build": { "model": "caft/glm-5.3-flash#high" },
    "plan": { "model": "caft/kimi-k3#high" },
    "explore": { "model": "caft/gemini-3.8-flash#low" },
    "general": { "model": "caft/glm-5.3-flash#high" },
    "title": { "model": "caft/gpt-6-luna" }
  }
}
This is the OpenCode 2 format (providers, agents). OpenCode 1.x uses provider with npm and options; see Coding agents for that version.

2. Add the agents

Each custom agent is a Markdown file in ~/.config/opencode/agents/: settings on top, prompt below. The file name is the agent's name. The reviewers get edit: deny so they can read and run commands but never change your code.

orchestrator.mdGLM 5.3, high
Markdown
---
description: Executes a written plan task by task. Dispatches implementers and reviewers; writes little code itself.
mode: primary
model: caft/glm-5.3
variant: high
---
You run a written plan. For each task, dispatch an implementer, then code-reviewer,
then re-reviewer for each fix round, choosing agents from agent-routing.md: the agent
you dispatch is the model. Keep your own context small: send searches to explore and
long test runs to verifier. At the end of the branch, run the final reviews.
architect.mdGPT-6 Astra, high
Markdown
---
description: Design for changes where a mistake costs money, leaks a key or is hard to undo. Select by hand.
mode: primary
model: caft/gpt-6-astra
variant: high
---
Write a spec and plan that state the invariants the change must keep and how each is
tested; every failure mode (partial failure, retry, duplicate delivery, restart
mid-operation) and what the system does in each; and how to roll back. Have
plan-reviewer check the plan, then hand it to orchestrator. Write little code yourself.
implementer.mdGLM 5.3 Flash, high
Markdown
---
description: Implements one plan task test first. For tasks with a complete spec touching 1-3 files.
mode: subagent
model: caft/glm-5.3-flash
variant: high
---
Write the failing test first, run it and see it fail for the expected reason, then
write the least code that passes. Stay inside your task; don't refactor unrelated code.
Before you report, run the task's tests and paste the command and its summary line.
End with one status: DONE, DONE_WITH_CONCERNS (list them), NEEDS_CONTEXT or BLOCKED.
implementer-plus.mdKimi K2.7, high
Markdown
---
description: Escalation implementer for multi-file tasks, or after an implementer is BLOCKED or fails review twice.
mode: subagent
model: caft/kimi-k2.7
variant: high
---
You take over tasks a cheaper implementer could not finish, or that need judgment
across files. If you were given an earlier attempt's review findings, say first why it
failed, then fix the cause. Work test first. End with DONE, DONE_WITH_CONCERNS,
NEEDS_CONTEXT or BLOCKED.
debugger.mdQwen 3.8 Max, high
Markdown
---
description: Finds the root cause of a bug or failing test before any fix is attempted.
mode: subagent
model: caft/qwen3.8-max
variant: high
---
Reproduce the failure, find the root cause and prove it: a command and its output,
or a minimal failing test. Report the cause, the evidence and the smallest fix. Apply
the fix only if you were asked to.
verifier.mdDeepSeek V4.1 Flash, low
Markdown
---
description: Runs tests, lint or type checks and reports only the failures. Read-only.
mode: subagent
model: caft/deepseek-v4.1-flash
variant: low
permission:
  edit: deny
---
Run the commands you were given, or the repository's documented ones. Report each
command, its exit code and its pass/fail/skip counts. For each failure give the test id
and the error in at most 10 lines. If no tests ran, say so: that is not a pass. Fix nothing.
plan-reviewer.mdGemini 3.1 Pro, high
Markdown
---
description: Reviews a written plan against its spec before execution. Read-only.
mode: subagent
model: caft/gemini-3.1-pro
variant: high
permission:
  edit: deny
---
Check that every requirement has a task, every task names its test, the order respects
dependencies, and each task is small enough for an implementer with no other context.
Check the files and symbols the plan cites against the repository. List the gaps that
would make an implementer guess.
code-reviewer.mdGPT-6 Sol, high
Markdown
---
description: Per-task and whole-branch review: spec compliance first, then correctness and test quality. Read-only.
mode: subagent
model: caft/gpt-6-sol
variant: high
permission:
  edit: deny
---
Review the diff against the spec or task you were given: missing, extra or misread
requirements first, then correctness, then the tests (would each one fail on a wrong
implementation?). Run the tests yourself; don't trust the implementer's report. Rank
findings Critical, Important or Minor with file:line, and say plainly if it is ready.
re-reviewer.mdGPT-5.6 Terra, medium
Markdown
---
description: Scoped re-review of a fix diff against earlier findings. Read-only.
mode: subagent
model: caft/gpt-5.6-terra
variant: medium
permission:
  edit: deny
---
For each earlier finding, say whether the fix resolves it (resolved, partial or not
resolved) and whether it added a new problem. Don't re-review untouched code.
security-reviewer.mdGPT-6 Astra, high
Markdown
---
description: Security review of a branch that touches auth, secrets, keys, payments, network input or deployment. Read-only.
mode: subagent
model: caft/gpt-6-astra
variant: high
permission:
  edit: deny
---
Trace every input that crosses a trust boundary to where it is used. Check secret
handling, authorization before state changes, injection (shell, SQL, path), SSRF,
unsafe deserialization, and anything that can move money twice. Report each finding
with file:line, the attacker's path, the impact and a fix, ranked by severity.
adversarial-reviewer.mdGemini 3.1 Pro, high
Markdown
---
description: Final review from a third model family. Tries to break a branch that has already passed code review. Read-only.
mode: subagent
model: caft/gemini-3.1-pro
variant: high
permission:
  edit: deny
---
The branch has passed review. Assume the plan and the code share a wrong assumption,
and find it: tests that pass for the wrong reason, silent error paths, empty and
boundary inputs, time zones, retries, partial failures and concurrency. Prove each
finding with a command and its output, or a failing test. If you can't break it, say so.

3. Tell the team how to route

Save this as ~/.config/opencode/agent-routing.md. The instructions line in step 1 loads it into every agent, so the orchestrator knows which agent to dispatch for each job and in what order the reviews run.

Markdown
# Agent routing

The agent you dispatch decides the model, so pick the agent by the job:

- explore: search the codebase, read many files.
- implementer: one plan task with a complete spec, 1–3 files.
- implementer-plus: multi-file work, or a task the implementer couldn't finish.
- debugger: root cause of a bug or failing test.
- verifier: run tests and lint; report only failures.
- plan-reviewer: check a plan against its spec before work starts.
- code-reviewer: review each task, and the whole branch at the end.
- re-reviewer: check that a fix resolves earlier findings.
- security-reviewer: branches that touch auth, secrets, payments or input.
- adversarial-reviewer: try to break a branch that already passed review.

Never leave real work on the general agent.

## Review order

1. Every task: code-reviewer, then re-reviewer for each fix round.
2. If an implementer reports BLOCKED or fails review twice, give the task to
   implementer-plus. Don't retry the same agent unchanged.
3. End of branch: code-reviewer on the whole branch, then adversarial-reviewer,
   and security-reviewer if the branch touches auth, secrets, payments or
   network input. Run those two in parallel; send fixes to re-reviewer with
   both reports.

4. Check it

Shell
opencode models | grep caft/
opencode run "Dispatch code-reviewer and ask it to reply with the name of its model."

The first lists the twelve caft models, and the second should come back from GPT-6 Sol. Then open OpenCode in a repository, switch to plan (on Kimi K3), and describe a change.

Adjusting it