My Opinionated Coding Agent Workflow
Published on November 14, 2026 · 14 min read
Building an adaptive, cost-aware multi-agent development workflow with OpenCode.
I started configuring my coding agent by asking which model to use. I wanted the most capable model for difficult work, but paying for it to search for a file seemed wasteful.
Choosing a cheaper model didn’t settle the question either. If it needed several attempts and more help from me, the whole task could cost more.
I’m building my workflow around OpenCode. I use separate agents for investigation, testing, and review, and tev1 runs locally and picks the starting orchestrator. Saved task notes and cache-aware session management are parts I want to add.
Finding where an HTTP response is built mostly requires searching and reading code. Adding a validation rule means following an existing pattern. Changing payment retries requires understanding what happens when the same request arrives twice, including after a failure.
I don’t want to spend the same amount of reasoning and review on all of them. I also don’t want to save on the first call only to spend more on retries and corrections.
The October 2026 Artificial Analysis Intelligence Index v5 reports these results at maximum reasoning effort:
| Model | Cost per benchmark task |
|---|---|
| Claude Opus 5.5 | $10.04 |
| GPT-6.1 Sol | $1.27 |
| GPT-6.1 Terra | $0.96 |
Source: Artificial Analysis, 27 October 2026. Cost per benchmark task at maximum reasoning effort.
The same source scores Sol at 55 and Opus at 58. Sol costs about an eighth as much per benchmark task, which makes it worth trying as the agent that manages the work.
The Index includes tasks other than coding, and the reasoning setting affects both scores and cost. I use these results to choose models to try, then judge them on work in my own repositories.
Giving each agent a focused job
OpenCode agents can have separate instructions, models, and permissions. The primary agent owns the task. Subagents work in separate conversations and return their findings.
Suppose I’m investigating a bug involving transaction status. I can give Explore a question like this:
Find where transaction status changes are saved. Identify the rules those changes must follow, and return references to the relevant files.
The main agent gets the findings without keeping every failed search and tool response in its own conversation. It can still read the referenced code to check the answer.
These are the roles I use:
| Agent | Responsibility | Preferred model |
|---|---|---|
| Orchestrator | Owns the task and coordinates work | Terra 6.1, Sol 6.1, or Opus |
| Explore | Investigates the repository and gathers evidence | Luna or Haiku |
| Tester | Independently verifies changes and tests | Haiku or Luna |
| Judge | Reviews plans and results against requirements | Sol or Opus |
| Explainer | Explains code, decisions, and findings | Sonnet |
The Orchestrator calls specialists as needed.
The Orchestrator is the main agent. I use Terra for small, clearly scoped tasks, Sol for broader changes and debugging, and Opus for demanding work or a different model family. The task can start with any of them.
I don’t require every task to visit every specialist. A small change may need direct implementation and a test. An unfamiliar repository may need Explore first. The Orchestrator should have a specific question before calling another agent.
I’m experimenting with a local decision model, tev1, to recommend a starting Orchestrator and workflow.
This is routing: deciding which agent should handle a request. The local model considers the kind of work and its likely risk, then recommends where to start. It doesn’t implement the change.
For example, a validation change might look small until the agent finds that several services share the same data model. The Orchestrator should be able to choose a stronger model or request review at that point.
I want the starting choice to be fast and cheap, which is why I’m trying a local router.
A second opinion
For a payment retry bug, an agent might notice a possible race in a handler and change the code. Before accepting that fix, I want to know what should happen when a request is retried. That rule is the idempotency contract: the defined behaviour for repeated requests, so the same payment isn’t processed again.
The investigation should identify where the payment is created and saved. It should check database uniqueness rules and existing retry tests. Only then can the agent explain how its change addresses the failure.
I call this Goal → Evidence → Change.
For the payment example, retry checks feed back into the investigation.
A comment says what someone intended. Code shows current behaviour. Tests check particular cases. A specification states the required behaviour. The agent needs to distinguish these sources, especially when they disagree.
For a small fix, file references and test results may be enough. For a risky change, I also want the assumptions and unchecked cases recorded. This builds on my earlier approach to specifications and validation.
The Orchestrator gives the Judge the original task and the conditions for accepting it, along with the proposed plan or finished change. The Judge can inspect the repository itself.
That gives it more to work with than the Orchestrator’s account of why its own solution is correct.
My preferred pairing is:
| Orchestrator | Judge |
|---|---|
| Terra 6.1 | Sol 6.1 |
| Sol 6.1 | Opus |
| Opus | Sol 6.1 |
Terra can get help from Sol. Sol and Opus review each other’s work. I like having another model family look at the result.
A large mechanical refactoring may be easy to check. Three lines that decide who can access an account may need much more care. I consider both how hard a change is to understand and the harm it could cause.
Before implementation: review complex or uncertain plans.
After implementation: verify the change, then review critical or complex results.
I want findings that point to a problem and its evidence. I also limit review attempts: if the agents keep disagreeing, they should stop and ask me.
Context has a cost
A long session keeps failed searches and old plans alongside useful findings. Later requests may send all of that history again.
If several requests start with the same text, the provider may be able to reuse work from the earlier request. That shared beginning is the prompt prefix. Prompt caching can make repeated input cheaper and faster.
The Anthropic and OpenAI documentation describe different cache lifetimes. These are the published options as of November 2026. TTL means time to live: how long a cache entry remains eligible for reuse.
| Provider and model family | Relevant cache behaviour |
|---|---|
| Anthropic | Five-minute default cache, optional one-hour TTL |
| OpenAI, GPT-5.6 and later | Thirty-minute default; optional twelve-hour minimum lifetime in the Responses API |
| OpenAI, earlier models | Model- and configuration-dependent retention |
The Anthropic pricing table lists 1.25× writes for five minutes and 2× for one hour. Reads usually cost 0.1×, while Opus 5.5 and Sonnet 5.5 use 0.05×. OpenAI’s caching rates list 1.25× writes for thirty minutes and 0.05× reads for GPT-6.1 Sol and Terra.
Here is how growth and caching work together. Suppose there are n requests, each adding k tokens of history. Each request writes its new tokens at 1.25× the normal input rate and reads all earlier tokens at r times that rate. I’ll use k = 5,000, n = 10, and r = 0.05.
To compare costs without choosing a dollar price, I use normal-rate input-token equivalents. Processing one uncached input token costs one unit; writing it to the cache costs 1.25 units, and reading it costs 0.05 units.
Uncached: k × n(n + 1) / 2
= 5,000 × 55
= 275,000
Cached: k × [1.25n + r × n(n - 1) / 2]
= 5,000 × [12.5 + 0.05 × 45]
= 73,750That’s about 3.7× cheaper. The cached cost still grows quadratically: the repeated reads have a smaller coefficient, while the new cache writes add a linear term.
Now suppose I step away and the cache expires before request 6. That request has 25k of earlier history and 5k of new content. Instead of reading the earlier history cheaply, it writes the whole 30k again:
Request 6 normally: 1.25 × 5,000 + 0.05 × 25,000 = 7,500
Request 6 after expiry: 1.25 × 30,000 = 37,500
Extra cost: 37,500 - 7,500 = 30,000
Total with one expiry: 73,750 + 30,000 = 103,750 unitsOne idle gap adds four times the usual cost of request 6. Later requests reuse the new cache entry, but the extra write remains part of the session’s total.
Calculated example: 5k new tokens per request, 1.25× writes, 0.05× reads, and a single TTL for the whole prefix. Earlier history stays unchanged; all of it is reused except for one expiry before request 6 in the third line. No output tokens or compaction. The vertical axis shows cost equivalents, not raw token counts.
Compaction replaces earlier conversation history with a summary. It can also break prefix reuse and require new cache writes, although the cost depends on how much the summary changes and how long it is. A summary can lose a detail and cause another search later, too.
I currently compact at about 150,000 tokens, which gives me room for longer investigations without keeping the whole conversation forever. I leave space within the model’s context window for tool results, reasoning, and its answer. The cost of rewriting context is one reason I don’t compact more often.
Saving enough to resume the work
When I return after stepping away, I want to see what is done and what needs to happen next. I want to save a handoff: task notes that survive outside the conversation.
The expiry example is why I’m considering an inactivity trigger for the session manager. For Anthropic’s default cache, that means watching a five-minute window. The timer would use the provider’s rules and the last request that used the cache.
For example, Anthropic measures TTL from the start of a request that writes or reads the entry. If a response takes four minutes, much of a five-minute window has already passed by the time I see the answer.
The session manager could warn me before estimated expiry and save the current task state if I remain away:
The session manager I want to build: save task notes while I’m away and read them when I return.
A handoff should capture:
- The objective and acceptance criteria.
- Completed work and important decisions, with supporting evidence.
- Modified files, the relevant revision, and uncommitted work.
- Tests performed and their results.
- Unresolved issues and the next recommended action.
When I resume, the agent must check the repository against those notes. Files may have changed while it was idle.
It can then decide whether to continue the conversation or start from the handoff, based on the context still worth keeping.
Following the money
My preferred status bar shows estimated session, daily, and monthly spending. The task total needs to include subagents and retries as well as the primary Orchestrator.
I also want to see which agent spent the money. Expensive exploration could mean an unfamiliar task or duplicated searches. For the Judge, I want to know whether its review led to a useful correction.
For now, I want to see and manage spending rather than enforce a hard cap. A status bar showing estimated costs would let me do that without opening a provider dashboard.
Once I have enough session data, I want a command that recommends configuration changes. I think of it as a configuration doctor.
If Terra regularly needs Sol to finish a certain kind of task, starting on Sol may save work. If earlier compaction leads to repeated searches, the smaller prompts may not be cheaper overall. Reviews that rarely catch important problems in low-risk tasks are another cost to examine.
| Metric | Why it matters |
|---|---|
| Cost per completed task | Overall spending efficiency |
| Task completion time | Development time, including coordination |
| Retry and correction rate | Reliability |
| Cache hit rate | Context reuse efficiency |
| Compaction frequency | Context-management overhead |
| Review findings | Evidence of review value |
| Human intervention | Supervision required |
I need to compare similar tasks. Fixing a typo and changing payment recovery shouldn’t count as equivalent completed work. Model versions and repository changes can also affect the results.
The doctor would show the data behind each suggestion and leave the decision to me.
Keeping control
Blocking a web-fetch tool is not enough if an agent can run curl from the shell. A dependency’s install script can make network requests too.
My preferred policy blocks network access unless a destination is approved. The execution environment must enforce it for every tool and subprocess. Instructions asking the model to avoid a website cannot do that.
One network policy covers the agent’s tools and every program they launch.
I want temporary approvals to be narrow and recorded. The router chooses agents; it doesn’t change these permissions.
With those boundaries in place, my next step is to compare the workflow with simpler options:
- Fixed-model orchestration versus adaptive routing.
- Conditional review versus universal review, within appropriate safety constraints.
- My compaction settings versus provider defaults.
- Selective delegation versus direct investigation.
- Existing-session continuation versus reconstruction from a handoff.
For those comparisons, I need to record corrections and missed requirements alongside cost and elapsed time. Lower token use alone won’t tell me whether the work improved.
I’m interested in which choices save me work, and where I still need to step in. That’s how I expect to find the right mix of models, memory, and review for the way I develop software.