# Run with: mix run examples/demo.exs
#
# A self-contained demo of the agent loop using the in-process TestModel —
# no API key needed. Shows: instructions, a tool that takes the RunContext
# (dependency injection), and the final structured result.
alias ExAgent.{Tool, RunContext}
alias ExAgent.Message.Part
balance_tool =
Tool.new(
name: "get_balance",
description: "Return the account balance for the current customer.",
parameters_json_schema: %{type: "object", properties: %{}},
takes_ctx: true,
call: fn %RunContext{deps: %{customer_id: id}}, _args ->
{:ok, 123.45 * id}
end
)
# The TestModel is scripted: first it calls the tool, then it writes the final answer.
model = %ExAgent.Models.Test{
script: [
{:tool_calls, [%Part.ToolCall{tool_name: "get_balance", args: %{}}]},
"Your balance is ready. (final answer)"
]
}
agent =
ExAgent.new(
model: model,
instructions: "You are a bank assistant.",
tools: [balance_tool]
)
{:ok, result} = ExAgent.run(agent, "What's my balance?", deps: %{customer_id: 2})
IO.puts("=== OUTPUT ===")
IO.inspect(result.output, label: "output")
IO.puts("\n=== MESSAGE HISTORY ===")
Enum.each(result.messages, fn msg ->
case msg do
%ExAgent.Message.Request{parts: parts} ->
IO.puts("[Request]")
Enum.each(parts, &IO.inspect/1)
%ExAgent.Message.Response{parts: parts} ->
IO.puts("[Response]")
Enum.each(parts, &IO.inspect/1)
end
end)
IO.puts("\n=== USAGE ===")
IO.inspect(result.usage, label: "usage")