anomalyco / anomalyco/opencode
[FEATURE]: Expose delegation metadata (e.g. plugin-assigned category/label) on subagent sessions and message events — plugins cannot surface it anywhere in the runtime UI
@rekram1-node is already working on this.
Since Aug 22, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Description
OpenCode's plugin ecosystem (orchestration plugins like oh-my-openagent, 68k stars) spawns subagent sessions via the SDK with delegation metadata — most importantly a category that selects a category-optimized model profile. That metadata is completely invisible in the UI at runtime, because OpenCode's event stream and session model provide no channel for a plugin to surface it.
This was originally reported from the plugin side as code-yeongyu/oh-my-openagent#6854: "task(category=...) category is invisible in TUI — delegated subagents always labeled 'Sisyphus-Junior', making it look like the orchestrator skipped the category". After digging through both codebases, the root cause is on the OpenCode side, not the plugin side.
The problem in detail
When a plugin orchestrator delegates task(category="quick", ...), OpenCode spawns a child session. The runtime status line and message headers show only:
▣ Sisyphus-Junior · deepseek-v4-flash · 11.4s
The category (quick) — which determined the model, reasoning effort, and agent profile — appears nowhere. This is actively misleading: after plugins migrated category→model mappings to plain model IDs, multiple categories resolve to the same model as the default agent, so a categorized delegation is visually indistinguishable from a category-less one. Users cannot audit which model profile a delegation actually used without opening the SQLite DB and inspecting the parent's task tool-call input.
Why plugins cannot fix this themselves (root cause on OpenCode side)
We traced all three possible injection points; each is closed:
-
session.createbody only acceptsparentID+title(SDKtypes.gen.d.ts). There is nometadata, noagent, no custom display field. A plugin's only channel is the session title, which shows up in session lists/history but not in the runtime status line or message headers. -
The runtime status line / agent header is rendered from event
info(info.agent,info.modelID,info.variant— e.g.EventMessageUpdatedproperties).EventMessagePartUpdatedproperties contain onlypart+delta; no session title, no category, no delegation metadata. A plugin-side renderer literally has no data to work with. -
info.agentoriginates from the prompt dispatchagentparameter and must exactly match a registered agent name. A plugin cannot pass a display-suffixed name like"Sisyphus-Junior (quick)"— the server rejects unknown agent names (Agent "..." not found), and oh-my-openagent explicitly strips invisible characters from agent names before dispatch (stripInvisibleAgentCharacters) for this reason.
So the only workaround plugins have today is embedding the category into the session title (oh-my-openagent now does "<description> (@<agent> · <category> subagent)" — see code-yeongyu/oh-my-openagent#6854 and the linked PR), which covers the session list but cannot cover the live status line or per-message agent headers, because those never read the title.
Proposed solution (any one of these unblocks the ecosystem)
- Option A (smallest): Add an optional
agentLabel/displayName(or free-formmetadataobject) to thesession.createbody, propagated intosession.infoand included inEventMessageUpdated/EventMessagePartUpdatedinfo. Plugins could then setdisplayName: "Sisyphus-Junior · quick"at spawn time, and every renderer (TUI, desktop,opencode runCLI) that already printsinfo.agentcould print it alongside. - Option B: Include
session.title(or the full session info) in the message event payloads, so downstream renderers can correlate a message with its session and derive the label. - Option C: Allow the
agentfield on prompt dispatch to carry a display suffix (e.g.agent: "sisyphus-junior [quick]", bracketed suffix ignored for agent resolution) — this matches how the status line already rendersvariantin parentheses and requires no schema additions.
Why this matters
- Auditability: delegation category determines cost and capability (a
deepvsquickdelegation can differ 6x in token price). Users currently have no way to see it at a glance. - Plugin ecosystem parity: Claude Code and Codex-style harnesses surface delegation metadata in their UIs; OpenCode plugins currently cannot, by construction.
- The plugin side is already done: oh-my-openagent has merged the title-based half of this (session list visibility). The remaining half — live status line / message headers — is blocked purely on OpenCode exposing the data.
Happy to provide reproduction steps, SDK traces, or test a PR branch.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.