mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 05:47:28 +00:00
chore: Run pnpm format:fix.
This commit is contained in:
@@ -3,24 +3,28 @@ summary: "Session management rules, keys, and persistence for chats"
|
||||
read_when:
|
||||
- Modifying session handling or storage
|
||||
---
|
||||
|
||||
# Session Management
|
||||
|
||||
OpenClaw treats **one direct-chat session per agent** as primary. Direct chats collapse to `agent:<agentId>:<mainKey>` (default `main`), while group/channel chats get their own keys. `session.mainKey` is honored.
|
||||
|
||||
Use `session.dmScope` to control how **direct messages** are grouped:
|
||||
|
||||
- `main` (default): all DMs share the main session for continuity.
|
||||
- `per-peer`: isolate by sender id across channels.
|
||||
- `per-channel-peer`: isolate by channel + sender (recommended for multi-user inboxes).
|
||||
- `per-account-channel-peer`: isolate by account + channel + sender (recommended for multi-account inboxes).
|
||||
Use `session.identityLinks` to map provider-prefixed peer ids to a canonical identity so the same person shares a DM session across channels when using `per-peer`, `per-channel-peer`, or `per-account-channel-peer`.
|
||||
Use `session.identityLinks` to map provider-prefixed peer ids to a canonical identity so the same person shares a DM session across channels when using `per-peer`, `per-channel-peer`, or `per-account-channel-peer`.
|
||||
|
||||
## Gateway is the source of truth
|
||||
|
||||
All session state is **owned by the gateway** (the “master” OpenClaw). UI clients (macOS app, WebChat, etc.) must query the gateway for session lists and token counts instead of reading local files.
|
||||
|
||||
- In **remote mode**, the session store you care about lives on the remote gateway host, not your Mac.
|
||||
- Token counts shown in UIs come from the gateway’s store fields (`inputTokens`, `outputTokens`, `totalTokens`, `contextTokens`). Clients do not parse JSONL transcripts to “fix up” totals.
|
||||
|
||||
## Where state lives
|
||||
|
||||
- On the **gateway host**:
|
||||
- Store file: `~/.openclaw/agents/<agentId>/sessions/sessions.json` (per agent).
|
||||
- Transcripts: `~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl` (Telegram topic sessions use `.../<SessionId>-topic-<threadId>.jsonl`).
|
||||
@@ -30,16 +34,19 @@ All session state is **owned by the gateway** (the “master” OpenClaw). UI cl
|
||||
- OpenClaw does **not** read legacy Pi/Tau session folders.
|
||||
|
||||
## Session pruning
|
||||
|
||||
OpenClaw trims **old tool results** from the in-memory context right before LLM calls by default.
|
||||
This does **not** rewrite JSONL history. See [/concepts/session-pruning](/concepts/session-pruning).
|
||||
|
||||
## Pre-compaction memory flush
|
||||
|
||||
When a session nears auto-compaction, OpenClaw can run a **silent memory flush**
|
||||
turn that reminds the model to write durable notes to disk. This only runs when
|
||||
the workspace is writable. See [Memory](/concepts/memory) and
|
||||
[Compaction](/concepts/compaction).
|
||||
|
||||
## Mapping transports → session keys
|
||||
|
||||
- Direct chats follow `session.dmScope` (default `main`).
|
||||
- `main`: `agent:<agentId>:<mainKey>` (continuity across devices/channels).
|
||||
- Multiple phone numbers and channels can map to the same agent main key; they act as transports into one conversation.
|
||||
@@ -57,6 +64,7 @@ the workspace is writable. See [Memory](/concepts/memory) and
|
||||
- Node runs: `node-<nodeId>`
|
||||
|
||||
## Lifecycle
|
||||
|
||||
- Reset policy: sessions are reused until they expire, and expiry is evaluated on the next inbound message.
|
||||
- Daily reset: defaults to **4:00 AM local time on the gateway host**. A session is stale once its last update is earlier than the most recent daily reset time.
|
||||
- Idle reset (optional): `idleMinutes` adds a sliding idle window. When both daily and idle resets are configured, **whichever expires first** forces a new session.
|
||||
@@ -68,6 +76,7 @@ the workspace is writable. See [Memory](/concepts/memory) and
|
||||
- Isolated cron jobs always mint a fresh `sessionId` per run (no idle reuse).
|
||||
|
||||
## Send policy (optional)
|
||||
|
||||
Block delivery for specific session types without listing individual ids.
|
||||
|
||||
```json5
|
||||
@@ -76,53 +85,56 @@ Block delivery for specific session types without listing individual ids.
|
||||
sendPolicy: {
|
||||
rules: [
|
||||
{ action: "deny", match: { channel: "discord", chatType: "group" } },
|
||||
{ action: "deny", match: { keyPrefix: "cron:" } }
|
||||
{ action: "deny", match: { keyPrefix: "cron:" } },
|
||||
],
|
||||
default: "allow"
|
||||
}
|
||||
}
|
||||
default: "allow",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Runtime override (owner only):
|
||||
|
||||
- `/send on` → allow for this session
|
||||
- `/send off` → deny for this session
|
||||
- `/send inherit` → clear override and use config rules
|
||||
Send these as standalone messages so they register.
|
||||
Send these as standalone messages so they register.
|
||||
|
||||
## Configuration (optional rename example)
|
||||
|
||||
```json5
|
||||
// ~/.openclaw/openclaw.json
|
||||
{
|
||||
session: {
|
||||
scope: "per-sender", // keep group keys separate
|
||||
dmScope: "main", // DM continuity (set per-channel-peer/per-account-channel-peer for shared inboxes)
|
||||
scope: "per-sender", // keep group keys separate
|
||||
dmScope: "main", // DM continuity (set per-channel-peer/per-account-channel-peer for shared inboxes)
|
||||
identityLinks: {
|
||||
alice: ["telegram:123456789", "discord:987654321012345678"]
|
||||
alice: ["telegram:123456789", "discord:987654321012345678"],
|
||||
},
|
||||
reset: {
|
||||
// Defaults: mode=daily, atHour=4 (gateway host local time).
|
||||
// If you also set idleMinutes, whichever expires first wins.
|
||||
mode: "daily",
|
||||
atHour: 4,
|
||||
idleMinutes: 120
|
||||
idleMinutes: 120,
|
||||
},
|
||||
resetByType: {
|
||||
thread: { mode: "daily", atHour: 4 },
|
||||
dm: { mode: "idle", idleMinutes: 240 },
|
||||
group: { mode: "idle", idleMinutes: 120 }
|
||||
group: { mode: "idle", idleMinutes: 120 },
|
||||
},
|
||||
resetByChannel: {
|
||||
discord: { mode: "idle", idleMinutes: 10080 }
|
||||
discord: { mode: "idle", idleMinutes: 10080 },
|
||||
},
|
||||
resetTriggers: ["/new", "/reset"],
|
||||
store: "~/.openclaw/agents/{agentId}/sessions/sessions.json",
|
||||
mainKey: "main",
|
||||
}
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Inspecting
|
||||
|
||||
- `openclaw status` — shows store path and recent sessions.
|
||||
- `openclaw sessions --json` — dumps every entry (filter with `--active <minutes>`).
|
||||
- `openclaw gateway call sessions.list --params '{}'` — fetch sessions from the running gateway (use `--url`/`--token` for remote gateway access).
|
||||
@@ -133,20 +145,23 @@ Send these as standalone messages so they register.
|
||||
- JSONL transcripts can be opened directly to review full turns.
|
||||
|
||||
## Tips
|
||||
|
||||
- Keep the primary key dedicated to 1:1 traffic; let groups keep their own keys.
|
||||
- When automating cleanup, delete individual keys instead of the whole store to preserve context elsewhere.
|
||||
|
||||
## Session origin metadata
|
||||
|
||||
Each session entry records where it came from (best-effort) in `origin`:
|
||||
|
||||
- `label`: human label (resolved from conversation label + group subject/channel)
|
||||
- `provider`: normalized channel id (including extensions)
|
||||
- `from`/`to`: raw routing ids from the inbound envelope
|
||||
- `accountId`: provider account id (when multi-account)
|
||||
- `threadId`: thread/topic id when the channel supports it
|
||||
The origin fields are populated for direct messages, channels, and groups. If a
|
||||
connector only updates delivery routing (for example, to keep a DM main session
|
||||
fresh), it should still provide inbound context so the session keeps its
|
||||
explainer metadata. Extensions can do this by sending `ConversationLabel`,
|
||||
`GroupSubject`, `GroupChannel`, `GroupSpace`, and `SenderName` in the inbound
|
||||
context and calling `recordSessionMetaFromInbound` (or passing the same context
|
||||
to `updateLastRoute`).
|
||||
The origin fields are populated for direct messages, channels, and groups. If a
|
||||
connector only updates delivery routing (for example, to keep a DM main session
|
||||
fresh), it should still provide inbound context so the session keeps its
|
||||
explainer metadata. Extensions can do this by sending `ConversationLabel`,
|
||||
`GroupSubject`, `GroupChannel`, `GroupSpace`, and `SenderName` in the inbound
|
||||
context and calling `recordSessionMetaFromInbound` (or passing the same context
|
||||
to `updateLastRoute`).
|
||||
|
||||
Reference in New Issue
Block a user