Skip to content

sessions_spawn: streamTo schema lacks runtime=acp hint, causes 2x-token retry loop for subagent callers #69166

Description

@IsaacAPerez

Summary

When a subagent (runtime=subagent) calls sessions_spawn, the model routinely includes streamTo: "parent" in the arguments. The server correctly rejects this with:

streamTo is only supported for runtime=acp; got runtime=subagent

The model then retries without streamTo and the second call succeeds. Every subagent-to-specialist delegation costs ~2× tokens (one failed spawn + one successful).

Repro

Any depth-1 subagent that delegates to another agent via sessions_spawn with runtime="subagent" exhibits this. Observed consistently across 20+ sessions in local testing with [email protected] on gpt-5.4.

Sample toolCall args the model emits on the first attempt:

{
  "task": "",
  "runtime": "subagent",
  "agentId": "ios_agent",
  "mode": "run",
  "cleanup": "delete",
  "sandbox": "inherit",
  "streamTo": "parent",
  "lightContext": true
}

Tool result:

{"status":"error","error":"streamTo is only supported for runtime=acp; got runtime=subagent"}

The model then re-emits the same args minus streamTo and succeeds.

Root cause

In SessionsSpawnToolSchema (compiled at dist/openclaw-tools-*.js around the src/agents/tools/sessions-spawn-tool.ts region), streamTo is declared without a description:

streamTo: optionalStringEnum(SESSIONS_SPAWN_ACP_STREAM_TARGETS),

Compare to its siblings in the same schema, which both carry runtime hints:

  • resumeSessionId"…Requires runtime=\"acp\"."
  • lightContext"Only applies to runtime='subagent'."

describeSessionsSpawnTool() in tool-policy also never mentions streamTo. So from the model's vantage point it's an enum-valued "parent" field with no constraint hint — it reasonably includes it whenever streaming semantics feel relevant, even on subagent spawns.

The server-side rejection is correct (subagent spawns are fire-and-forget with push-based auto-announce; there is no bidirectional stream channel). The bug is purely that the schema fails to communicate the constraint, causing a predictable, paid-for retry on every delegation.

Proposed fix

One-line change in src/agents/tools/sessions-spawn-tool.ts:

streamTo: optionalStringEnum(SESSIONS_SPAWN_ACP_STREAM_TARGETS, {
  description: "Stream child output to parent turn-by-turn. Requires runtime=\"acp\"; omit for runtime=\"subagent\" (subagents use push-based auto-announce instead)."
}),

Optional: append a sentence to describeSessionsSpawnTool() mirroring the same constraint, and add a unit test asserting the streamTo field description contains runtime="acp" as a regression guard.

Happy to open a PR if you'd like.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions