GenServer that owns a multi-turn conversation.
A Session is the right abstraction when you want:
- the message history to persist across multiple user turns,
- resumable state across LiveView reconnects,
- streaming deltas broadcast to subscribers,
- an identifiable process pid / name you can monitor.
For one-shot agent runs, use ExAthena.Loop.run/2 directly. For truly
stateless single-turn inference, ExAthena.query/2.
Usage
{:ok, pid} = ExAthena.Session.start_link(
provider: :ollama,
model: "llama3.1",
tools: :all,
cwd: "/path/to/project"
)
{:ok, result} = ExAthena.Session.send_message(pid, "read mix.exs and list deps")
IO.puts(result.text)
ExAthena.Session.stop(pid)Each send_message appends to the session's message list, runs the agent
loop to completion, and returns the final result. Subsequent messages
include the full prior history, so the model has context.
Summary
Functions
Returns a specification to start this module under a supervisor.
Return the current message list (for debugging / persistence).
Resume a session by reading prior events back from a store.
Send a user message; blocks until the loop terminates.
Return the stable session id assigned at start.
Start a session. Accepts the same options as ExAthena.Loop.run/2 plus
Stop the session.
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec messages(GenServer.server()) :: [map()]
Return the current message list (for debugging / persistence).
Resume a session by reading prior events back from a store.
Returns the reconstructed message list. Permissions deliberately do
NOT survive resume — Claude Code's design pattern: each session
re-establishes trust with the host. The caller is expected to feed
the returned messages into a fresh start_link/1 call via
:messages.
@spec send_message(GenServer.server(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}
Send a user message; blocks until the loop terminates.
@spec session_id(GenServer.server()) :: String.t()
Return the stable session id assigned at start.
@spec start_link(keyword()) :: GenServer.on_start()
Start a session. Accepts the same options as ExAthena.Loop.run/2 plus:
:name— GenServer name.:system_prompt— pinned system prompt used on every turn.:store—:in_memory(default),:jsonl, or a custom module implementingExAthena.Sessions.Store. Per-turn events are persisted via the chosen store;resume/2reads them back.
@spec stop(GenServer.server()) :: :ok
Stop the session.