Skip to content

fix(session): skip synthetic delegation nudge in subagent sessions#17210

Open
vicary wants to merge 3 commits intoanomalyco:devfrom
vicary:fix/subagent-synthetic-injection
Open

fix(session): skip synthetic delegation nudge in subagent sessions#17210
vicary wants to merge 3 commits intoanomalyco:devfrom
vicary:fix/subagent-synthetic-injection

Conversation

@vicary
Copy link

@vicary vicary commented Mar 12, 2026

Issue for this PR

Closes #17202

Type of change

  • Bug fix

What does this PR do?

When a user message contains an @agent mention, SessionPrompt.createUserMessage injects a synthetic text part instructing the model to call the task tool with that subagent. This is correct behaviour in a root session where the user is initiating a delegation.

In a child/subagent session however, the orchestrator has already written an explicit task prompt before the session starts. When the subagent processes its own message history it encounters the @agent part and the injection runs again, appending a second delegation instruction. This causes recursive nesting bias: the subagent reads its own context, sees the nudge, and attempts to spawn yet another delegation layer.

The fix is a minimal guard in the if (part.type === "agent") branch of createUserMessage:

const currentSession = await Session.get(input.sessionID)
if (currentSession.parentID) {
  return [agentPart]
}

Session.Info.parentID is already set by the orchestrator when it creates child sessions. The guard is minimal and does not affect any other code path.

How did you verify your code works?

  • Read the injection logic in packages/opencode/src/session/prompt.ts to confirm the root cause.
  • Confirmed Session.Info.parentID is populated for child sessions via packages/opencode/src/session/index.ts.
  • Built a patched binary locally (OPENCODE_VERSION=1.2.24 bun run ./packages/opencode/script/build.ts).
  • Ran a multi-agent session end-to-end: root session delegated to a subagent via @agent. Verified via DB inspection that the subagent's message history no longer contains the synthetic delegation text part.
  • Verified root-session delegation still works correctly (synthetic text still injected when parentID is absent).
  • Added two unit tests to packages/opencode/test/session/prompt.test.ts:
    • injects synthetic delegation nudge in root sessions
    • skips synthetic delegation nudge in subagent sessions
  • All 6 tests in prompt.test.ts pass (bun test ./test/session/prompt.test.ts).

Screenshots / recordings

No UI changes.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actions github-actions bot added the needs:compliance This means the issue will auto-close after 2 hours. label Mar 12, 2026
When a user message contains an @agent part, createUserMessage injects a
synthetic text part that tells the model to call the task tool with that
subagent. In a child/subagent session the orchestrator has already written
an explicit task prompt, so injecting the nudge again causes recursive
nesting bias: the subagent re-reads the @agent mention in its own context
and tries to spawn another layer of delegation.

Guard the injection behind a parentID check so only root sessions receive
the synthetic delegation instruction.

Fixes anomalyco#17202
@vicary vicary changed the title fix: skip delegation nudge in subagent sessions fix(session): skip synthetic delegation nudge in subagent sessions Mar 12, 2026
@github-actions github-actions bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Mar 12, 2026
@github-actions
Copy link
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@vicary vicary force-pushed the fix/subagent-synthetic-injection branch from 5bbdffa to ed32b28 Compare March 12, 2026 17:13
@vicary vicary force-pushed the fix/subagent-synthetic-injection branch 2 times, most recently from 5bbdffa to f76ead9 Compare March 12, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@agent tagging creates synthetic injection that breaks agent swarm

1 participant