Summary
sessions_spawn with mode: "session" is hardcoded to require thread: true. Since thread binding currently only works on Discord (via subagent_spawning hooks), persistent sub-agent sessions are completely unavailable on Telegram, Slack, WhatsApp, and all other channels.
This blocks the orchestrator pattern documented in the official docs (docs.openclaw.ai/tools/subagents#nested-sub-agents) from working on any non-Discord channel.
Steps to reproduce
- Configure OpenClaw with Telegram (or any non-Discord channel)
- Set
maxSpawnDepth: 2 in config
- Attempt to spawn an orchestrator sub-agent:
sessions_spawn({
task: "...",
mode: "session"
})
Error: mode="session" requires thread=true so the subagent can stay bound to a thread.
- Add
thread: true:
sessions_spawn({
task: "...",
mode: "session",
thread: true
})
Error: Unable to create or bind a thread for this subagent session. Session mode is unavailable for this target.
Root cause
In reply-B2UJINPw.js (spawnSubagentDirect):
if (spawnMode === "session" && !requestThreadBinding) return {
status: "error",
error: "mode=\"session\" requires thread=true..."
};
And ensureThreadBindingForSubagentSpawn requires:
if (!hookRunner?.hasHooks("subagent_spawning")) return {
status: "error",
error: "thread=true is unavailable because no channel plugin registered subagent_spawning hooks."
};
Only Discord registers subagent_spawning hooks, so mode: "session" is Discord-only in practice.
Why this matters
The orchestrator pattern (main → orchestrator sub-agent → worker sub-sub-agents) requires the orchestrator to stay alive between child announces. Sequential workflows like:
- Orchestrator spawns Agent A
- Agent A finishes → announces back to orchestrator
- Orchestrator processes result → spawns Agent B
- Repeat
...require mode: "session" because mode: "run" ends the session after the first turn completes. Without session persistence, the orchestrator exits before child announces arrive.
This is documented as a supported pattern in the docs (maxSpawnDepth: 2, nested sub-agents, announce chain), but it cannot actually work on non-Discord channels.
Proposed fix
Decouple session persistence from thread binding. These are independent concepts:
- Session persistence (
mode: "session") — session stays alive to receive messages (sub-agent announces, sessions_send, etc.)
- Thread binding (
thread: true) — routes platform thread I/O to the session (Discord/Slack feature)
The guard clause should be relaxed: allow mode: "session" without thread: true. The session stays alive headlessly (no platform thread presence) but can still receive child announces as new turns.
// Current (blocks non-Discord):
if (spawnMode === "session" && !requestThreadBinding) return error;
// Proposed (allow headless persistent sessions):
// Remove this guard. Thread binding becomes optional for session mode.
Related issues
Environment
- OpenClaw: latest (2026-02-22)
- Channel: Telegram
- Config:
maxSpawnDepth: 2, maxChildrenPerAgent: 5
- OS: Linux (WSL2)
Summary
sessions_spawnwithmode: "session"is hardcoded to requirethread: true. Since thread binding currently only works on Discord (viasubagent_spawninghooks), persistent sub-agent sessions are completely unavailable on Telegram, Slack, WhatsApp, and all other channels.This blocks the orchestrator pattern documented in the official docs (
docs.openclaw.ai/tools/subagents#nested-sub-agents) from working on any non-Discord channel.Steps to reproduce
maxSpawnDepth: 2in configError:
mode="session" requires thread=true so the subagent can stay bound to a thread.thread: true:Error:
Unable to create or bind a thread for this subagent session. Session mode is unavailable for this target.Root cause
In
reply-B2UJINPw.js(spawnSubagentDirect):And
ensureThreadBindingForSubagentSpawnrequires:Only Discord registers
subagent_spawninghooks, somode: "session"is Discord-only in practice.Why this matters
The orchestrator pattern (main → orchestrator sub-agent → worker sub-sub-agents) requires the orchestrator to stay alive between child announces. Sequential workflows like:
...require
mode: "session"becausemode: "run"ends the session after the first turn completes. Without session persistence, the orchestrator exits before child announces arrive.This is documented as a supported pattern in the docs (
maxSpawnDepth: 2, nested sub-agents, announce chain), but it cannot actually work on non-Discord channels.Proposed fix
Decouple session persistence from thread binding. These are independent concepts:
mode: "session") — session stays alive to receive messages (sub-agent announces,sessions_send, etc.)thread: true) — routes platform thread I/O to the session (Discord/Slack feature)The guard clause should be relaxed: allow
mode: "session"withoutthread: true. The session stays alive headlessly (no platform thread presence) but can still receive child announces as new turns.Related issues
Environment
maxSpawnDepth: 2,maxChildrenPerAgent: 5