ExAgent.Session.SharedState (ExAgent v0.3.0)

Copy Markdown View Source

A handle placed in RunContext.deps so tools running inside an agent run can read the session's shared state and propose changes — without ever holding a mutable reference to it.

This enforces the Session's single-writer rule: a tool never mutates the world directly. It reads through SharedState.read/1 and proposes a change through SharedState.propose_change/2, which the Session validates (it must be the owning participant's turn) and applies atomically.

Wiring

Build the handle when you start the agent's run for a participant, and pass it as deps:

handle = ExAgent.Session.SharedState.new(session, "dm")
ExAgent.Server.chat(dm_server, "narrate the scene", deps: handle)

Inside a tool:

deftool set_scene(ctx, description :: String.t()) do
  {:ok, _new_state} =
    ExAgent.Session.SharedState.propose_change(ctx.deps, fn s ->
      {:ok, %{s | scene: description}}
    end)

  {:ok, "scene updated"}
end

Summary

Functions

Build a handle for participant_id operating on session.

Propose a change to the shared state. The Session applies change_fn atomically only if it's this participant's turn; otherwise it returns {:error, :not_your_turn}. Does not advance the turn (use Session.end_turn/2 when the participant is done).

Read the current shared state (read-only; anyone may read).

Types

t()

@type t() :: %ExAgent.Session.SharedState{
  participant_id: term(),
  session: GenServer.server()
}

Functions

new(session, participant_id)

@spec new(GenServer.server(), term()) :: t()

Build a handle for participant_id operating on session.

propose_change(shared_state, change_fn)

@spec propose_change(t(), (term() -> {:ok, term()} | {:error, term()} | term())) ::
  {:ok, term()} | {:error, term()}

Propose a change to the shared state. The Session applies change_fn atomically only if it's this participant's turn; otherwise it returns {:error, :not_your_turn}. Does not advance the turn (use Session.end_turn/2 when the participant is done).

read(shared_state)

@spec read(t()) :: term()

Read the current shared state (read-only; anyone may read).