Why OpenCode Subagents Feel Slower: A Four-Platform Architecture Comparison

Background
Every task in my workflow runs a local subagent code review before merge and push. After a few hundred iterations of that loop, one pattern became impossible to ignore: the same review delegation took noticeably longer on OpenCode than on Claude Code, CodeBuddy, or TRAE.
The limits of that observation matter, so let me state them up front. I never ran a timing harness. I could not identify which step was slow. What I had was a consistent impression — which is a question, not a conclusion.
The only honest way forward was to read all four platforms’ official subagent documentation side by side and line the definitions up.
The architectural question
Does a subagent run in a fresh child session, or in a context window inside the main session?
Nearly everything else — startup cost, isolation strength, permission model — follows from how each vendor answered this one question.
OpenCode: a new session every time
An agent declared mode: subagent runs only in a child session, invoked through the subagent tool, with fresh context.
The permission model is where this choice is committed. From the permissions documentation: a custom subagent uses its own permissions, “not a subset of its parent’s.” The parent separately requires an explicit subagent permission before it can launch anything.
{
"agents": {
"orchestrator": {
"permissions": [
{ "action": "subagent", "resource": "*", "effect": "deny" },
{ "action": "subagent", "resource": "general", "effect": "allow" }
]
},
"auditor": {
"mode": "subagent",
"permissions": [{ "action": "edit", "resource": "*", "effect": "deny" }]
}
}
}
Permission rules are ordered and the last matching rule wins, so a broad deny followed by a narrow allow is the idiomatic shape.
Two details worth knowing: V2 ships only general and explore as subagent-mode built-ins — the documentation specifically notes there is no built-in scout in V2 — and general ships with launching subagents denied.
Claude Code: same session, separate context
The documentation is unusually direct: “Subagents work within a single session.” Each subagent still gets its own context window and its own system prompt, but no new session is opened.
Permissions inherit the parent conversation by default; hard repository isolation is opt-in via isolation: worktree.
It also trims the startup path deliberately. The built-in Explore and Plan agents skip CLAUDE.md files and the git status snapshot by default.
There is a trap worth flagging: omitClaudeMd disables CLAUDE.md, but it does not disable the git snapshot. The docs are unambiguous — “You can’t change which subagents receive git status. Only Explore and Plan skip it.”
Quotas are documented too: nesting defaults to 3 layers (CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH), and 20 concurrent subagents per session (CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS), with no cap on total spawns within a session.
CodeBuddy: separate context, explicit quotas
An independent context window, with the most precisely documented limits of the four:
| Limit | Default | Environment variable |
|---|---|---|
| Nesting depth | 5 levels | not configurable |
| Concurrent subagents | 20 per session tree | CODEBUDDY_CODE_MAX_CONCURRENT_SUBAGENTS |
| Spawns per session | 200 | CODEBUDDY_CODE_MAX_SUBAGENTS_PER_SESSION |
Its built-in Explore agent ships with a lite model tier, and MCP tools default to deferred loading — the model discovers tools via ToolSearch before invoking them.
One footgun: omitting the tools field inherits every tool available to the main thread, MCP tools included. Minimum privilege requires an explicit allowlist.
MCP declarations come in two forms, and the difference is real: a string reference borrows an already-connected global server and does not close it, while an inline definition is created for that subagent’s session only and closed when it finishes.
TRAE: separate context, least freedom
Also an independent context window, defined in Markdown, with intermediate reasoning kept out of the main Agent’s conversation history.
Two constraints stand out: only the built-in “Agent” can invoke Subagents, and the model field accepts only TRAE’s built-in models.
Side-by-side
| Dimension | OpenCode | Claude Code | CodeBuddy | TRAE |
|---|---|---|---|---|
| Runtime model | Fresh child session | Context window in main session | Separate context window | Separate context window |
| Permissions | Fully independent, not a parent subset | Inherits parent, permissionMode overrides |
Inherits all tools if tools omitted |
tools/disallowedTools allowlist |
| Startup context | Fresh context + own permissions and tools | System prompt + CLAUDE.md + git snapshot | System prompt; MEMORY.md if memory enabled |
System prompt |
| Context switches | None (child session is always fresh) | omitClaudeMd (cannot disable git snapshot) |
None | None |
| Nesting limit | general cannot relaunch subagents |
3 layers by default | 5 layers max | Not documented separately |
| Concurrency / budget | Not documented separately | 20 concurrent, no total cap | 20 concurrent / 200 spawns | Not documented separately |
| Forced light path | Command subagent: false |
Light by default | Built-in light Explore |
None |
“Not documented separately” means the vendor’s documentation has no dedicated entry — not that the capability is absent.
The latency cost every vendor documents
The genuinely surprising finding was that all four vendors acknowledge this cost. I had assumed I was describing an OpenCode quirk; I was describing the category.
Claude Code, in its guidance on when to prefer the main conversation:
Latency matters. A subagent that isn’t a fork starts fresh and may need time to gather context.
CodeBuddy, under Performance Considerations:
Sub-agents start from a clean state each invocation and may add latency as they gather context needed to work effectively.
Starting from a clean state on every invocation is the shared design. OpenCode simply defaults to the heavier end of the spectrum.
One documented path is cheaper than a fresh subagent: Claude Code’s fork. A fork inherits the whole conversation, and because its system prompt and tool definitions are identical to the parent’s, its first request reuses the parent’s prompt cache — the documentation states that “a fork costs less than a fresh subagent” for tasks needing the same context.
The subagent tri-state
OpenCode’s subagent field on a command is frequently misread as a performance flag. It is the opposite.
| Value | Behaviour |
|---|---|
true |
Always spawn a child session |
false |
Always stay in the current session |
| omitted | Spawn a child only if the selected agent is mode: subagent |
The gap between true and false is exactly the cost of full session creation. Background execution removes blocking — it does not make startup cheaper.
Recommendation
Classify by task risk rather than migrating tools.
Low-risk, read-only work — grep, summaries, quick lookups — gains nothing from a hard isolation boundary. Use subagent: false and skip the child session.
Privileged work — untrusted repositories, risky file operations, anything needing an independent audit trail — genuinely benefits from what OpenCode is paying for. Keep the default.
Several additional levers are documented: trim the tool pool per agent (MCP tools themselves consume context), assign cheaper models to exploration tasks, prefer built-in lightweight agents over custom ones, and consider Claude Code’s fork when a task needs the same background repeatedly.
What I still don’t know
I have no timing data, and any number I invented would be fiction. Two gaps stood out:
MCP connection cost is described only in scattered fragments across all four docs. CodeBuddy’s private inline MCP servers are created on subagent start and closed on finish — that appears expensive per invocation, but it is unmeasured.
Behaviour under CI is unaddressed here. Interactive sessions surface permission prompts as they arise; automated contexts cannot answer them, and I did not work through how these models degrade when nobody is available to approve.