Skip to content

ACP (acpx) sessions don't trigger subagent_ended hook or announce pipeline #46439

Description

@worldofgeese

Summary

ACP sessions spawned via sessions_spawn(runtime: "acp") complete successfully but never trigger the subagent_ended hook or the subagent announce pipeline. The orchestrator/parent session never receives a completion announcement, creating a silent stall.

Expected Behavior

When an ACP session finishes, the parent session should receive a completion announcement (same as embedded/Pi subagent runs), and the subagent_ended hook should fire.

Actual Behavior

  • ACP session completes and emits done event internally
  • Stream log shows :start:stall (60s idle) — but no lifecycle event reaches the agent event bus
  • subagent_ended hook never fires
  • Announce pipeline never triggers
  • Parent session waiting via sessions_yield is never woken

Root Cause (from source investigation)

The embedded Pi runtime (pi-embedded-subscribe.handlers.lifecycle.ts) calls emitAgentEvent({ stream: "lifecycle", data: { phase: "end" } }) on completion, which the subagent registry listener picks up → completeSubagentRunemitSubagentEndedHookForRun → announce flow.

The ACPX plugin runtime (runtime.ts) yields { type: "done" } to its caller but this is not bridged into the gateway's emitAgentEvent bus. ACPX manages its own lifecycle internally (service.ts:lifecycleRevision) without emitting to the shared agent event system.

So the announce pipeline is architecturally sound — it just never receives the signal from ACP runs.

Proposed Fix

When an ACP run yields { type: "done" }, the gateway's ACP handler should call:

emitAgentEvent({
  runId,
  stream: "lifecycle",
  data: { phase: "end", endedAt: Date.now() }
});

This would make all existing infrastructure work: subagent_ended hook fires, announce pipeline delivers results to requester session, sessions_yield wakes up.

Workaround

Currently using a background stream-log watcher that polls .acp-stream.jsonl files for :stall events every 10s and cross-references active-tasks.json for git branch changes. Works but adds ~70s latency (60s stall + 10s scan).

Environment

  • OpenClaw v2026.3.13 (commit f6e5b67)
  • acpx v0.1.16
  • ACP backend: claude (via Anthropic proxy)

Relevant Source Locations

  • auth-profiles-*.js:92532onAgentEvent listener for lifecycle events
  • auth-profiles-*.js:92344completeSubagentRun
  • auth-profiles-*.js:92375emitSubagentEndedHookForRun
  • ACPX runtime.ts:409 — yields { type: "done" } (not bridged to agent event bus)
  • ACPX service.ts:39-100 — internal lifecycle management
  • Pi runtime: pi-embedded-subscribe.handlers.lifecycle.ts — correctly emits lifecycle events

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