Skip to main content

Loop

Trait Loop 

Source
pub trait Loop: Send + Sync {
    // Required methods
    fn run<'a>(
        &'a mut self,
        input: &'a str,
        run_config: &'a RunConfig,
    ) -> Pin<Box<dyn Future<Output = RunResult> + Send + 'a>>;
    fn should_continue(&self) -> bool;
    fn finalize<'a>(
        &'a mut self,
        error: Option<&'a LoopError>,
    ) -> Pin<Box<dyn Future<Output = RunResult> + Send + 'a>>;
    fn state(&self) -> MachineState;
    fn cancel(&self);

    // Provided method
    fn stop_reason(&self) -> Option<LoopError> { ... }
}
Expand description

The core agent lifecycle trait.

Implement this trait to create a new type of agent. The framework provides shared infrastructure for context management, tool execution, reflection, and observability, so implementations only need to define the core processing logic.

§Example

use loopctl::engine::core::Loop;
use loopctl::engine::RunConfig;
use loopctl::engine::core::{MachineState, Run};
use loopctl::error::LoopError;

struct MyAgent {
    state: MyState,
}

impl Loop for MyAgent {
    fn run<'a>(
        &'a mut self,
        input: &'a str,
        run_config: &'a RunConfig,
    ) -> Pin<Box<dyn Future<Output = RunResult> + Send + 'a>> {
        Box::pin(async { Ok(loopctl::engine::core::Run::new(input, &Default::default())) })
    }
    fn should_continue(&self) -> bool {
        !self.state.is_complete
    }
    fn finalize<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = RunResult> + Send + 'a>> {
        Box::pin(async { Ok(loopctl::engine::core::Run::new("", &Default::default())) })
    }
    fn state(&self) -> MachineState {
        MachineState::Start
    }
    fn cancel(&self) {}
}

Required Methods§

Source

fn run<'a>( &'a mut self, input: &'a str, run_config: &'a RunConfig, ) -> Pin<Box<dyn Future<Output = RunResult> + Send + 'a>>

Drive one run of the agent loop for the given user prompt.

This is the main entry point for running an agent. Session-scoped state (identity, start time, system prompt) is established once at construction and stays stable across calls; each run() receives a fresh RunConfig for the per-run budget and policy, mints a new Run, and drives the turn loop until the model finishes or the budget is exhausted.

input is the prompt for this run. It is passed to the first turn; continuation turns receive an empty string (tool results are already in the conversation history).

§Errors
Source

fn should_continue(&self) -> bool

Check whether the agent should continue processing turns.

Called after each turn. Return false to end the session.

Source

fn finalize<'a>( &'a mut self, error: Option<&'a LoopError>, ) -> Pin<Box<dyn Future<Output = RunResult> + Send + 'a>>

Finalize the agent run and produce its result.

Called once after the last turn. Use this to clean up resources and produce a final Run.

Source

fn state(&self) -> MachineState

Get the current state of the agent.

Used by the framework to drive the state machine and by observers to report status.

Source

fn cancel(&self)

Cancel the agent’s current operation.

Implementations must use thread-safe interior mutability (e.g. AtomicBool, Mutex<bool>) to store the cancellation flag, since this method takes &self. The flag should be set in a non-blocking fashion so that run and should_continue can observe it and return promptly across threads.

Provided Methods§

Source

fn stop_reason(&self) -> Option<LoopError>

Explain why should_continue returned false.

Return None for normal completion (the model finished) or Some(err) when the session was forced to stop (Cancelled, MaxTurnsExceeded, etc.). The default implementation returns None (normal completion).

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§