An agent: model + instructions + tools + output spec, runnable as a loop that alternates between calling the model and executing tools until a final result is produced.
This is the heart of the framework. It follows a small loop:
UserPromptNode → ModelRequestNode ⇄ CallToolsNode → EndIt is implemented as idiomatic Elixir recursion. Each recursive step issues a
model request or handles returned tool calls; termination happens when the
model returns a valid final response (no tool calls) or an empty response with
allow_text_output.
Quick start
alias ExAgent
agent =
ExAgent.new(
model: "test",
instructions: "Be concise."
)
{:ok, %{output: text}} = ExAgent.run(agent, "Hello!")
Summary
Functions
Build an agent from options. Use :output for the output spec.
Run the agent against prompt, returning {:ok, result} or {:error, _}.
Run synchronously and return the output value directly, raising on error.
Run the agent, returning a lazy stream of events as the model generates.
Types
@type output_type() :: :text | module()
@type result() :: %{ output: term(), messages: [ExAgent.Message.t()], new_messages: [ExAgent.Message.t()], usage: ExAgent.Message.Usage.t(), run_step: non_neg_integer() }
@type t() :: %ExAgent{ capabilities: [module() | struct()], instructions: [ExAgent.Message.Part.System.t()], model: ExAgent.Model.model(), name: String.t() | nil, output_retries: non_neg_integer(), output_type: output_type(), settings: ExAgent.ModelSettings.t(), tool_timeout: pos_integer(), tools: [ExAgent.Tool.t()], usage_limits: ExAgent.UsageLimits.t() | nil }
Functions
Build an agent from options. Use :output for the output spec.
Run the agent against prompt, returning {:ok, result} or {:error, _}.
Options:
:deps— dependency value threaded intoRunContext.:message_history— priorMessage.t()list to continue from.:model_settings— per-run settings overrides.
Run synchronously and return the output value directly, raising on error.
@spec run_stream(t(), String.t(), keyword()) :: Enumerable.t()
Run the agent, returning a lazy stream of events as the model generates.
This is the streaming variant. It yields:
{:delta, binary}— incremental output text (one per model text chunk),{:result, map}— the final result once the stream completes.
It is text-focused: best suited to chat / response-streaming UIs. Tool calls
emitted mid-stream are not re-executed in this path (use run/3 for full
agentic tool loops). The same per-run options as run/3 apply.