> ## Documentation Index
> Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Thread-bound sub-agent sessions

## Thread-bound sessions

When thread bindings are enabled for a channel, a sub-agent can stay bound
to a thread so follow-up user messages in that thread keep routing to the
same sub-agent session.

### Thread supporting channels

A channel supports persistent thread-bound subagent sessions
(`sessions_spawn` with `thread: true`) when it registers a conversation
binding adapter. Bundled channels with that support: **Discord**,
**iMessage**, **Matrix**, and **Telegram**. Discord and Matrix default to
creating a child thread; Telegram and iMessage default to binding the
current conversation. Use the per-channel `threadBindings` config keys for
enablement, timeouts, and `spawnSessions`.

### Quick flow

**1. Spawn**

`sessions_spawn` with `thread: true` (and optionally `mode: "session"`).

**2. Bind**

OpenClaw creates or binds a thread to that session target in the active channel.

**3. Route follow-ups**

Replies and follow-up messages in that thread route to the bound session.

**4. Inspect timeouts**

Use `/session idle` to inspect/update inactivity expiry and
`/session max-age` to control the hard cap.

**5. Detach**

Use `/session unbind` to detach without closing the agent session.

### Manual controls

| Command | Effect |
| - | - |
| `/session unbind` | Remove the current conversation binding without closing the agent session |
| `/agents` | List active runs and binding state (`binding:<id>`, `unbound`, or `bindings unavailable`) |
| `/session idle` | Inspect/update inactivity expiry for the current binding |
| `/session max-age` | Inspect/update the maximum age of the current binding |

### Config switches

* **Global default:** `session.threadBindings.enabled`, `session.threadBindings.idleHours`, `session.threadBindings.maxAgeHours`.
* **Channel override and spawn auto-bind keys** are adapter-specific. See [Thread supporting channels](#thread-supporting-channels) above.

See [Configuration reference](https://docs2.openclaw.ai/gateway/configuration-reference.md) and
[Slash commands](https://docs2.openclaw.ai/tools/slash-commands.md) for current adapter details.

### Allowlist

**agents.entries.\*.subagents.allowAgents** `string[]`

List of configured agent ids that can be targeted via explicit `agentId` (`["*"]` allows any configured target). Default: only the requester agent. If you set a list and still want the requester to spawn itself with `agentId`, include the requester id in the list.

**agents.defaults.subagents.allowAgents** `string[]`

Default configured target-agent allowlist used when the requester agent does not set its own `subagents.allowAgents`.

**agents.defaults.subagents.requireAgentId** `boolean` (default: false)

Block `sessions_spawn` calls that omit `agentId` (forces explicit profile selection). Per-agent override: `agents.entries.*.subagents.requireAgentId`.

**agents.defaults.subagents.announceTimeoutMs** `number` (default: 120000)

Timeout for gateway `agent` announcement handoff attempts. Once a handoff is accepted, waiting for the parent session's turn does not consume this budget. After execution starts, the requester's normal [runtime timeout and cancellation controls](https://docs2.openclaw.ai/concepts/agent-loop.md#timeouts) apply; the announcement timer does not restart. Values are positive integer milliseconds and are clamped to the platform-safe timer maximum. Queue waits, requester execution, and transient retries can make total delivery time longer than one configured timeout.

If the requester session is sandboxed, `sessions_spawn` rejects targets
that would run unsandboxed.

### Discovery

Use `agents_list` to see which agent ids are currently allowed for
`sessions_spawn`. The response includes each listed agent's effective
model and embedded runtime metadata so callers can distinguish OpenClaw, Codex
app-server, and other configured native runtimes.

`allowAgents` entries must point at configured agent ids in `agents.entries.*`.
`["*"]` means any configured target agent plus the requester. If an agent config
is deleted but its id remains in `allowAgents`, `sessions_spawn` rejects that id
and `agents_list` omits it. Run `openclaw doctor --fix` to clean stale
allowlist entries, or add a minimal `agents.entries.*` entry when the target should
remain spawnable while inheriting defaults.

### Auto-archive

* Sub-agent sessions are automatically archived after `agents.defaults.subagents.archiveAfterMinutes` (default `60`).
* Archive uses `sessions.delete` and renames the transcript to `*.deleted.<timestamp>` (same folder).
* `cleanup: "delete"` archives immediately after announce (still keeps the transcript via rename).
* Auto-archive is best-effort; pending timers are lost if the gateway restarts.
* Configured run timeouts do **not** auto-archive; they only stop the run. The session remains until auto-archive.
* Auto-archive applies equally at every sub-agent depth.
* Browser cleanup is separate from archive cleanup: tracked browser tabs/processes are best-effort closed when the run finishes, even if the transcript/session record is kept.

If a newer run takes over the same session, the older run stops claiming tabs for
cleanup. Cleanup already admitted for a tab still settles against that tab's
captured ownership; it does not remove a later registration.

The `subagent_ended` plugin hook is best-effort. Hook execution or plugin runtime
loading failures are logged and do not abort sub-agent cleanup.
