Skip to content

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

Closed
Mintalix wants to merge 12 commits into
openclaw:mainfrom
Mintalix:codex/fix-sessions-tool-validation
Closed

fix(agents): ignore ACP-only streamTo on subagent sessions_spawn#55483
Mintalix wants to merge 12 commits into
openclaw:mainfrom
Mintalix:codex/fix-sessions-tool-validation

Conversation

@Mintalix

@Mintalix Mintalix commented Mar 27, 2026

Copy link
Copy Markdown

Summary

  • Problem: some sessions_spawn callers retain streamTo: "parent" even when the effective runtime is subagent, so the tool rejects an otherwise valid subagent spawn at the entrypoint.
  • Why it matters: this makes sessions_spawn fail for upstream callers that automatically attach ACP-only fields, even though subagent runtime never consumes streamTo.
  • What changed: sessions_spawn now treats streamTo as ACP-only, forwards it only for runtime="acp", and ignores it for subagent requests. Added regression tests for explicit and implicit subagent runtime.
  • What did NOT change (scope boundary): ACP streamTo="parent" behavior is unchanged, and resumeSessionId / ACP-only validation still stays strict.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • API / contracts
  • Auth / tokens
  • Memory / storage
  • Integrations
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Root Cause / Regression History (if applicable)

  • Root cause: src/agents/tools/sessions-spawn-tool.ts validated streamTo before dispatch and rejected any non-ACP runtime, even though only ACP runtime consumes streamTo.
  • Missing detection / guardrail: there was no regression test for callers that carry ACP-only params into subagent requests.
  • Prior context (git blame, prior PR, issue, or refactor if known): streamTo is ACP-only and is only used in src/agents/acp-spawn.ts.
  • Why this regressed now: upstream callers can retain streamTo while switching or defaulting to subagent runtime, which turns a recoverable extra param into a hard failure.
  • If unknown, what was ruled out: ruled out changes in acp-spawn.ts; ACP handling remains unchanged.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/agents/tools/sessions-spawn-tool.test.ts
  • Scenario the test should lock in: subagent spawns ignore streamTo when runtime is explicitly subagent and when runtime is omitted and defaults to subagent.
  • Why this is the smallest reliable guardrail: the regression is at the tool entrypoint before ACP/subagent dispatch, so the tool unit test is the narrowest place that proves the contract.
  • Existing test that already covers this (if any): ACP streamTo="parent" behavior is already covered in src/agents/acp-spawn.test.ts.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

Previously, sessions_spawn returned an error when a subagent request included streamTo. Now it ignores streamTo for subagent requests and continues the spawn.

Diagram (if applicable)

Before:
[sessions_spawn runtime=subagent + streamTo=parent] -> [entry validation] -> [error]

After:
[sessions_spawn runtime=subagent + streamTo=parent] -> [drop ACP-only field] -> [subagent spawn succeeds]

Copilot AI review requested due to automatic review settings March 27, 2026 02:14
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S labels Mar 27, 2026
@greptile-apps

greptile-apps Bot commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a correctness bug in sessions_spawn where callers that retain ACP-only fields (specifically streamTo: "parent") while targeting subagent runtime would receive a hard error instead of a successful spawn. The fix is minimal and well-scoped: streamTo is now parsed into a requestedStreamTo intermediate and then conditionally forwarded only when runtime === "acp", making it silently dropped for subagent requests. The resumeSessionId guard (which is semantically different — resuming a session without ACP is genuinely invalid) is left untouched, preserving existing strict validation where it matters.\n\n- Two regression tests lock in the new contract: one for runtime="subagent" explicit and one for omitted runtime (defaulting to subagent).\n- ACP streamTo forwarding is unaffected; the existing ACP test at line 116 still passes streamTo: "parent" and expects it through to spawnAcpDirect.\n- spawnSubagentDirect never accepted streamTo in its parameter object, so the field was already not forwarded; the real improvement is that the tool no longer short-circuits with an error before reaching the dispatch.

Confidence Score: 5/5

Safe to merge — targeted one-line logic change with full regression test coverage and no impact on ACP behavior.

The change is minimal (one conditional assignment replaces a rejection guard), the old behavior for ACP is provably unchanged (the ternary forwards requestedStreamTo when runtime === "acp"), the subagent path never consumed streamTo anyway, and two new tests directly lock in the fixed contract. No other call sites are affected.

No files require special attention.

Important Files Changed

Filename Overview
src/agents/tools/sessions-spawn-tool.ts Replaces the hard rejection of streamTo on non-ACP runtimes with a silent drop: streamTo is now conditionally forwarded only when runtime === "acp". The removed guard and the new two-step parse are both correct.
src/agents/tools/sessions-spawn-tool.test.ts Old error-expectation test replaced with two new passing tests: explicit runtime="subagent" and omitted runtime both succeed when streamTo is present, and verify spawnSubagentDirect is called without the field.

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes sessions_spawn entrypoint validation so ACP-only streamTo does not cause otherwise-valid subagent spawns to fail, improving compatibility with upstream callers that may carry ACP-only fields.

Changes:

  • Treat streamTo as ACP-only: forward it only when runtime="acp", otherwise ignore it.
  • Remove the prior rejection of streamTo when runtime is not ACP.
  • Add regression tests covering explicit and default (omitted) subagent runtime with streamTo present.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/agents/tools/sessions-spawn-tool.ts Drops streamTo for subagent runtime and preserves ACP forwarding behavior.
