Getting started
View SourceRun an agent without credentials first. This gives you a working application and the result contract before introducing a provider, streaming or persistence.
Install ExAgent 2.2
This guide targets ExAgent 2.2.2. Published 1.x releases have older contracts. Add the published package:
def deps do
[{:exagent, "~> 2.2.2"}]
endFor local source development, use {:exagent, path: "../exAgent"} with the clone
beside your application. See Supported features and limits.
Run mix deps.get, then iex -S mix in your application. The supported runtime
targets are Elixir 1.18 / OTP 28 and Elixir 1.20 / OTP 29. ExAgent starts its own
supervised runtime; a one-shot run needs no database, Phoenix or tracing service.
If your application manages its own environment and credentials, set this in
config/config.exs before application startup:
import Config
config :req_llm, load_dotenv: falseStock ReqLLM otherwise loads .env from the host's working directory.
Run your first agent
agent = ExAgent.new(model: "test", instructions: "Be concise.")
{:ok, result} = ExAgent.run(agent, "Hello!")
%{output: result.output, status: result.status, requests: result.request_count}
# => %{output: "a test response", status: :succeeded, requests: 1}"test" is a deterministic in-process model. It does not interpret the prompt
or call a provider. It exercises the same public loop, so you can build your
application's handling of results before making real requests.
An agent definition is reusable configuration. A run produces history and a possibly updated model; the definition itself does not hold a conversation.
Keep a conversation
For an occasional follow-up, pass the previous history explicitly:
{:ok, first} = ExAgent.run(agent, "Hello!")
{:ok, second} =
ExAgent.run(%{agent | model: first.model}, "And next?",
message_history: first.messages
)
second.outputRetain result.model for stateful model adapters as well as result.messages.
For a supervised conversation with multiple requests, use
Server.
Handle success and failure
An operational failure includes the progress known before it failed:
case ExAgent.run(agent, "Hello!") do
{:ok, result} ->
{:completed, result.output}
{:error, %ExAgent.RunError{reason: reason, partial: partial}} ->
{:failed, reason, partial.status}
endThe failure branch is application handling, not permission to retry a tool. Keep the partial history and outcomes for reconciliation when an effect may already have happened. Invalid construction options can raise before execution. Live results may contain model credentials; log a deliberate projection rather than the whole result or error.
Connect a real model
Resolve a catalogue model for text, or explicitly configure a qualified tools profile. Models and limits explains the difference and shows the constructor. Keep keys in application configuration, outside prompts, source code and serialized results.
Check the endpoint's actual Chat, reasoning, tool and output capabilities before choosing a profile. Catalogue membership alone does not enable those features. See Supported features and limits for the available combinations.
Next steps
- Tools and output: invoke application functions and return an Ecto struct.
- Runtime and events: keep history and update a UI.
- Testing: script model responses and verify effects without network access.