OpenClaw
OpenClaw gives API-driven subagents an explicit delivery target
OpenClaw proposes letting /v1/responses callers bind a delivery target after a report showed API-launched subagent completions could finish without reaching a user. A related gateway change keeps delivery inside the owning agent binding.
openclaw/openclaw PR #126501 is the inspected primary source: “feat: let /v1/responses callers set a delivery target so subagent completions can be delivered.” The related records below were inspected as supporting context rather than independent confirmation.
The facts
- openclaw/openclaw PR #126501 was created 2026-08-20T01:18:19Z and was open at inspection; its title is “feat: let /v1/responses callers set a delivery target so subagent completions can be delivered.” - openclaw/openclaw issue #126500 was created 2026-08-20T01:17:52Z and was open at inspection; its title is “[Feature]: /v1/responses cannot bind a delivery target, so subagent completions in API-driven sessions are never delivered.” - openclaw/openclaw PR #126424 was created 2026-08-19T19:42:19Z and was open at inspection; its title is “fix(gateway): keep conversation delivery within agent bindings.” - The repository reported 386805 stars, 5792 open issues, default branch main, and last push 2026-08-20T01:16:30Z. - The latest tagged-release baseline checked was v2026.8.1-beta.2 published 2026-08-15T05:36:23Z.
What changed
openclaw/openclaw PR #126501 reports: Closes #126500 What Problem This Solves An integrator that drives an agent purely through POST /v1/responses (no inbound chat channel) never sees subagent results: the completion announce turn runs in the requester session, the model writes the user-facing update, and it is delivered nowhere — it only lands in the session transcript. The documented session_queued fallback never settles for such a session either, because the session can never acquire a delivery target: x-openclaw-message-channel supplies the channel half of the route, but the endpoint has no way to supply the target half (to), and direct completion delivery requires both. Sibling surfaces already accept exactly this context — /tools/invoke and MCP HTTP read x-openclaw-message-to / x-openclaw-account-id / x-openclaw-thread-id, and the WS agent method takes to/channel/accountId/threadId params — /v1/responses is the only agent-run surface where the caller can name the channel but not the recipient. Why This Change Was Made resolveGatewayRequestContext now optionally resolves the same target-header family the sibling surfaces use (useMessageTargetHeaders), and the OpenResponses handler passes the resolved to / accountId / threadId into the ingress agent command. The run plumbing that already exists carries them the rest of the way: the parent run's delivery context becomes the spawn's requester origin, so a subagent completion announce that returns plain text auto-delivers through the bound channel plugin. Boundaries: **No change to the
openclaw/openclaw issue #126500 reports: Summary Let POST /v1/responses callers supply a delivery target (x-openclaw-message-to, plus optional x-openclaw-account-id / x-openclaw-thread-id) so asynchronous out-of-turn output — first of all subagent completion announces — can be delivered to the caller's channel. Problem to solve A gateway operator drives an agent purely through the HTTP API (POST /v1/responses); no chat channel is connected inbound. The agent spawns a subagent (sessions_spawn), the child finishes, OpenClaw runs the announce turn in the requester session, the model writes a user-facing update — and that update is delivered nowhere. It is only persisted in the session transcript. Verified on 2026.7.1 and reproduced on 2026.8.1-beta.2 with a local gateway, a scripted openai-responses provider and a real outbound-only channel plugin: the announce:v1:agent:…:subagent:… run starts and ends cleanly, its reply reaches the transcript and the gateway console, and the channel plugin is never invoked. The cause is not a missing channel: x-openclaw-message-channel binds the run's channel fine, and a message-tool call inside a turn delivers through the plugin. What is missing is the target half of the route: direct completion delivery is gated on Boolean(channel && to) (resolveExternalBestEffortDeliveryTarget), and /v1/responses offers no way to supply a to — no header, no body field. A session that has only ever seen /v1/responses turns never acquires lastTo/route.target, so the documented fallback (session_queued) never settles either: the completion
openclaw/openclaw PR #126424 reports: Additional instructions MUST:** Keep **Allow edits from maintainers** enabled for this PR so maintainers can help update the branch when needed. What Problem This Solves Fixes an issue where multi-agent operators using conversation tools could discover and deliver to an external conversation through a channel account bound to a different agent. Why This Change Was Made Conversation discovery and delivery now reuse the canonical inbound route resolver for the exact channel, account, and peer. Stored conversation references are revalidated before send or turn I/O, while Mattermost directory requests honor the account supplied by the Gateway. Explicitly unscoped Mattermost directory calls retain their aggregate behavior. User Impact Agents using conversations_list, conversations_send, and conversations_turn remain within their configured channel-account bindings. Existing single-agent and legitimately bound workflows continue to work. Evidence Added regressions that failed before the fix by registering and delivering through a sibling agent's account route. Added positive coverage for a legitimate bound delivery workflow. pnpm test src/gateway/conversation-list.test.ts src/gateway/conversation-send.test.ts src/gateway/conversation-turn.test.ts extensions/mattermost/src/mattermost/directory.test.ts (34 tests passed) pnpm check:changed Local structured autoreview: clean, no accepted/actionable findings
Why it matters
A completed subagent is not delivered work. API sessions need an explicit, authorized destination that survives asynchronous completion without crossing agent bindings. The operator test is whether the system remains bounded and its receipts still describe the action after failure, retry or restart.
Current
The primary record was open when captured on 2026-08-20. The tagged-release baseline was v2026.8.1-beta.2 published 2026-08-15T05:36:23Z. Repository metadata, full source bodies, current pull requests and issues, releases, Google News, Hacker News, Lobsters, Metamesh and the rendered ClawCharts row were inspected. ClawCharts selected the subject; it did not prove the claim.
Evidence
The primary URL is https://github.com/openclaw/openclaw/pull/126501. Supporting records are https://github.com/openclaw/openclaw/issues/126500 and https://github.com/openclaw/openclaw/pull/126424. Source bodies, timestamps and states are preserved in the daily evidence bundle. Test counts and reproductions remain attributed to their authors unless identified as independently rerun.
Source boundary
Open work is described as open, closed work as closed, and operator reports as reports. A pull request is evidence of proposed or reviewed direction, not proof of a shipped release. Search residue, package mirrors and historically published source spines were excluded.
Operator take
Require callers to name a delivery target, validate it against the owning agent binding, and record both completion and delivery in the same receipt. Preserve a before-state receipt, make the smallest reversible change, and verify the original failure independently.
Caveat
Public project records are mutable. Status, scope and evidence can change after publication. This brief records the inspected state and does not authorize changes to a reader’s deployment.
Source inspected; source state, environment and release boundary remain explicit.