0
Fork 0
mirror of https://github.com/obra/superpowers.git synced 2026-09-25 22:09:05 +00:00

OpenCode: Superpowers bootstrap is injected into task subagents, causing them to restart controller workflows #2160

Open
opened 2026-08-16 05:00:17 +00:00 by ray73864 · 2 comments
ray73864 commented 2026-08-16 05:00:17 +00:00 (Migrated from github.com)

Summary

The OpenCode Superpowers plugin injects the complete using-superpowers
bootstrap into task subagent sessions as well as the primary session.

using-superpowers contains a <SUBAGENT-STOP> instruction telling a
dispatched subagent to ignore the skill, but this relies on the model correctly
recognising and prioritising that instruction.

In practice this is not reliable.

I have reproduced a worker subagent receiving an already-approved, atomic
implementation task and then invoking brainstorming instead of executing the
task. The worker subsequently started a new design/approval cycle.

Environment

  • OpenCode 1.18.18
  • Superpowers installed through the OpenCode git plugin
  • macOS
  • Primary agent: Qwen3.6-35B-A3B
  • Worker subagent: Muse-Glimmer-30B
  • Local OpenAI-compatible model provider via llama.cpp

This is not specific to the models above; the issue is that correct behaviour
currently depends on model interpretation of <SUBAGENT-STOP>.

Reproduction

  1. Configure an OpenCode primary agent and a separate coder subagent.
  2. Give the primary agent a bounded implementation task.
  3. Have the primary dispatch the coder through OpenCode's task/subagent
    mechanism.
  4. Observe the worker's initial context/reasoning.

The worker receives the Superpowers bootstrap containing both:

  • the instruction to skip using-superpowers when dispatched as a subagent;
  • the much stronger general instructions requiring applicable skills to be
    invoked before any action.

In my reproduction, the worker reasoned that implementation implied
brainstorming / test-driven-development, invoked brainstorming, and began
another design/approval cycle instead of performing the bounded task.

The parent had already completed process selection and explicitly authorised
the implementation.

Why the existing SUBAGENT-STOP is insufficient

The current OpenCode plugin injects the bootstrap through:

experimental.chat.messages.transform

and does so for the first user message without structurally distinguishing a
top-level session from a task subagent.

This leaves enforcement to the LLM:

  1. recognise that it is a dispatched subagent;
  2. notice <SUBAGENT-STOP>;
  3. give that instruction precedence over the subsequent strongly-worded
    skill-first instructions.

That works for some models but demonstrably fails for others.

OpenCode exposes enough information to avoid model-dependent detection

OpenCode UserMessage metadata includes:

  • sessionID
  • agent

Task subagents are also created as child sessions with:

parentID: ctx.sessionID

Therefore the OpenCode adapter should be able to determine structurally whether
the current session is a child/task session rather than asking the model to
infer it.

Expected behaviour

For a task subagent executing an already-bounded assignment, Superpowers should
not inject the controller/bootstrap workflow that can restart brainstorming,
planning, approval, or other parent-level process selection.

The worker should still retain access to ordinary skills so that appropriate
execution-oriented skills can be explicitly selected or used.

This is important: simply denying the skill tool to worker agents is not a
good general workaround because useful implementation skills may be needed by
workers.

Suggested direction

In the OpenCode plugin, detect whether the message belongs to a child session
before prepending the using-superpowers bootstrap.

Conceptually:

  • obtain the current sessionID from the message;
  • inspect that session using the OpenCode client;
  • if it has a parentID, do not inject the controller bootstrap;
  • otherwise inject it normally.

Alternatively, inject a purpose-built worker bootstrap for child sessions
rather than the full using-superpowers controller bootstrap.

The important part is that subagent detection should be structural rather than
dependent on the model obeying <SUBAGENT-STOP>.

Current workaround

A local modification to the OpenCode Superpowers plugin can skip bootstrap
injection for child sessions, but this is not a sustainable workaround because
the cached plugin is replaced by normal Superpowers updates.

