Skip to content

fix(agents): ignore ACP-only streamTo on subagent sessions_spawn#65282

Closed
damselem wants to merge 2 commits into
openclaw:mainfrom
damselem:fix/sessions-spawn-streamto
Closed

fix(agents): ignore ACP-only streamTo on subagent sessions_spawn#65282
damselem wants to merge 2 commits into
openclaw:mainfrom
damselem:fix/sessions-spawn-streamto

Conversation

@damselem

Copy link
Copy Markdown
Contributor

Problem

When an agent falls back from ACP runtime to subagent runtime, it may still pass streamTo: "parent" from the original ACP request parameters. This caused sessions_spawn to return an error:

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

Fix

Treat streamTo as ACP-only: silently drop it when runtime is not ACP, instead of returning an error. The parameter is documented as ACP-only in the schema, so dropping it is correct behavior.

// Before
const streamTo = params.streamTo === "parent" ? "parent" : undefined;
// ...
if (streamTo && runtime !== "acp") return jsonResult({ status: "error", error: `streamTo is only supported for runtime=acp` });

// After
const requestedStreamTo = params.streamTo === "parent" ? "parent" : undefined;
// Some callers retain ACP-only fields when they fall back to subagent runtime.
// Treat streamTo as ACP-only and drop it silently for subagent requests.
const streamTo = runtime === "acp" ? requestedStreamTo : undefined;

Validation

Validated end-to-end on v4.11: spawned a real research subagent that ran web_search + web_fetch, completed in 67.6s with outcome.status = "ok" and valid frozenResultText JSON output.

References

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS labels Apr 12, 2026
@greptile-apps

