-
-
Notifications
You must be signed in to change notification settings - Fork 79.2k
[Bug]: lifecycle:end event payload missing aborted and stopReason on pi-embedded path #66534
Copy link
Copy link
Closed
Labels
P2Normal backlog priority with limited blast radius.Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.ClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.ClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.Session, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.staleMarked as stale due to inactivityMarked as stale due to inactivity
Metadata
Metadata
Assignees
Labels
P2Normal backlog priority with limited blast radius.Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.ClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.ClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.Session, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.staleMarked as stale due to inactivityMarked as stale due to inactivity
Type
Fields
Give feedbackNo fields configured for issues without a type.
Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
The main
lifecycle:endevent emitted byhandleAgentEndinsrc/agents/pi-embedded-subscribe.handlers.lifecycle.tsdoes not carryabortedorstopReasonfields. Subscribers cannot distinguish cancellation from natural completion without falling back to theagent()RPC completion frame. The fallback emitter inagent-command.tsalready constructs both fields but is unreachable becauselifecycleEnded = trueis set earlier in the same flow.Steps to reproduce
event:agentevents for a givensessionKey(or have a plugin install anonAgentEventlistener).agent()RPC call that starts a long-running run on that session.abortEmbeddedPiRun(sessionId)directly (for example via theglobalThis[Symbol.for("openclaw.embeddedRunState")].activeRuns.get(sessionId).abort()side door, or viachat.abortfor achat.send-initiated run).lifecycle:endpayload delivered to the subscriber.Expected behavior
The
lifecycle:endpayload contains a booleanabortedand a stringstopReason(for example"aborted"when the run was canceled,"end_turn"when it completed naturally). This matches what the fallback emitter atsrc/agents/agent-command.ts:919-934is already coded to produce for runs that bypass the main emit path.Actual behavior
The
lifecycle:endpayload contains only{phase: "end", livenessState?, replayInvalid?, endedAt}(seesrc/agents/pi-embedded-subscribe.handlers.lifecycle.ts:130-148). NeitherabortednorstopReasonis present, so subscribers cannot tell cancellation from completion.OpenClaw version
2026.4.12
Operating system
Ubuntu 22.04.5 LTS on WSL2 (Linux 6.6.87.2-microsoft-standard-WSL2)
Install method
npm global
Model
N/A (model-agnostic; the bug is in event emitter code paths that run after the model response)
Provider / routing chain
N/A (bug occurs regardless of provider/routing)
Additional provider/model setup details
N/A
Logs, screenshots, and evidence
src/agents/pi-embedded-subscribe.handlers.lifecycle.tshandleAgentEndemits at approximately L130-148 with a payload shape of roughly:No
abortedorstopReasonfield is constructed there.By contrast, the fallback path at
src/agents/agent-command.ts:919-934does construct both fields:but the guard
if (!lifecycleEnded)around that fallback emit is never true in practice.handleAgentEndsetslifecycleEnded = trueatagent-command.ts:910before the fallback runs, so the enriched payload is prepared and then discarded. Downstream consumers (event subscribers, plugin bridges, UI clients) receive the field-lesslifecycle:endexclusively.Impact and severity
event:agentthat needs to distinguish cancel from completion — plugin bridges, UI clients, telemetry pipelines.agent()RPC completion frame (result.meta.aborted) to recover information the event stream is already supposed to carry. This is problematic when the RPC caller and the event subscriber are different parties (for example a plugin that only observes events but did not initiate the run).agent()-initiated run.Additional information
The likely minimum fix is to have
handleAgentEndreadabortedandstopReasonfrom the attempt result (or fromlastAssistant.stopReason, as theagent-command.tsfallback already does) and include them in the emitted payload. The field set at the subscribe layer would then match whatagent-command.ts:919-934already intends to produce.Verified against OpenClaw commit
d7cc6f7643(v2026.4.14-beta.1+69).Related: feature request #66531 (proposing an
agent.abortRPC). Enriching thelifecycle:endpayload is useful regardless of whether that dedicated RPC lands, because it is the primary event-layer signal external clients receive.Reported by the CoClaw team.
This issue was discovered while developing @coclaw/openclaw-coclaw, a CoClaw channel plugin for OpenClaw.