src/agents/tools/sessions-spawn-tool.test.ts Adds tests ensuring subagent spawns ignore streamTo while ACP behavior remains covered elsewhere.

Comment on lines +108 to +111
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 for subagent requests.
const streamTo = runtime === "acp" ? requestedStreamTo : undefined;

Copilot AI Mar 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

streamTo is now treated as ACP-only in the implementation, but the tool schema doesn’t communicate that to callers (unlike resumeSessionId, which has a description noting runtime="acp"). Consider adding a description to the streamTo schema property stating it’s only used for runtime="acp" and ignored for subagent spawns to prevent API confusion.

Copilot uses AI. Check for mistakes.
@vincentkoc

Copy link
Copy Markdown
Member

Re-checked against current origin/main on 2026-03-29. This still looks clean and mergeable. sessions-spawn-tool.ts continues to reject ACP-only streamTo when the effective runtime is subagent, so the original regression remains present on current main.

vincentkoc and others added 8 commits March 29, 2026 01:11
Remove memory_search and memory_get from SUBAGENT_TOOL_DENY_ALWAYS.

These are read-only tools with no side effects that are essential for
multi-agent setups relying on shared memory for context retrieval.

Rationale:
- Read-only tools (memory_search, memory_get) have no side effects and
  cannot modify state, send messages, or affect external systems
- Other read-only tools (read, web_search, web_fetch) are already
  available to sub-agents by default
- Multi-agent deployments with shared knowledge depend on memory tools
  for context retrieval
- The workaround (tools.subagents.tools.alsoAllow) works but requires
  manual configuration that contradicts memorySearch.enabled: true

Fixes openclaw#55385
@vincentkoc
vincentkoc requested a review from a team as a code owner March 29, 2026 08:32
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: bluebubbles Channel integration: bluebubbles channel: discord Channel integration: discord channel: googlechat Channel integration: googlechat channel: line Channel integration: line labels Mar 29, 2026
@openclaw-barnacle

Copy link
Copy Markdown

Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch.

@chosen67one-source chosen67one-source left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1911129201

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +104 to +106
export const definePluginEntry: FacadeModule["definePluginEntry"] = createLazyFacadeObjectValue(
() => loadFacadeModule()["definePluginEntry"] as object,
) as FacadeModule["definePluginEntry"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Export definePluginEntry as callable facade

definePluginEntry is wrapped with createLazyFacadeObjectValue, which always returns a proxy over {} (src/plugin-sdk/facade-runtime.ts), so this export is no longer callable. Any consumer importing openclaw/plugin-sdk/browser-runtime and invoking definePluginEntry(...) will hit a runtime TypeError because the value is an object proxy instead of a function.

Useful? React with 👍 / 👎.

Comment on lines +28 to +30
export const MemoryIndexManager: FacadeModule["MemoryIndexManager"] = createLazyFacadeObjectValue(
() => loadFacadeModule()["MemoryIndexManager"] as object,
) as FacadeModule["MemoryIndexManager"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve class-valued MemoryIndexManager export

MemoryIndexManager is also wrapped via createLazyFacadeObjectValue, which changes the export from a class/function value into a plain object proxy. This breaks class semantics for SDK consumers (for example new, instanceof, or prototype-based checks) compared to the prior direct re-export from memory-core/runtime-api.

Useful? React with 👍 / 👎.

@Mintalix
Mintalix deleted the codex/fix-sessions-tool-validation branch April 3, 2026 17:51
damselem added a commit to damselem/openclaw that referenced this pull request Apr 12, 2026
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)
damselem added a commit to damselem/openclaw that referenced this pull request Apr 15, 2026
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling channel: bluebubbles Channel integration: bluebubbles channel: discord Channel integration: discord channel: feishu Channel integration: feishu channel: googlechat Channel integration: googlechat channel: irc channel: line Channel integration: line channel: matrix Channel integration: matrix channel: mattermost Channel integration: mattermost channel: msteams Channel integration: msteams channel: nextcloud-talk Channel integration: nextcloud-talk channel: nostr Channel integration: nostr channel: slack Channel integration: slack channel: telegram Channel integration: telegram channel: tlon Channel integration: tlon channel: twitch Channel integration: twitch channel: voice-call Channel integration: voice-call channel: whatsapp-web Channel integration: whatsapp-web channel: zalo Channel integration: zalo channel: zalouser Channel integration: zalouser cli CLI command changes commands Command implementations docker Docker and sandbox tooling docs Improvements or additions to documentation extensions: acpx extensions: anthropic extensions: byteplus extensions: cloudflare-ai-gateway extensions: copilot-proxy Extension: copilot-proxy extensions: deepseek extensions: device-pair extensions: duckduckgo extensions: fal extensions: huggingface extensions: kilocode extensions: memory-lancedb Extension: memory-lancedb extensions: minimax extensions: modelstudio extensions: moonshot extensions: nvidia extensions: openai extensions: phone-control extensions: qianfan extensions: synthetic extensions: talk-voice extensions: tavily extensions: together extensions: venice extensions: vercel-ai-gateway extensions: volcengine extensions: xiaomi gateway Gateway runtime scripts Repository scripts size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: streamTo in sessions_spawn breaks subagent runtime

7 participants