greptile-apps Bot commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces a hard error for streamTo on non-ACP runtimes with a silent drop, fixing a regression where agents falling back from ACP to subagent runtime would fail if they still carried streamTo: \"parent\" in their parameters. The production logic change is correct and minimal.

  • The existing test 'rejects streamTo when runtime is not \"acp\"' (lines 287–305 of sessions-spawn-tool.test.ts) asserts the removed error path and will fail: it expects { status: \"error\" } and that spawnSubagentDirectMock was not called, but the new code drops streamTo silently and proceeds to call spawnSubagentDirect.

Confidence Score: 4/5

The production fix is correct, but the stale test will cause CI to fail — needs a one-line assertion update before merging.

The 2-line logic change in the source file is correct and the PR description accurately describes the fix. However, the existing test that asserted the old error behavior was not updated to match the new silent-drop contract, so CI will break on the current changeset.

src/agents/tools/sessions-spawn-tool.test.ts — the 'rejects streamTo when runtime is not acp' test needs to be updated to assert successful subagent dispatch instead of an error return.

Comments Outside Diff (1)

  1. src/agents/tools/sessions-spawn-tool.test.ts, line 287-305 (link)

    P1 Stale test will fail after this change

    This test still asserts the old error-return behavior: it expects { status: "error" } and that spawnSubagentDirectMock was not called. With the PR change, streamTo is silently dropped instead of returning an error, so spawnSubagentDirect will now be invoked — both assertions will fail and CI will break.

    The test description and assertions need to be updated to reflect the new contract: passing streamTo: "parent" with runtime: "subagent" should succeed and reach spawnSubagentDirect, without forwarding streamTo.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/agents/tools/sessions-spawn-tool.test.ts
    Line: 287-305
    
    Comment:
    **Stale test will fail after this change**
    
    This test still asserts the old error-return behavior: it expects `{ status: "error" }` and that `spawnSubagentDirectMock` was not called. With the PR change, `streamTo` is silently dropped instead of returning an error, so `spawnSubagentDirect` will now be invoked — both assertions will fail and CI will break.
    
    The test description and assertions need to be updated to reflect the new contract: passing `streamTo: "parent"` with `runtime: "subagent"` should succeed and reach `spawnSubagentDirect`, without forwarding `streamTo`.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/tools/sessions-spawn-tool.test.ts
Line: 287-305

Comment:
**Stale test will fail after this change**

This test still asserts the old error-return behavior: it expects `{ status: "error" }` and that `spawnSubagentDirectMock` was not called. With the PR change, `streamTo` is silently dropped instead of returning an error, so `spawnSubagentDirect` will now be invoked — both assertions will fail and CI will break.

The test description and assertions need to be updated to reflect the new contract: passing `streamTo: "parent"` with `runtime: "subagent"` should succeed and reach `spawnSubagentDirect`, without forwarding `streamTo`.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(agents): ignore ACP-only streamTo on..." | Re-trigger Greptile

@damselem

damselem commented Apr 12, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (was 420 commits behind). PR HEAD is now 30d3d9ad. The 2-file diff is unchanged; recent CI failures (check, checks-node-core-runtime, check-additional, etc.) were stale-base TypeScript rot in extensions/telegram, extensions/whatsapp, src/wizard/setup.ts, and src/cron/isolated-agent/* — all files this patch doesn't touch. CI should now run against a current base.

Greptile's earlier P1 about a stale test at sessions-spawn-tool.test.ts:287-305 was based on the first commit; the second commit (test(agents): update streamTo test to match new silent-drop behavior) renamed that test to 'silently drops streamTo when runtime is "subagent"' and flipped the assertions to status: "accepted" + spawnSubagentDirect called without streamTo. Only one streamTo-related test remains in the file.

@damselem
damselem force-pushed the fix/sessions-spawn-streamto branch from 412ef1f to 8ec72ac Compare April 13, 2026 18:32
@slk1061569042-lab

Copy link
Copy Markdown

Confirmed this is still reproducible on a newer local install and this PR matches the correct fix.

Fresh findings from my environment:

  • OpenClaw local install: v2026.4.12
  • Current compiled location is no longer only the older pi-embedded-* bundle. On my machine the live guard is in:
    • /opt/homebrew/lib/node_modules/openclaw/dist/openclaw-tools-CHy2rPF4.js:7544
    • /opt/homebrew/lib/node_modules/openclaw/dist/openclaw-tools-CHy2rPF4.js:7551
  • The current compiled code still effectively does:
    • const streamTo = params.streamTo === "parent" ? "parent" : void 0;
    • if (streamTo && runtime !== "acp") return ...

Observed behavior:

  • sessions_spawn(runtime="subagent") can still fail with:
    • streamTo is only supported for runtime=acp; got runtime=subagent
  • In our case this is easy to trigger when the tool-call arguments get auto-filled with ACP-style optional fields.

I also checked the current TypeScript source in src/agents/tools/sessions-spawn-tool.ts, and the fix in this PR is exactly the right direction:

  • treat streamTo as ACP-only at read time
  • silently drop it for non-ACP runtimes
  • do not hard-fail subagent requests just because callers/models supplied an ACP-only optional field

This is the behavior we want in production, because schema-following models often emit a "complete-looking" tool payload instead of a minimal one.

So from a downstream operator perspective: +1, this PR fixes a real still-active bug on current installs.

@pidgeon777

Copy link
Copy Markdown

We have locally validated this fix on top of OpenClaw v2026.4.14.

Our test flow was:

  • check out the v2026.4.14 tag
  • apply the PR change locally
  • rebuild and relink the installation
  • retest sessions_spawn(runtime="subagent") under the previously affected setup

After applying the fix, we successfully launched parallel subagent tasks using Gemini 3 Flash High and GPT-5.4. In our local validation, this removed the ACP-only streamTo failure mode described in the related reports.

Based on that result, this PR appears to be effective and was sufficient to resolve the issue in the tested v2026.4.14 environment.

Some callers retain ACP-only fields (streamTo) when falling back to subagent runtime. Silently drop streamTo for non-ACP requests instead of returning an error.

Closes openclaw#43556
Ref: PR openclaw#55483 (correct fix, closed due to unrelated scope creep)
Updated test case to reflect new behavior for runtime 'subagent'. Changed expected status from 'error' to 'accepted' and adjusted mock call expectations.
@damselem
damselem force-pushed the fix/sessions-spawn-streamto branch from 8ec72ac to 30d3d9a Compare April 15, 2026 16:00
@damselem

Copy link
Copy Markdown
Contributor Author

Triage of the 2 remaining red checks after the rebase:

1. check (Check types and lint and oxfmt)

Fails on extensions/matrix/src/matrix/sdk/crypto-bootstrap.test.ts:282 with TS2322: Type 'Mock<() => undefined>' is not assignable to type 'Mock<() => string>'. This is a main-branch regression, not a PR regression:

2. GPT-5.4 / Opus 4.6 parity gate

Fails on one scenario only, Approval turn tool followthrough, on the GPT-5.4 candidate lane (baseline 11/11, candidate 10/11). Failure mode is a 25 second gateway WS timeout during the pre-action turn, not a semantic divergence. The same scenario fails on the same lane on independent PRs that touch unrelated code:

The scenario definition at qa/scenarios/approval-turn-tool-followthrough.md tests a short approval triggering a readFile on QA_KICKOFF_TASK.md. It does not use sessions_spawn, subagents, or streamTo. Additionally, the scenarios that would regress if this patch broke subagent spawning (Subagent handoff, Subagent fanout synthesis) both pass on both lanes in this PR's run.

In short, both reds reproduce on main or on unrelated PRs and are not attributable to this change.

@clawsweeper

clawsweeper Bot commented Apr 26, 2026

Copy link
Copy Markdown
Contributor

Closing this as duplicate or superseded after Codex automated review.

Close #65282 as superseded by open PR #68397. Current main still has the reported streamTo rejection, so this is not implemented-on-main, but #68397 is the broader canonical patch for the same sessions_spawn bug because it silently strips both ACP-only fields, streamTo and resumeSessionId, for runtime=subagent and updates both regression tests.

Best possible solution:

Close #65282 as superseded and consolidate review on #68397 or an equivalent maintainer patch that keeps ACP behavior unchanged while silently ignoring ACP-only streamTo and resumeSessionId on native subagent spawns, with regression tests for both fields.

What I checked:

So I’m closing this here and keeping the remaining discussion on the canonical linked item.

Codex Review notes: model gpt-5.5, reasoning high; reviewed against d54d2d6b9b8a.

@vincentkoc

Copy link
Copy Markdown
Member

ProjectClownfish could not safely update this branch, so it opened a narrow replacement PR instead.

Replacement PR: #72331
Source PR: #65282
Contributor credit is preserved in the replacement PR body and changelog plan.

1 similar comment
@vincentkoc

Copy link
Copy Markdown
Member

ProjectClownfish could not safely update this branch, so it opened a narrow replacement PR instead.

Replacement PR: #72331
Source PR: #65282
Contributor credit is preserved in the replacement PR body and changelog plan.

@vincentkoc

Copy link
Copy Markdown
Member

ProjectClownfish could not safely update this branch, so it opened a narrow replacement PR instead.

Replacement PR: #72614
Source PR: #65282
Contributor credit is preserved in the replacement PR body and changelog plan.

@vincentkoc

Copy link
Copy Markdown
Member

ProjectClownfish could not safely update this branch, so it opened a narrow replacement PR instead.

Replacement PR: #72331
Source PR: #65282
Contributor credit is preserved in the replacement PR body and changelog plan.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: streamTo in sessions_spawn breaks subagent runtime

4 participants