🏠 Home ← Docs Index
Open Beta πŸ“– Interactive Reader Raw .md llms.txt

Sessions

Sessions store the conversation history between users and the agent. Each channel conversation gets its own isolated session.

Session Keys

Messages from a chat channel (Discord, Teams, Telegram, Facebook) get the key {channel}:{peerID}. With more than one agent in agents.list, the key starts with the agent the message was routed to: {agentID}:{channel}:{peerID}.

Channel Example Key Scope
Discord DM discord:dm:987654321098765432 Per user
Discord Guild discord:123456789012345678:987654321098765432 Per user in each guild channel (channel ID, then user ID)
MS Teams msteams:19:0123456789abcdef0123456789abcdef@thread.v2 Per conversation: one session for everyone in a group chat or channel, one per user in a 1:1 chat
Telegram telegram:123456789 Per chat
Multi-agent agent-ops:msteams:19:0123456789abcdef0123456789abcdef@thread.v2 As above, per agent

When session.identity_links lists a person's accounts on several channels, all of them use the key of the first account in the list, so they share one session. Each account is written as the channel and the peer ID of its key in the table above, for example telegram:123456789 or discord:dm:987654321098765432 (a Discord DM); upper and lower case are not distinguished.

session:
  identity_links:
    alice: ["telegram:123456789", "discord:dm:987654321098765432"]

Other entry points name their sessions themselves:

Entry point Key Scope
Web UI chat (POST /api/chat) the request's session_id: admin-session, or an admin-… conversation the page created Per named conversation, shared by the browser's tabs
WebSocket on channel web admin-conn-<connection ID>, or an admin-… session ID the client sends Per connection, or per named conversation
WebSocket from other clients the session ID the client sends, else p2p:<peer>:<default agent> Per peer
/api/webhook (and goclaw message) p2p:<peer>:<default agent>; channel web with the gateway token uses admin-session; with subject_ref (a delegated cron agent … job), p2p:<peer>:<default agent>:for:<subject> Per peer, and per person a job acts for
OpenAI-compatible API openai-compat:<client IP> Per client IP
App API app_api:<user>, or app_api:<user>/<session_id> (both URL-escaped) Per employee, and per session the app asks for
Webhook (chat) webhook:<agent>:<type>:<entity> Per object the event is about (merge request, issue, alert); ts-<time> when the payload names none
Subagent run agent:<parent agent>:subagent:job-<time> Per run

Storage Backends

SQLite (GORM)

Persistent storage using the main GoClaw SQLite database. Sessions survive gateway restarts and support transactional updates.

In-Memory

Non-persistent storage for development and testing. All sessions are lost on restart.

Used automatically when the database is unavailable.

Session Lifecycle

  1. Creation: A new session is created on the first message from a peer
  2. Retrieval: Session history is loaded and passed to the agent on each turn
  3. Updates: Each user message and agent response is appended to the history. A session is written by one turn at a time: a second message to the same session waits until the first is answered (see One Turn per Session)
  4. Reset: /new or /reset (session.reset_triggers) clears the session. session.reset (mode: daily with at_hour, or mode: idle with idle_minutes) and session.reset_by_type (per channel) clear sessions automatically; they are off by default
  5. Cleanup: Sessions are not deleted by age. They stay until they are reset. The exception is webhook sessions made for a single event (webhook:<agent>:<type>:ts-…, and the SOP-run logs webhook-sop:…:ts-… and webhook-sop:…:batch-…), removed after 7 days without activity. There is no other pruning: session.maintenance, which was never read, has been removed, and a config that still has it gets a warning at startup.

History Format

Session history uses LangChainGo's MessageContent format:

type Session struct {
    ID       string
    History  []llms.MessageContent
    LastSeen time.Time
}

Each history entry is either:

Tool results stay inside their turn and are never stored. On a later turn the model reads the earlier calls as one line at the start of the reply they belong to, for example [Tool calls behind this reply, recorded by GoClaw; results not kept: datetime {"timezone":"UTC"} Γ—2], so it knows what it has already done. Without that line, some models said they had used no tools and ran the same calls again. The line costs about 15–40 tokens for each earlier reply that used tools (eight distinct calls at most, then a count). The Sessions page and the chat show the reply's text only.

Session Inspection

Via REST API

Both endpoints need the gateway token:

# List all sessions
curl -H "X-Goclaw-Token: $GOCLAW_TOKEN" http://localhost:8080/api/sessions

# Inspect sessions with memory
curl -H "X-Goclaw-Token: $GOCLAW_TOKEN" http://localhost:8080/api/inspect

Via Agent Tools

In a human admin's conversation, the agent has the sessions_list and sessions_history tools. They read any session of the agent, other people's included, so no one else is offered them:

User: Show me all active sessions

Agent: [uses sessions_list tool]
Active sessions:
- discord:123456789012345678:987654321098765432 (12 messages, last seen 5 min ago)
- msteams:19:0123456789abcdef0123456789abcdef@thread.v2 (3 messages, last seen 1 hour ago)

Via Web UI

The Web UI Dashboard shows active sessions with message counts and last activity timestamps.

Session Isolation