Sessions and Persistence

Copy Markdown View Source

Every running agent owns a Condukt.Session: the GenServer that holds conversation history, tool configuration, and runtime options. By default sessions live only for the lifetime of the process. A session store lets you snapshot and restore them.

Built-in stores

# Restore within the current VM
{:ok, agent} =
  MyApp.CodingAgent.start_link(
    session_store:
      {Condukt.SessionStore.Memory, key: {:coding_agent, "/tmp/project"}}
  )

# Persist to disk across restarts
{:ok, agent} =
  MyApp.CodingAgent.start_link(
    cwd: "/tmp/project",
    session_store: Condukt.SessionStore.Disk
  )

# Custom path
{:ok, agent} =
  MyApp.CodingAgent.start_link(
    session_store: {Condukt.SessionStore.Disk, path: "/tmp/condukt.session"}
  )

When a store is configured, Condukt loads the snapshot at start_link/1 and saves a fresh snapshot after every completed turn.

What a snapshot contains

Condukt.SessionStore.Snapshot captures the parts of the session that need to survive a restart: the message history and the configurable options (such as model, system prompt, and cwd). It does not capture transient state like in flight tool calls.

Implementing a store

Implement the Condukt.SessionStore behaviour:

defmodule MyApp.RedisStore do
  @behaviour Condukt.SessionStore

  @impl true
  def load(opts) do
    case Redix.command(MyApp.Redix, ["GET", key(opts)]) do
      {:ok, nil} -> :not_found
      {:ok, blob} -> {:ok, :erlang.binary_to_term(blob)}
      {:error, reason} -> {:error, reason}
    end
  end

  @impl true
  def save(snapshot, opts) do
    Redix.command(MyApp.Redix, ["SET", key(opts), :erlang.term_to_binary(snapshot)])
    :ok
  end

  @impl true
  def clear(opts) do
    Redix.command(MyApp.Redix, ["DEL", key(opts)])
    :ok
  end

  defp key(opts), do: "condukt:" <> Keyword.fetch!(opts, :key)
end

Then plug it into the agent:

MyApp.CodingAgent.start_link(
  session_store: {MyApp.RedisStore, key: "user:42"}
)

Clearing history

Condukt.clear/1 resets the conversation. If a session store is configured, the next save will overwrite the persisted snapshot with the empty state.