2026-07-04 — sessions_spawn denies subagent runtime operator.write
Summary
On OpenClaw 2026.6.11, when a channel-driven main-agent session (e.g. agent:main:bluebubbles:direct:+1... or agent:main:slack:direct:...) calls the sessions_spawn tool to delegate a task to a subagent, the request is rejected with:
missing scope: operator.write
The main agent's runtime client identity — which the gateway synthesizes to invoke tools on behalf of the running model — appears to be missing operator.write. This blocks all subagent delegation from that surface.
Reproduction
- OpenClaw
2026.6.11
- Agent
main running ollama/minimax-m2.5:cloud
- Inbound channel:
bluebubbles (Blue Bubbles / iMessage). Slack observed same behavior on channel-driven sessions.
- User sends an iMessage that leads the main agent to call
sessions_spawn with agentId=wozbot.
Observed behavior
The tool returns (verbatim from a runtime trajectory record at 2026-07-04T20:30:26.182Z):
{
"toolName": "sessions_spawn",
"meta": "Fix the FiCalc (retirement calculator) mobile touch issues ...",
"error": "missing scope: operator.write",
"mutatingAction": true,
"actionFingerprint": "tool=sessions_spawn|meta=..."
}
The model receives this error, cannot delegate, and either aborts or (worse) attempts the task itself in the main-agent context — bypassing the whole point of subagent routing.
Repeats every attempt on the same session; retries do not help.
Expected behavior
The main-agent runtime should hold operator.write (and operator.read) by default. Spawning a subagent is a normal control-plane write action and should be permitted for any active agent runtime, regardless of which channel drove the inbound event.
Impact
- All subagent delegation broken from iMessage / BlueBubbles-driven main sessions (confirmed).
- Suspected same-shape failure on other channels — needs testing per channel.
- Any agent config with
subagents.allowAgents: [...] becomes non-functional on affected surfaces.
- Downstream effect: models that lack strict "do not proceed without subagent" instructions will silently do the work themselves on the wrong (lower-privilege / wrong-model) main agent.
Isolation test (important)
sessions_spawn from a Slack channel-bound agent session (agent wozbot, binding agent:wozbot:slack:channel:C0AJU4X0DG9) works — subagent accepted, child ran, completion event fired normally.
sessions_spawn from a BlueBubbles channel-bound agent session (agent main, binding agent:main:bluebubbles:direct:+1...) fails with missing scope: operator.write.
Both agents are configured with subagents.allowAgents: ["wozbot", ...] and the same paired device set. The only meaningful diff is the channel plugin: BlueBubbles uses core.channel.inbound.run (which the Blue Bubbles plugin invokes from monitor-processing-*.js) → kernel.runChannelTurn. Slack uses its own inbound path that does not go through core.channel.inbound.run.
So the scope drop is on the runChannelTurn codepath (kernel-CpJ_eT7K.js) — specifically wherever the resolved turn context is handed off to the runtime that will later invoke tools on the model's behalf. The runtime identity for that path is missing operator.write.
Diagnostic breadcrumbs
- Scope check emitter:
plugin-host-hooks-BH_m3lco.js (missing scope: ${missingScope}).
- Inbound dispatch path for BlueBubbles:
inbound-reply-dispatch-DIfEV7g-.js → kernel-CpJ_eT7K.js#runChannelTurn → dispatchResolvedChannelTurn.
- Slack does not use this path.
- Paired device store shows normal operator scopes for the human's CLI + Control UI devices — the missing scope is on the internal runtime identity used when the model calls a tool from a channel-driven session, not on any human-paired device.
Proposed fix: in the runChannelTurn (or dispatchResolvedChannelTurn) runtime-client construction, ensure the synthesized operator scopes include operator.write by default (or, better, use the same scope set that Slack's inbound path uses — since that path demonstrably works).
Workaround
None known short of doing coding in a dedicated wozbot-bound channel (e.g. Slack channel with a direct wozbot binding), which bypasses the main-agent spawn via the BlueBubbles path.
Environment
- OpenClaw
2026.6.11 (e085fa1)
- macOS Darwin
25.3.0 arm64, Node v22.22.0
- Channels affected (confirmed):
bluebubbles
- Model provider on
main: ollama/minimax-m2.5:cloud (irrelevant to the failure — the scope check happens before the tool executes)
2026-07-04 —
sessions_spawndenies subagent runtimeoperator.writeSummary
On OpenClaw
2026.6.11, when a channel-driven main-agent session (e.g.agent:main:bluebubbles:direct:+1...oragent:main:slack:direct:...) calls thesessions_spawntool to delegate a task to a subagent, the request is rejected with:The main agent's runtime client identity — which the gateway synthesizes to invoke tools on behalf of the running model — appears to be missing
operator.write. This blocks all subagent delegation from that surface.Reproduction
2026.6.11mainrunningollama/minimax-m2.5:cloudbluebubbles(Blue Bubbles / iMessage). Slack observed same behavior on channel-driven sessions.sessions_spawnwithagentId=wozbot.Observed behavior
The tool returns (verbatim from a runtime trajectory record at
2026-07-04T20:30:26.182Z):{ "toolName": "sessions_spawn", "meta": "Fix the FiCalc (retirement calculator) mobile touch issues ...", "error": "missing scope: operator.write", "mutatingAction": true, "actionFingerprint": "tool=sessions_spawn|meta=..." }The model receives this error, cannot delegate, and either aborts or (worse) attempts the task itself in the main-agent context — bypassing the whole point of subagent routing.
Repeats every attempt on the same session; retries do not help.
Expected behavior
The main-agent runtime should hold
operator.write(andoperator.read) by default. Spawning a subagent is a normal control-plane write action and should be permitted for any active agent runtime, regardless of which channel drove the inbound event.Impact
subagents.allowAgents: [...]becomes non-functional on affected surfaces.Isolation test (important)
sessions_spawnfrom a Slack channel-bound agent session (agentwozbot, bindingagent:wozbot:slack:channel:C0AJU4X0DG9) works — subagent accepted, child ran, completion event fired normally.sessions_spawnfrom a BlueBubbles channel-bound agent session (agentmain, bindingagent:main:bluebubbles:direct:+1...) fails withmissing scope: operator.write.Both agents are configured with
subagents.allowAgents: ["wozbot", ...]and the same paired device set. The only meaningful diff is the channel plugin: BlueBubbles usescore.channel.inbound.run(which the Blue Bubbles plugin invokes frommonitor-processing-*.js) →kernel.runChannelTurn. Slack uses its own inbound path that does not go throughcore.channel.inbound.run.So the scope drop is on the
runChannelTurncodepath (kernel-CpJ_eT7K.js) — specifically wherever the resolved turn context is handed off to the runtime that will later invoke tools on the model's behalf. The runtime identity for that path is missingoperator.write.Diagnostic breadcrumbs
plugin-host-hooks-BH_m3lco.js(missing scope: ${missingScope}).inbound-reply-dispatch-DIfEV7g-.js→kernel-CpJ_eT7K.js#runChannelTurn→dispatchResolvedChannelTurn.Proposed fix: in the
runChannelTurn(ordispatchResolvedChannelTurn) runtime-client construction, ensure the synthesized operator scopes includeoperator.writeby default (or, better, use the same scope set that Slack's inbound path uses — since that path demonstrably works).Workaround
None known short of doing coding in a dedicated
wozbot-bound channel (e.g. Slack channel with a directwozbotbinding), which bypasses the main-agent spawn via the BlueBubbles path.Environment
2026.6.11 (e085fa1)25.3.0arm64, Nodev22.22.0bluebubblesmain:ollama/minimax-m2.5:cloud(irrelevant to the failure — the scope check happens before the tool executes)