Skip to content

feat(acp): add sessions_spawn streamTo parent relay for ACP spawns#34310

Merged
osolmaz merged 1 commit intoopenclaw:mainfrom
osolmaz:vincentkoc-code/cli-acpx-reliability-20260304-fork
Mar 4, 2026
Merged

feat(acp): add sessions_spawn streamTo parent relay for ACP spawns#34310
osolmaz merged 1 commit intoopenclaw:mainfrom
osolmaz:vincentkoc-code/cli-acpx-reliability-20260304-fork

Conversation

@dutifulbob
Copy link
Copy Markdown
Contributor

Summary

  • Problem: ACP sessions_spawn runs are non-blocking but gave poor parent-session visibility during long or blocked initial turns.
  • Why it matters: Orchestrator sessions could not see child progress/no-output state without external process inspection.
  • What changed:
    • Added sessions_spawn.streamTo: "parent" support for runtime: "acp".
    • Added ACP parent relay that forwards initial child-run progress/no-output/completion/failure updates into requester session system events.
    • When streamTo: "parent" is used, direct child delivery for that initial run is disabled.
    • Added tests for relay behavior, ACP spawn behavior, and schema/tool forwarding.
    • Updated docs and changelog.
  • What did NOT change (scope boundary):
    • No persistent tail-log file or full WebSocket parity implementation yet; this addresses parent visibility for the initial run path.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

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

Linked Issue/PR

User-visible / Behavior Changes

  • sessions_spawn now accepts streamTo: "parent" for ACP runtime.
  • With runtime: "acp" + streamTo: "parent", requester session receives progress/no-output/completion/failure system-event updates for the initial child run.
  • Initial child run uses deliver: false in that mode to avoid direct child-delivery duplication.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: Node 22+
  • Model/provider: ACP harness session path
  • Integration/channel (if any): sessions/tool runtime path
  • Relevant config (redacted): ACP enabled

Steps

  1. Run sessions_spawn with { runtime: "acp", streamTo: "parent", task: "..." } from an active requester session.
  2. Observe system-event updates in requester session while child run executes.
  3. Verify direct child delivery is disabled for that initial run.

Expected

  • Parent session receives progress/no-output/completion updates for initial ACP run.

Actual

  • Covered by new tests and implementation.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:
    • relay progress + completion updates
    • no-output + resumed update behavior
    • ACP spawn streamTo parent dispatch behavior (deliver=false)
    • sessions tool schema/forwarding updates
  • Edge cases checked:
    • streamTo: "parent" rejected when requester session context is missing
  • What you did not verify:
    • end-to-end channel UX on live gateway/channel environment

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly:
    • stop using streamTo: "parent" (default behavior unchanged)
    • revert relay + ACP spawn stream target commits
  • Files/config to restore:
    • src/agents/acp-spawn-parent-stream.ts
    • src/agents/acp-spawn.ts
    • src/agents/tools/sessions-spawn-tool.ts
  • Known bad symptoms reviewers should watch for:
    • missing or noisy requester system-event updates
    • unexpected delivery suppression when not using streamTo: "parent"

Risks and Mitigations

  • Risk:
    • Parent relay could produce noisy updates on very chatty child output.
    • Mitigation:
      • Buffered/compacted forwarding with periodic flush and bounded snippets.
  • Risk:
    • Missing requester session key with streamTo: "parent" could silently fail.
    • Mitigation:
      • Explicit validation error when requester session context is unavailable.

Original PR: #34055

@openclaw-barnacle openclaw-barnacle bot added docs Improvements or additions to documentation agents Agent runtime and tooling size: L labels Mar 4, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 4, 2026

Greptile Summary

This PR adds streamTo: "parent" support for runtime: "acp" in sessions_spawn, enabling requester sessions to receive real-time progress, stall, and completion system-events for initial ACP child runs. A new acp-spawn-parent-stream.ts module handles buffered delta forwarding, no-output watchdog, best-effort JSONL relay logging, and safe disposal. The implementation is well-organized with good test coverage for the relay module itself.

