Orchestrates agent execution — creates sessions, runs agents, collects events.
Summary
Functions
Find the agent that should handle the current turn based on transfer history.
Create a new Runner.
Run an agent with a message, returning a list of events.
Run an agent with async streaming — non-blocking, events delivered via messages.
Run an agent with streaming — calls on_event callback for each event as it's produced.
Types
Functions
@spec find_active_agent(ADK.Agent.t(), pid() | nil) :: ADK.Agent.t()
Find the agent that should handle the current turn based on transfer history.
Scans session events backward for the last transfer_to_agent action.
If found, looks up that agent in the agent tree and returns it.
If not found or the target is a non-LLM agent (SequentialAgent, LoopAgent),
returns the root agent.
This mirrors Python ADK's Runner._find_agent_to_run().
Create a new Runner.
Options
:app_name- application name (required):agent- the agent to run (required):session_store- optional{Module, opts}tuple for session persistence:artifact_service- optional{Module, opts}tuple for artifact storage:memory_store- optional{Module, opts}tuple for long-term memory
Examples
iex> agent = ADK.Agent.LlmAgent.new(name: "bot", model: "test", instruction: "Help")
iex> runner = ADK.Runner.new(app_name: "test", agent: agent)
iex> runner.app_name
"test"
Run an agent with a message, returning a list of events.
Examples
iex> agent = ADK.Agent.LlmAgent.new(name: "bot", model: "test", instruction: "Help")
iex> runner = %ADK.Runner{app_name: "test", agent: agent}
iex> events = ADK.Runner.run(runner, "user1", "sess1", %{text: "hi"})
iex> is_list(events)
true
@spec run_async(t(), String.t(), String.t(), map() | String.t(), keyword()) :: {:ok, pid()} | {:error, term()}
Run an agent with async streaming — non-blocking, events delivered via messages.
Spawns a supervised Task that runs the agent with the given on_event callback.
Messages sent to reply_to (default: self()):
{:adk_event, event}for each event (via on_event callback){:adk_done, events}when the run completes{:adk_error, reason}on failure
Returns {:ok, task_pid}.
Examples
{:ok, _pid} = ADK.Runner.run_async(runner, "user1", "sess1", "hi")
receive do
{:adk_event, event} -> IO.inspect(event, label: "event")
{:adk_done, events} -> IO.puts("Done, #{length(events)} events")
end
@spec run_streaming(t(), String.t(), String.t(), map() | String.t(), keyword()) :: [ ADK.Event.t() ]
Run an agent with streaming — calls on_event callback for each event as it's produced.
Events are delivered in real-time via the agent's execution pipeline. The on_event
callback is wired into the execution context so it fires immediately as each event
is generated (model response, tool call, tool result), not after the full run completes.
Runs in a supervised Task under ADK.RunnerSupervisor and sends a {:adk_done, events}
message to the caller when complete. If the supervisor is not running, falls back to
synchronous execution.
Options
Same as run/5 plus:
:on_event—(ADK.Event.t() -> any())callback invoked for each event in real-time:reply_to— pid to send{:adk_done, events}when complete (default:self())
Examples
ADK.Runner.run_streaming(runner, "user1", "sess1", "hi",
on_event: fn event -> IO.inspect(event) end)