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
Condukt.SessionStore.Memorykeeps snapshots in ETS. Useful for restoring state within a running BEAM (for example after aGenServercrash).Condukt.SessionStore.Diskwrites snapshots to disk. Useful for crashing recovery, deployments, and CLIs.
# 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)
endThen 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.