Skip to main content

Sessions

A session is one conversation of one person with one application's agent, kept in the application's record: one id a person lists, resumes, hands to another agent, clones, exports and ends — on the web, in loop, from a script. The runtime that runs the application holds a session while it is open; the record is its truth, so a session outlives its runtime and its agent.

What a session is​

FieldMeaning
uidThe session's id, the same on every surface (8 to 128 letters, digits, hyphens or underscores).
stateopen (held by a runtime, a turn may run), paused (nothing runs; held or not) or ended (its code's end ran; the record stays). stopped is no state: posted or read as one, it is refused in a sentence.
turnWhile open, what the runtime does: idle, running or waiting (a question asked).
heldWhether a runtime holds it now.
agent, harnessThe agentspec bound to it now; its harness when the agent runs on one (Claude Code, Codex, OpenCode, pi — see Harness capabilities).
turnsThe person's turns — the cursor a clone is cut at.
title, archivedThe person's title, else the first turn's first line; an archived session is hidden from the list unless asked for.
runs_on{kind: runtime, uid} where it runs when open; null on no runtime.
lineageforked_from: {uid, at_turn} for a clone; imported_from: {digest, exported_at, exported_by, redactions} for an import.

The record keeps the session's shape on its opening entry and says every change of state (paused, ended) and every operation (swapped, cloned, exported, imported, titled) as an entry of its own, so a listing of sessions the runtime no longer holds says the truth.

The operations​

OperationRouteWhat carriesWhat does not
openPOST /api/v1/apps/sessions——
resumePOST /sessions/{uid}/resumeThe whole conversation from the record: turns, tool rows with their displays, the files given (their places in the sandbox re-stated), the session's Rules; then the harness's own session when it can load it (the replay compared with the record, a difference said), else a start-over said in a sentenceA turn that was running (cancelled, said)
swapPOST /sessions/{uid}/agent {agent}The conversation, the files, the Rules, the settings, the workspace; the new agent is told in a sentenceThe harness's own state (kept for a swap back when it can be loaded again), model and effort picks, always answers given to the old harness's tools
clonePOST /sessions/{uid}/clone {up_to_turn?, agent?, title?} → 201, a new uid, pausedThe conversation up to the turn, the files, the RulesThe harness's own session, what came after the turn, the mode (reset to the application's default)
exportGET /sessions/{uid}/export → application/x-ndjsonEvery entry of the record, redacted and counted; the files as entries (name, size, digest, place)Credentials, a signed user, the runtime's addresses, a file's bytes
importPOST /sessions/import (the file as the body) → 201, always a new uid, pausedThe entries, validated one by oneThe source's uid, owner, runtime; an agent the runtime lacks (refused unless ?agent= names one it has)
listGET /sessionsThe caller's sessions, held and recorded, paged (?limit=, ?after=, has_more), filtered (?app=, ?agent=, ?state=, ?q=, ?archived=true)—
endPOST /sessions/{uid}/end——

Every refusal is a sentence that says what to do instead; none falls back to a default the caller did not ask for:

POST /api/v1/apps/sessions/e67a52b2/agent {"agent": "shield-mvp-codex"}
→ 200 {"uid": "e67a52b2", "agent": "shield-mvp-codex", "harness": "codex", "state": "open",
"said": "This conversation was with Claude Code until turn 4; from here it is with Codex. What was said stays; what Claude Code kept for itself waits for a swap back.",
"carried": {"turns": 4, "files": 1, "rules": 2, "settings": ["tone"], "workspace": true},
"dropped": {"allow_always": 1, "harness_state": "kept for a swap back"}}
→ 409 {"detail": "Session e67a52b2 is answering turn 5: swap it when the turn is over, or interrupt it first."}

POST /api/v1/apps/sessions/e67a52b2/clone {"up_to_turn": 7}
→ 422 {"detail": "Session e67a52b2 has 4 turns; there is no turn 7 to clone it at."}

POST /api/v1/apps/sessions/e67a52b2/resume (an ended session)
→ 409 {"detail": "Session e67a52b2 ended; an ended session is not resumed — clone it to go on from it."}

GET /api/v1/apps/sessions?state=stopped
→ 422 {"detail": "There is no session state 'stopped': one of open, paused, ended."}

POST /api/v1/loop/sessions/e67a52b2/agent (the old route)
→ 410 {"detail": "A session's agent is swapped at POST /api/v1/apps/sessions/e67a52b2/agent; this route is gone."}

What a swap says​

The sentence the new agent is told, appended to the conversation and read with its first turn, depends on the old harness's resume capability (see Harness capabilities):

  • This conversation was with Claude Code until turn 4; from here it is with Codex. What was said stays; what Claude Code kept for itself waits for a swap back. — the old harness loads its own session again on a swap back.
  • … what OpenCode kept for itself is gone. — it cannot (resume: none).
  • A swap back to Codex later will start it over. — added when the target's resume is none.

Who may​

The opener, or a host session's linked person signed in as themselves, for every operation; the machine itself on a local runtime. An embed's visitor may neither clone, export nor resume: nothing is kept of them. A stranger's session — an organization's administrator included — is a 404. A pending question answered from any surface first wins; the second answer is a 409.

Where sessions are kept​

Through the session.store point (see Plugins): the platform's record when DATALAYER_AI_AGENTS_URL or DATALAYER_API_KEY is set, a file store (~/.datalayer/sessions/<uid>/entries.jsonl) otherwise; AGENT_RUNTIMES_SESSION_STORE names one (record or file). Naming two, or one nothing contributes, refuses the runtime at start. The harness's own rows — the ACP session id and the vendor's own session id per (session, agent) — stay in the protocol state store.

Not built yet​

  • The phone's session list and deep link.
  • Sharing a session with a second person (clone and export are the owner's alone).
  • Cross-plane import with people mapping; import of a vendor's own transcripts (~/.claude).
  • The harness bench provoking each capability live.
  • Side chats, projects, pins; a follow-up queued mid-turn; credits per session.
  • A clone rebuilding the vendor's own session file; an agent's own child sessions.

See also: loop sessions, the session file, the plugin points and the worked examples, the examples/sessions scripts.