Skip to main content

Session ABI

Socket requests must include session. If the client omits it, runtime uses default.

Request:

{"op":"send","id":"client-msg-id","session":"default","scope":"private","cwd":"/workspace","input":"hello"}

Durable Run IDs

Each production durable send, chat, and repl run ID is independently generated from 128 bits of Linux system entropy and encoded as ctx- followed by exactly 32 lowercase hexadecimal characters. The probability of accidental reuse or collision is negligible. Short r1, run-1, and msg-1 values in examples and tests are illustrative or local labels only, not production-generated durable IDs.

Within one session, retrying send with the same client id, input, scope, and effective cwd replays the original start or recorded final done. Replay does not execute the agent and appends no message, event, or index fact. Reusing an id with a different payload returns EINVAL. Malformed JSONL or a final line without its terminating newline returns EIO; an implementation must not append to or reuse an unprovable history claim.

cwd must be a path inside the agent chroot. If omitted, runtime uses agent/<name>.d/cwd. If cwd does not exist, return ENOENT. If it exists but is outside the visible mount/chroot, return EACCES. A client must not pass a host absolute path to bypass the agent root.

scope has three values:

private default, private to the current Linux uid, resumable
shared stored in shared space, visible to multiple agents or users when allowed
temp temporary session, not required to survive socket close or agent exit

Agent session locations:

private /ctx/home/<uid>/agent/<agent>/session/<session>/
shared /ctx/shared/<name>/agent/<agent>/session/<session>/
temp no durable path required; may live only in process memory

Model session locations:

private /ctx/home/<uid>/model/<model>.d/session/<session>/
shared /ctx/shared/<name>/model/<model>.d/session/<session>/
temp no durable path required

Session Directory

Session directories use ordinary files:

messages.jsonl conversation messages
events.jsonl tool calls, errors, and state changes
latest.md latest assistant text
state active, idle, done, error
cwd session working directory
created_at creation time
updated_at update time
meta.json client, model, scope, and related metadata
AGENTS.md optional run snapshot: effective merged AGENTS.md rules
SKILLS.md optional run snapshot: discovered skill metadata only
context/ rebuildable prompt working set and derived context cache

AGENTS.md and SKILLS.md under the session directory are observability snapshots written when the agent runtime builds the prompt for a run. They are not required session layout files and must not grant authority.

AGENTS.md merged project + global AGENTS.md text injected as {{rules}}
SKILLS.md skill catalog metadata only (name, description, SKILL.md path)

Full skill bodies stay in the original SKILL.md paths listed in SKILLS.md. Snapshots are ordinary files replaced atomically on each run; older runs are not versioned inside the session directory.

ctx agent trajectory <agent> [--session <session>] projects messages.jsonl and events.jsonl to validated ATIF JSON on stdout. Event run and tool-call ids remain the correlation authority for tool calls, observations, and usage. The projection is derived output, not a second durable history or submission path.

Tool results must carry a run and a call id matching a canonical tool_call event. Projection drops unmatched results and never synthesizes a tool call or chat message.

History is session files. Do not add /ctx/history. Context runtime state stays under the session directory. Do not add /ctx/memory, /ctx/context, /ctx/swap, or /ctx/task.

Users can inspect history with ordinary file operations:

ctx agent history coder
ctx agent output coder
less /ctx/home/$(id -u)/agent/coder/session/default/messages.jsonl
cat /ctx/home/$(id -u)/agent/coder/session/default/AGENTS.md
cat /ctx/home/$(id -u)/agent/coder/session/default/SKILLS.md

If --session is omitted, client commands resolve session/index/current first and fall back to default. There is no separate ctx latest command.

Session Index

Reserved index files live under session/index/ to avoid colliding with user session names such as list, current, by-cwd, by-hash, or by-uuid.

session/
index/
list
current
by-cwd/
<hash>
by-hash/
<hash>
by-uuid/
<uuid>
default/
messages.jsonl
events.jsonl
latest.md
state
cwd
created_at
updated_at
meta.json

Index file formats are fixed:

index/list one session name per line, newest updated_at first
index/current single value, current session name
index/by-cwd/<hash> single value, session name for that cwd
index/by-hash/<hash> single value, session name for that external hash
index/by-uuid/<uuid> single value, session name for that external uuid

index/by-cwd/<hash>, index/by-hash/<hash>, and index/by-uuid/<uuid> are not symlinks. That keeps the ABI identical across mounts and different backing stores.

Session garbage collection defaults to a no-write preview. Applying it with --yes archives each eligible live session by same-filesystem RENAME_NOREPLACE to <CTX_HOME>/archived_sessions/<agent>/<session> and removes exact references to that session from index/list, index/by-cwd/, index/by-hash/, and index/by-uuid/. The archive destination never overwrites an existing entry. Permanent deletion is opt-in and requires --delete --yes; --delete without --yes only changes the preview mode. --archive-dir <absolute-path> replaces the default archive root, must not overlap the live session tree, and is invalid with --delete.

ctx agent session archive <agent> <session> [--archive-dir <absolute-path>] applies the same lock, index claim, source claim, no-replace rename, and rollback rules immediately to exactly one eligible session. The archived directory preserves the complete original session tree, including raw messages.jsonl and events.jsonl, without reserialization.

default, index/current, explicit --keep names, and sessions whose plain, bounded state value is active are protected. A missing state remains compatible with legacy sessions; unsafe or unreadable state entries are conservatively protected. GC selects only live session directories and never selects archived entries for a second operation. archived_sessions is an external home directory, not a new root ABI namespace. Destination conflicts or cross-filesystem renames fail without removing the live source, and no recursive copy fallback is allowed. This phase defines no restore command.

Resume is not a root-level feature. Clients read the session index for the current agent:

/ctx/home/1000/agent/coder/session/index/list
/ctx/home/1000/agent/coder/session/index/current
/ctx/home/1000/agent/coder/session/index/by-cwd/<hash>
/ctx/home/1000/agent/coder/session/index/by-hash/<hash>
/ctx/home/1000/agent/coder/session/index/by-uuid/<uuid>

Shared resume reads the matching index under shared. Temp sessions do not appear in resume lists.

Durable sessions do not live in the chroot root:

/ctx/home/<uid>/agent/<agent>/session/<session>/

The chroot root is only the runtime environment:

/ctx/home/<uid>/agent/<agent>/root/

Rebuilding the root, cleaning it, or switching runtime environment must not destroy session history.

Context-window limits, rebuildable prompt working sets, and context compaction rules are defined in agent-runtime.md. Child handoff channels and their durable result files are defined in ctx-coreutils.md.