pub struct AgentLoop<P: Provider, C: ContextStrategy> { /* private fields */ }Expand description
The agentic while loop: drives provider + tool + context interactions.
Generic over P: Provider (the LLM backend) and C: ContextStrategy
(the compaction strategy). Hooks and durability are optional.
Implementations§
Source§impl<P: Provider, C: ContextStrategy> AgentLoop<P, C>
impl<P: Provider, C: ContextStrategy> AgentLoop<P, C>
Sourcepub fn new(
provider: P,
tools: ToolRegistry,
context: C,
config: LoopConfig,
) -> Self
pub fn new( provider: P, tools: ToolRegistry, context: C, config: LoopConfig, ) -> Self
Create a new AgentLoop with the given provider, tools, context strategy,
and configuration.
Sourcepub fn add_hook<H: ObservabilityHook + 'static>(&mut self, hook: H) -> &mut Self
pub fn add_hook<H: ObservabilityHook + 'static>(&mut self, hook: H) -> &mut Self
Add an observability hook to the loop.
Hooks are called in order of registration at each event point.
Sourcepub fn set_durability<D: DurableContext + 'static>(
&mut self,
durable: D,
) -> &mut Self
pub fn set_durability<D: DurableContext + 'static>( &mut self, durable: D, ) -> &mut Self
Set the durable context for crash-recoverable execution.
When set, LLM calls and tool executions go through the durable context so they can be journaled, replayed, and recovered by engines like Temporal, Restate, or Inngest.
Sourcepub fn config(&self) -> &LoopConfig
pub fn config(&self) -> &LoopConfig
Returns a reference to the current configuration.
Sourcepub fn tools_mut(&mut self) -> &mut ToolRegistry
pub fn tools_mut(&mut self) -> &mut ToolRegistry
Returns a mutable reference to the tool registry.
Sourcepub async fn run(
&mut self,
user_message: Message,
tool_ctx: &ToolContext,
) -> Result<AgentResult, LoopError>
pub async fn run( &mut self, user_message: Message, tool_ctx: &ToolContext, ) -> Result<AgentResult, LoopError>
Run the agentic loop to completion.
Appends the user message, then loops: call provider, execute tools if needed, append results, repeat until the model returns a text-only response or the turn limit is reached.
When durability is set, LLM calls go through
DurableContext::execute_llm_call and tool calls go through
DurableContext::execute_tool.
Fires HookEvent at each step. If a hook returns
HookAction::Terminate, the loop stops with
LoopError::HookTerminated.
§Errors
Returns LoopError::MaxTurns if the turn limit is exceeded,
LoopError::Provider on provider failures, LoopError::Tool
on tool execution failures, or LoopError::HookTerminated if
a hook requests termination.
Sourcepub async fn run_text(
&mut self,
text: &str,
tool_ctx: &ToolContext,
) -> Result<AgentResult, LoopError>
pub async fn run_text( &mut self, text: &str, tool_ctx: &ToolContext, ) -> Result<AgentResult, LoopError>
Convenience method to run the loop with a plain text message.
Wraps text into a Message { role: User, content: [Text(text)] }
and calls run.
Sourcepub fn builder(provider: P, context: C) -> AgentLoopBuilder<P, C>
pub fn builder(provider: P, context: C) -> AgentLoopBuilder<P, C>
Create a builder with the required provider and context strategy.
All other options have sensible defaults:
- Empty tool registry
- Default loop config (no turn limit, empty system prompt)
- No hooks or durability
Source§impl<P: Provider, C: ContextStrategy> AgentLoop<P, C>
impl<P: Provider, C: ContextStrategy> AgentLoop<P, C>
Sourcepub fn run_step<'a>(
&'a mut self,
user_message: Message,
tool_ctx: &'a ToolContext,
) -> StepIterator<'a, P, C>
pub fn run_step<'a>( &'a mut self, user_message: Message, tool_ctx: &'a ToolContext, ) -> StepIterator<'a, P, C>
Create a step-by-step iterator over the loop.
Unlike run which drives to completion, this
lets you advance one turn at a time, inspect state, inject messages,
and modify tools between turns.
The user message is appended immediately. Call
StepIterator::next to advance.
Sourcepub async fn run_stream(
&mut self,
user_message: Message,
tool_ctx: &ToolContext,
) -> Receiver<StreamEvent>
pub async fn run_stream( &mut self, user_message: Message, tool_ctx: &ToolContext, ) -> Receiver<StreamEvent>
Run the loop with streaming, forwarding StreamEvents through a channel.
Uses provider.complete_stream() instead of provider.complete() for
each LLM turn. When durability is set, falls back to DurableContext::execute_llm_call
(full response) and synthesizes stream events from the result.
Tool execution is handled identically to run.
Fires the same hook events as run(): LoopIteration, PreLlmCall,
PostLlmCall, PreToolExecution, PostToolExecution, and
ContextCompaction.
Returns a receiver that yields StreamEvents. The final
StreamEvent::MessageComplete on the last turn signals the loop
has finished.
§Errors
Errors are sent as StreamEvent::Error on the channel.