## Summary The OpenCode Superpowers plugin injects the complete `using-superpowers` bootstrap into task subagent sessions as well as the primary session. `using-superpowers` contains a `<SUBAGENT-STOP>` instruction telling a dispatched subagent to ignore the skill, but this relies on the model correctly recognising and prioritising that instruction. In practice this is not reliable. I have reproduced a worker subagent receiving an already-approved, atomic implementation task and then invoking `brainstorming` instead of executing the task. The worker subsequently started a new design/approval cycle. ## Environment - OpenCode 1.18.18 - Superpowers installed through the OpenCode git plugin - macOS - Primary agent: Qwen3.6-35B-A3B - Worker subagent: Muse-Glimmer-30B - Local OpenAI-compatible model provider via llama.cpp This is not specific to the models above; the issue is that correct behaviour currently depends on model interpretation of `<SUBAGENT-STOP>`. ## Reproduction 1. Configure an OpenCode primary agent and a separate coder subagent. 2. Give the primary agent a bounded implementation task. 3. Have the primary dispatch the coder through OpenCode's task/subagent mechanism. 4. Observe the worker's initial context/reasoning. The worker receives the Superpowers bootstrap containing both: - the instruction to skip `using-superpowers` when dispatched as a subagent; - the much stronger general instructions requiring applicable skills to be invoked before any action. In my reproduction, the worker reasoned that implementation implied `brainstorming` / `test-driven-development`, invoked brainstorming, and began another design/approval cycle instead of performing the bounded task. The parent had already completed process selection and explicitly authorised the implementation. ## Why the existing SUBAGENT-STOP is insufficient The current OpenCode plugin injects the bootstrap through: `experimental.chat.messages.transform` and does so for the first user message without structurally distinguishing a top-level session from a task subagent. This leaves enforcement to the LLM: 1. recognise that it is a dispatched subagent; 2. notice `<SUBAGENT-STOP>`; 3. give that instruction precedence over the subsequent strongly-worded skill-first instructions. That works for some models but demonstrably fails for others. ## OpenCode exposes enough information to avoid model-dependent detection OpenCode `UserMessage` metadata includes: - `sessionID` - `agent` Task subagents are also created as child sessions with: `parentID: ctx.sessionID` Therefore the OpenCode adapter should be able to determine structurally whether the current session is a child/task session rather than asking the model to infer it. ## Expected behaviour For a task subagent executing an already-bounded assignment, Superpowers should not inject the controller/bootstrap workflow that can restart brainstorming, planning, approval, or other parent-level process selection. The worker should still retain access to ordinary skills so that appropriate execution-oriented skills can be explicitly selected or used. This is important: simply denying the `skill` tool to worker agents is not a good general workaround because useful implementation skills may be needed by workers. ## Suggested direction In the OpenCode plugin, detect whether the message belongs to a child session before prepending the `using-superpowers` bootstrap. Conceptually: - obtain the current `sessionID` from the message; - inspect that session using the OpenCode client; - if it has a `parentID`, do not inject the controller bootstrap; - otherwise inject it normally. Alternatively, inject a purpose-built worker bootstrap for child sessions rather than the full `using-superpowers` controller bootstrap. The important part is that subagent detection should be structural rather than dependent on the model obeying `<SUBAGENT-STOP>`. ## Current workaround A local modification to the OpenCode Superpowers plugin can skip bootstrap injection for child sessions, but this is not a sustainable workaround because the cached plugin is replaced by normal Superpowers updates.
arittr commented 2026-08-17 23:42:51 +00:00 (Migrated from github.com)

Confirmed — the OpenCode plugin injects the bootstrap into every session, including task children, which is what restarts controller workflows inside subagents. Fix queued on our side, coordinated with the v2 plugin work in #2106. Thanks for the report.

Confirmed — the OpenCode plugin injects the bootstrap into every session, including task children, which is what restarts controller workflows inside subagents. Fix queued on our side, coordinated with the v2 plugin work in #2106. Thanks for the report.
arittr commented 2026-08-17 23:42:51 +00:00 (Migrated from github.com)

Confirmed — the OpenCode plugin injects the bootstrap into every session, including task children, which is what restarts controller workflows inside subagents. Fix queued on our side, coordinated with the v2 plugin work in #2106. Thanks for the report.

Confirmed — the OpenCode plugin injects the bootstrap into every session, including task children, which is what restarts controller workflows inside subagents. Fix queued on our side, coordinated with the v2 plugin work in #2106. Thanks for the report.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
skills/obra-superpowers#2160
No description provided.