These docs track the main branch and may describe unreleased features. The stable documentation lives at docs.docker.com.

Sessions

How Docker Agent stores conversations, resumes them across runs, and tracks their token cost.

What a Session Is

Every docker agent run creates or resumes a session: the record of a conversation, including every message, tool call, sub-agent run, and cost. Sessions are what makes /undo, /sessions, --session <id>, and cost tracking possible — the agent itself is stateless between runs, but the session is not.

A session is only persisted to disk once it has content (the first message added), so a run you cancel before sending anything never leaves an empty session behind.

Where Sessions Are Stored

Sessions live in a SQLite database, session.db, under the data directory (~/.cagent by default):

$ ls ~/.cagent/session.db

Override the location with -s/--session-db, or by overriding the data directory itself with --data-dir:

# Use a project-local session database instead of the global one
$ docker agent run agent.yaml --session-db ./sessions.db

Generated Media Files

Some models (e.g. Gemini image-output models) can generate an image as part of a reply. Docker Agent saves each generated image into the session's workspace as an ordinary, untracked file. After the file and its manifest entry are saved, it stores a portable copy in session.db. Reopening or moving the session can therefore render the original generated bytes even when the workspace file was edited, moved, or deleted. If the portable-copy write fails, the workspace file is kept and the turn carries a warning. Ordinary follow-up turns replace generated-media parts with metadata placeholders rather than resending the bytes. User attachments are unaffected; explicitly attaching the file or reading it through a tool can send its contents to a model. The workspace file remains yours to edit, commit, or delete.

Existing session databases are upgraded in place when a newer Docker Agent opens them. The database now carries portable generated-media bytes as well as session records; an older binary may not understand the upgraded schema. Do not assume a database opened by a newer version remains readable by an older version. Sessions created before portable copies were introduced continue to render through their manifest-gated workspace files. Historical manifest entries for files outside the workspace are rejected. An unrecorded path is never read. Every resolution rechecks the current manifest, so deleting a session revokes its references even if workspace provenance is cached. A legacy workspace file that was deleted, replaced by a symlink, made invalid, or cannot be read appears as a short "unavailable" note. Manifest and containment checks do not verify the integrity of ordinary-file contents, which may have changed. Generated-media storage and resolution have no byte cap. Deleting a session also deletes its stored generated-media blobs. See Generated Media for naming, collision handling, and rendering details.

Resuming a Session

Pass --session <id> to continue a previous conversation instead of starting a new one:

# Resume by explicit session ID
$ docker agent run agent.yaml --session 3f9c1e2a-...

# Resume the most recently created session
$ docker agent run agent.yaml --session -1

# Resume the session created before that one
$ docker agent run agent.yaml --session -2

--session accepts two kinds of reference:

Read-Only Sessions

Add --session-read-only to open a session for viewing without sending new messages — useful for reviewing a past conversation without accidentally continuing it:

$ docker agent run agent.yaml --session -1 --session-read-only

--session-read-only requires the TUI: it cannot be combined with --exec, since there would be nothing to display without one.

Browsing Sessions in the TUI

Press /sessions to open the session browser: search and filter past conversations, see which ones were started in the current working directory ("This workspace") versus elsewhere ("Other locations"), and restore one with Enter. Restoring a session reopens it in its original working directory. See Session Management in the Terminal UI docs for the full set of session-browser and session-title features (starring, branching by editing a past message, and so on).

Tabs

Ctrl+T opens a new tab running an additional agent session alongside the current one; Ctrl+N/Ctrl+P cycle between tabs and Ctrl+W closes the current one. By default, tabs are not restored the next time you launch the TUI. Set restore_tabs: true in your user config to reopen the same tabs (and their sessions) on the next launch:

# ~/.config/cagent/config.yaml
settings:
  restore_tabs: true

Session Titles

Docker Agent auto-generates a short title for each session from your first message, using a one-shot call to the agent's own model. Point that call at a smaller, cheaper model instead with title_model on a model definition:

# examples/title_model.yaml
models:
  primary:
    provider: anthropic
    model: claude-sonnet-4-5
    # Generate session titles with the cheaper Haiku model instead of Sonnet.
    title_model: fast
  fast:
    provider: anthropic
    model: claude-haiku-4-5

agents:
  root:
    model: primary
    description: An assistant that generates session titles with a cheaper model.
    instruction: You are a helpful assistant.

When title_model is omitted, title generation reuses the agent's own model. Set or regenerate a title from inside the TUI with /title (see Session Title Editing) — regenerating sends every user message in the session so far, not just the first — or generate one from the command line without starting a session at all:

$ docker agent debug title agent.yaml "How do I configure a fallback model?"

See docker agent debug title for details.

Usage & Cost Tracking

Every tracked model call — the main conversation turns and compaction calls — updates the session's cumulative input/output token counts and cost. Check them at any time with /cost in the TUI, or disable tracking per-model with track_usage: false if you don't want a model's calls counted (for example, a free local model). Auxiliary one-shot calls the runtime makes on your behalf, such as automatic session-title generation, call the model directly and are not folded into this total.

Cost is computed from the models.dev pricing catalogue by default. For a custom endpoint, a private deployment, or a negotiated enterprise rate the catalogue doesn't know about, declare pricing explicitly with a model's cost: block:

# examples/custom-pricing.yaml
models:
  internal-gpt:
    provider: internal-llm
    model: gpt-4o
    cost:
      input: 1.25 # USD per 1M input tokens
      output: 5.00 # USD per 1M output tokens
      cache_read: 0.125 # USD per 1M cached input tokens
      cache_write: 1.5625 # USD per 1M cache-write tokens

An all-zero cost: table means "priced, free" — distinct from a model with no cost: at all, which falls back to the catalogue (and bills $0 for models the catalogue doesn't know).

Cost never decreases

A session's cumulative cost is a running total updated after every tracked model call — the same main conversation turns and compaction calls described above. Compacting the conversation (manually with /compact, or automatically — see the agent's session_compaction/compaction_threshold fields in the Agent Config reference) reshapes the message history sent back to the model, but never touches this running total. Auxiliary one-shot calls such as automatic session-title generation are not tracked and are not reflected in this total: /cost covers everything the session's tracked calls have spent, not literally every model call the runtime makes on your behalf.

Resuming Into a Worktree

A session created during a --worktree run remembers which worktree it used. Resuming it with --session reattaches to the same worktree directory and branch automatically — you don't need to pass --worktree again. See --worktree in the CLI reference for the full worktree lifecycle.