Nous.AgentRunner (nous v0.15.8)
View SourceExecutes agent runs with tool calling loop.
The AgentRunner is responsible for:
- Building messages with system prompts and instructions
- Calling the model via the provider
- Detecting and executing tool calls
- Looping until
needs_responseis false - Extracting and validating output
- Executing callbacks and sending process notifications
Context-Based Execution
The runner uses a Context struct to manage all state during execution:
ctx = Context.new(
deps: %{database: MyDB},
callbacks: %{on_llm_new_delta: fn _, d -> IO.write(d) end},
notify_pid: self()
)Behaviour Integration
Different agent types can customize behavior by implementing
Nous.Agent.Behaviour and setting behaviour_module on the agent.
Summary
Functions
@spec run(Nous.Agent.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}
Run agent to completion.
Options
:deps- Dependencies for tools:message_history- Previous messages:usage_limits- Usage limits (not implemented yet):model_settings- Override model settings:max_iterations- Maximum iterations (default: 10):cancellation_check- Function to check if execution should be cancelled. Understream: true, also invoked between every streamed chunk; on cancellation the consumer aborts cleanly without partial tool execution.:callbacks- Map of callback functions:notify_pid- PID to receive event messages:context- Existing context to continue from:output_type- Override the agent'soutput_typefor this run:structured_output- Override the agent'sstructured_outputoptions for this run:stream- Whentrue, the LLM call streams chunks while still running the tool-call loop (default:false). Fires:on_llm_new_deltaper text chunk and:on_llm_new_thinking_deltaper reasoning chunk.:on_llm_new_messagestill fires once per iteration with the assembled message, identical in shape to the non-streaming path. Works across all providers (OpenAI-compatible, Anthropic, Gemini) and is compatible withoutput_type(the synthetic-tool path is honored under streaming).
@spec run_stream(Nous.Agent.t(), String.t(), keyword()) :: {:ok, Enumerable.t()} | {:error, term()}
Run agent with streaming.
Returns a stream that yields events as they occur.
Events
{:text_delta, text}- Incremental text update{:thinking_delta, text}- Thinking content (reasoning models){:tool_call, call}- Tool is being called{:tool_result, result}- Tool execution completed{:finish, reason}- Stream finished{:complete, result}- Final result
@spec run_with_context(Nous.Agent.t(), Nous.Agent.Context.t(), keyword()) :: {:ok, map()} | {:error, term()}
Run agent with an existing context.
Useful for continuing from a previous run or with pre-built context.