---
title: "Sessions"
description: "Realm-scoped session lifecycle with deterministic concurrency and cross-surface consistency."
icon: "arrows-rotate"
---

Sessions are realm-scoped. A session is visible across surfaces only when they use the same `realm_id`.

## Lifecycle

| Operation | What it does |
|-----------|-------------|
| `create_session` | Build an agent, run first turn, persist session metadata |
| `start_turn` | Continue existing session; returns `SESSION_BUSY` if a turn is already running |
| `interrupt` | Cancel in-flight turn |
| `read` | Return session state + usage |
| `read_history` | Return committed transcript messages with optional pagination |
| `list` | List sessions in the active realm |
| `archive` | Remove the live runtime handle and hide the session from normal listing while preserving committed history for later reads |

## Realm visibility rules

| Scenario | Result |
|----------|--------|
| CLI + RPC with same `realm_id` | Shared session visibility |
| CLI + RPC with different `realm_id` | Strict isolation |
| 100 RPC servers, no realm provided | Each gets its own isolated realm by default |
| 100 agents, same explicit `realm_id` | Shared state and consistent visibility |

See [realms](/concepts/realms) for default surface behavior.

## Session metadata

Session metadata now carries realm context:

- `realm_id`
- `instance_id`
- `backend`
- `config_generation`

This allows deterministic resume behavior and cross-surface observability.

## Session history

Public surfaces now expose full transcript history separately from lightweight metadata reads.

- REST: `GET /sessions/{id}/history`
- RPC: `session/history`
- MCP: `meerkat_history`
- Python SDK: `read_session_history()`, `Session.history()`, `DeferredSession.history()`
- TypeScript SDK: `readSessionHistory()`, `Session.history()`, `DeferredSession.history()`

History responses return committed messages oldest-to-newest and support `offset` / `limit` pagination. They do not expose in-flight partial output.

Archived sessions still keep their committed transcript history on the normal runtime-backed path. Archiving retires the live runtime handle, blocks further mutation, and can still leave committed state readable depending on the surface/service implementation. It is a lifecycle visibility change, not a history wipe.

## Persistence and backend pinning

Backends are selected once per realm and pinned in `realm_manifest.json`.

| Backend | Notes |
|---------|-------|
| `sqlite` | Durable embedded database; default for new persistent realms when compiled |
| `jsonl` | File-based, inspectable, useful for debugging |

A realm created as `sqlite` stays `sqlite`; a realm created as `jsonl` stays `jsonl`.

## Concurrency guarantees

- One turn per session at a time.
- No implicit queueing for concurrent turns.
- `interrupt()` is explicit cancellation.
- Config writes can be synchronized with generation CAS (`expected_generation`) to avoid lost updates during concurrent operations.
- SQLite-backed realms support the standard same-realm multi-process workflow across CLI, REST, RPC, MCP, and SDK surfaces.

## See also

- [Realms](/concepts/realms)
- [Configuration](/concepts/configuration)
- [Session contracts](/reference/session-contracts)
