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).
Send a user message; blocks until the loop terminates.
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).
@spec send_message(GenServer.server(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}
Send a user message; blocks until the loop terminates.
@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.
@spec stop(GenServer.server()) :: :ok
Stop the session.