Sessions
A session is one continuous conversation between an agent and a user. Sonzai uses session boundaries to scope fact extraction, consolidation, and recall.
What a Session Is
A session is one continuous conversation between an agent and a user, identified by a session_id you control. Sessions are Sonzai's unit of consolidation: when a session ends, the platform extracts facts from the transcript, tags every fact with its source session_id, and runs the memory pipeline (dedup, cluster, decay) before the next session begins.
Sessions are not a wrapper around individual messages — they're how Sonzai knows which messages belong together for extraction. A session can last seconds or days.
You always have a session
Every /chat call belongs to a session. If you don't start one explicitly, the platform creates one for you. Session IDs flow through to extracted facts either way — you never lose attribution.
Two Ways to Use Sessions
Auto-session (simplest)
Just call agents.chat without touching the sessions API. The platform creates a session on the first message, keeps it open while the conversation is active, and closes it automatically when the conversation goes idle. This is the right default for most apps.
Explicit session
Call sessions.start before the first message and sessions.end when the conversation is definitively over. Use this when you need to:
- Register custom tools for a specific conversation (
tool_definitionsonsessions.start). - Control boundary timing — e.g. end a coaching call exactly when the user hangs up, not when the idle timer fires.
- Replay historical transcripts — pass the full message list to
sessions.end(messages=...)to ingest a canned conversation verbatim, which is how data migration and benchmarks work. - Scope memory extraction around a meaningful unit (a support case, a daily stand-up, a D&D game night).
Session Lifecycle
1. sessions.start — Register session_id (+ optional tools); get ready to accept messages
2. agents.chat (× N) — Stream turns through the session; facts extracted inline
3. sessions.end — Close the session; triggers consolidation, dedup, diary, clustering
→ every extracted fact carries this session_id
If you skip step 1, the first agents.chat call will auto-register a session. If you skip step 3, the session closes on idle timeout (configurable per tenant).
Starting and Ending a Session
import { Sonzai } from "@sonzai-labs/agents";
const sonzai = new Sonzai({ apiKey: process.env.SONZAI_API_KEY! });
const AGENT_ID = "agent_abc";
const USER_ID = "user_123";
const SESSION_ID = crypto.randomUUID();
// 1. Start
await sonzai.agents.sessions.start(AGENT_ID, {
user_id: USER_ID,
session_id: SESSION_ID,
user_display_name: "Mia",
});
// 2. Chat turns
const reply = await sonzai.agents.chat({
agent: AGENT_ID,
user_id: USER_ID,
session_id: SESSION_ID,
messages: [{ role: "user", content: "Hi, quick question..." }],
});
// 3. End — triggers fact extraction + consolidation
await sonzai.agents.sessions.end(AGENT_ID, {
user_id: USER_ID,
session_id: SESSION_ID,
total_messages: 2,
});Session IDs on Extracted Facts
Every fact Sonzai extracts carries its source session_id and source_id. You can use these to:
- Reconstruct a conversation's memory footprint — "what did the agent learn from session X?" via
GET /memory/timeline(grouped by session) orGET /memory/facts(filter client-side bysession_id). - Score retrieval at session granularity — benchmarks like LongMemEval evaluate whether retrieved facts come from the correct source session.
- Surface recency context — "conversations from last Tuesday" resolves via the session's
created_atplus its attributed facts.
Facts that exist outside a specific conversation — agent-global wisdom, manually inserted facts, migrated priming content — carry empty session_id and are attributed through source_type instead (e.g. "manual", "agent_global").
Registering Session-Scoped Tools
Custom tool definitions can be scoped to a single session. Pass them on sessions.start, or update them mid-session via sessions.set_tools. Character-level (agent-wide) tools are always merged in — session tools layer on top for the duration of the session.
sonzai.agents.sessions.start(
AGENT_ID,
user_id=USER_ID,
session_id=SESSION_ID,
tool_definitions=[
{
"name": "check_patient_chart",
"description": "Read the active patient's medication list.",
"parameters": {
"type": "object",
"properties": {"patient_id": {"type": "string"}},
"required": ["patient_id"],
},
}
],
)Tool names starting with sonzai_ are reserved for platform-built-in tools.
When to Be Explicit
| Situation | Auto-session | Explicit start / end |
|---|---|---|
| Simple chat app, one conversation per user per day | ✅ | — |
| Multi-session app (support cases, tickets, coaching calls) | — | ✅ |
| Need per-session custom tools | — | ✅ (pass tool_definitions on start) |
| Replaying a canned transcript (migration, eval, benchmark) | — | ✅ (pass messages on end) |
| Want consolidation to fire on your trigger, not idle timeout | — | ✅ |
| Voice calls with well-defined start/end signals | — | ✅ |
What Happens on sessions.end
The end call is where Sonzai does its heavy lifting. In the background, the platform runs:
- Fact extraction from the transcript with coverage validation.
- Grounding verification — every fact is checked against the actual messages to prevent hallucinated memories.
- Session-end consolidation — a session summary is stored; facts are deduped against existing memory via SPO triples and embedding similarity.
- Clustering + polarity checks — new facts find their thematic cluster; contradictions are flagged.
- Diary and insights (if enabled) — the agent's internal narrative is updated.
None of this blocks the sessions.end response — it's asynchronous. The call returns as soon as the transcript is queued.
What's next
- Conversations — the chat lifecycle and streaming.
- Memory — how extracted facts are organized.
- Sessions API reference — endpoint schemas.
Custom State
Per-user counters, flags, and strings the agent reads and writes — energy, currency, progress flags, game state — with a stable schema you control.
Conversations
Send messages to an agent and stream back responses over SSE — the primary loop that drives memory, mood, and personality evolution with every turn.