Key observations:

  • The relay pre-registration strategy (registering before gateway dispatch) is sound for avoiding missed fast failures when the gateway echoes the idempotency key as the runId.
  • When the gateway returns a runId different from childIdem, the first relay is disposed and recreated. Since the first relay was filtering for event.runId === childIdem, it cannot observe gateway events tagged with the actual runId — meaning there is a race window where early lifecycle events (emitted by the gateway before responding) may be silently dropped.
  • The stream-related tests in acp-spawn.test.ts always exercise the relay-recreation branch because the mock gateway returns a fixed runId: "run-1" which never matches the crypto.randomUUID() idempotency key. The happy path — where the gateway echoes the idempotency key — is not covered.
  • deliverToBoundTarget = hasDeliveryTarget && !streamToParentRequested cleanly gates delivery suppression; backward compatibility is preserved since the feature is opt-in.
  • Documentation and changelog additions are accurate and well-scoped.

Confidence Score: 3/5

  • Safe to merge with awareness of the relay-recreation race window and incomplete test coverage for the happy path.
  • The core implementation is clean and backward-compatible. However, two concerns remain: (1) a race window in the relay-recreation logic where early lifecycle events from the gateway could be dropped when it returns a runId different from the idempotency key—an acknowledged edge case that could silently degrade the feature's primary purpose of parent visibility; (2) integration tests never exercise the common-case code path (no relay recreation), leaving a gap in confidence that the happy path where the gateway echoes the idempotency key works correctly end-to-end.
  • src/agents/acp-spawn.ts (relay recreation race, lines 485–498) and src/agents/acp-spawn.test.ts (missing happy-path test coverage, lines 454–509)

Last reviewed commit: 96771db

@osolmaz osolmaz self-assigned this Mar 4, 2026
@osolmaz osolmaz force-pushed the vincentkoc-code/cli-acpx-reliability-20260304-fork branch from 96771db to 68c3b2d Compare March 4, 2026 10:44
@osolmaz osolmaz merged commit 257e2f5 into openclaw:main Mar 4, 2026
9 checks passed
@osolmaz
Copy link
Copy Markdown
Contributor

osolmaz commented Mar 4, 2026

Landed via temp rebase onto main.

  • Gate: pnpm lint && pnpm build && pnpm test
  • Land commit: 68c3b2d
  • Merge commit: 257e2f5

Thanks @vincentkoc!

@osolmaz
Copy link
Copy Markdown
Contributor

osolmaz commented Mar 4, 2026

This is a copy of original PR by @vincentkoc #34055

@osolmaz osolmaz deleted the vincentkoc-code/cli-acpx-reliability-20260304-fork branch March 4, 2026 10:48
mrosmarin added a commit to mrosmarin/openclaw that referenced this pull request Mar 4, 2026
* main: (92 commits)
  fix: preserve raw media invoke for HTTP tool clients (openclaw#34365)
  fix: prevent nodes media base64 context bloat (openclaw#34332)
  docs(changelog): credit @Brotherinlaw-13 for openclaw#34318
  fix(telegram): materialize dm draft final to avoid duplicates
  fix: relay ACP sessions_spawn parent streaming (openclaw#34310) (thanks @vincentkoc) (openclaw#34310)
  fix: kill stuck ACP child processes on startup and harden sessions in discord threads (openclaw#33699)
  feat(ios): add Live Activity connection status + stale cleanup (openclaw#33591)
  chore(docs): add plugins refactor changelog entry
  Chore: remove accidental .DS_Store artifact
  Plugins/zalouser: migrate to scoped plugin-sdk imports
  Plugins/zalo: migrate to scoped plugin-sdk imports
  Plugins/whatsapp: migrate to scoped plugin-sdk imports
  Plugins/voice-call: migrate to scoped plugin-sdk imports
  Plugins/twitch: migrate to scoped plugin-sdk imports
  Plugins/tlon: migrate to scoped plugin-sdk imports
  Plugins/thread-ownership: migrate to scoped plugin-sdk imports
  Plugins/test-utils: migrate to scoped plugin-sdk imports
  Plugins/talk-voice: migrate to scoped plugin-sdk imports
  Plugins/synology-chat: migrate to scoped plugin-sdk imports
  Plugins/qwen-portal-auth: migrate to scoped plugin-sdk imports
  ...