openclaw - 💡(How to fix) Fix subagent_ended hook does not fire for runs created via api.runtime.subagent.run() [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#59164Fetched 2026-04-08 02:27:58
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Author
Participants

api.on("subagent_ended", handler) never fires for subagent sessions created via api.runtime.subagent.run(). The hook only fires for runs created through the internal sessions_spawn tool path.

Root Cause

Two execution paths diverge:

sessions_spawn (tool)api.runtime.subagent.run() (plugin SDK)
Calls registerSubagentRun()Yes (sessions-spawn-tool.ts:259)No
Creates SubagentRunRecordYesNo
Tracked in subagent registryYesNo
Emits subagent_ended hookYes (via subagent-registry-lifecycle.ts:148)No

When a plugin calls api.runtime.subagent.run(params):

  1. server-plugins.ts:328 dispatches to the gateway "agent" method
  2. server-methods/agent.ts:264 calls agentCommandFromIngress() directly
  3. No call to registerSubagentRun() — the run is never tracked in the subagent registry
  4. When the agent finishes, no SubagentRunRecord exists, so emitSubagentEndedHookOnce() is never called
  5. The plugin's api.on("subagent_ended", handler) never fires

Fix Action

Workaround

Workers can self-report completion by calling a plugin-registered tool (e.g. tasks.handoff) before their run ends. The plugin handles completion in the tool's execute handler instead of the hook.

RAW_BUFFERClick to expand / collapse

Summary

api.on("subagent_ended", handler) never fires for subagent sessions created via api.runtime.subagent.run(). The hook only fires for runs created through the internal sessions_spawn tool path.

Root Cause

Two execution paths diverge:

sessions_spawn (tool)api.runtime.subagent.run() (plugin SDK)
Calls registerSubagentRun()Yes (sessions-spawn-tool.ts:259)No
Creates SubagentRunRecordYesNo
Tracked in subagent registryYesNo
Emits subagent_ended hookYes (via subagent-registry-lifecycle.ts:148)No

When a plugin calls api.runtime.subagent.run(params):

  1. server-plugins.ts:328 dispatches to the gateway "agent" method
  2. server-methods/agent.ts:264 calls agentCommandFromIngress() directly
  3. No call to registerSubagentRun() — the run is never tracked in the subagent registry
  4. When the agent finishes, no SubagentRunRecord exists, so emitSubagentEndedHookOnce() is never called
  5. The plugin's api.on("subagent_ended", handler) never fires

Impact

Any plugin that uses api.runtime.subagent.run() to spawn workers and api.on("subagent_ended") to handle completion will never receive the completion event. These two APIs are documented as companion features but are not wired together.

Workaround

Workers can self-report completion by calling a plugin-registered tool (e.g. tasks.handoff) before their run ends. The plugin handles completion in the tool's execute handler instead of the hook.

Suggested Fix

The gateway's "agent" handler (server-methods/agent.ts) should call registerSubagentRun() for runs dispatched via the plugin SDK, so they participate in the normal subagent completion lifecycle and emit subagent_ended when done.

Reproduction

  1. Create a plugin that registers a tool and a subagent_ended hook
  2. Call api.runtime.subagent.run({ sessionKey: "test:key", message: "hello" })
  3. Wait for the run to complete
  4. Observe: the subagent_ended handler is never called

Environment

  • OpenClaw version: latest (as of 2026-03-31)
  • Affected files: src/gateway/server-plugins.ts, src/gateway/server-methods/agent.ts, src/agents/subagent-registry.ts

extent analysis

TL;DR

The api.on("subagent_ended", handler) event is not fired for subagent sessions created via api.runtime.subagent.run() due to missing registration in the subagent registry, and a workaround involves having workers self-report completion.

Guidance

  • To fix the issue, modify the gateway's "agent" handler in server-methods/agent.ts to call registerSubagentRun() for runs dispatched via the plugin SDK.
  • Verify the fix by creating a plugin that registers a tool and a subagent_ended hook, calling api.runtime.subagent.run(), and checking if the subagent_ended handler is called after the run completes.
  • As a temporary workaround, plugins can have workers self-report completion by calling a plugin-registered tool before their run ends and handling completion in the tool's execute handler.
  • Review the affected files (src/gateway/server-plugins.ts, src/gateway/server-methods/agent.ts, src/agents/subagent-registry.ts) to ensure the changes are correctly implemented.

Example

// In server-methods/agent.ts
agentCommandFromIngress(...args) {
  // ...
  registerSubagentRun(...); // Add this call for plugin SDK runs
  // ...
}

Notes

The provided fix assumes that the registerSubagentRun() function is correctly implemented and will properly register the subagent run in the registry. Additionally, the workaround may require modifications to the plugin's code to handle self-reported completion.

Recommendation

Apply the workaround of having workers self-report completion until the fix can be implemented and verified, as it provides a temporary solution for plugins that rely on the subagent_ended event.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING