Skip to main content

Agent

Struct Agent 

Source
pub struct Agent {
    pub history: Box<dyn History>,
    /* private fields */
}
Expand description

Agent loop that coordinates LLM calls and tool execution. Uses ParallelExecutor by default.

Fields§

§history: Box<dyn History>

Implementations§

Source§

impl Agent

Source

pub fn new(llm: impl LLMProvider + 'static) -> Self

Create a new agent loop

Source

pub fn history(self, history: impl History + 'static) -> Self

Set custom history manager (default: InfiniteHistory)

§Example
use tiny_loop::{Agent, history::InfiniteHistory, llm::OpenAIProvider};

let agent = Agent::new(OpenAIProvider::new())
    .history(InfiniteHistory::new());
Source

pub fn system(self, content: impl Into<String>) -> Self

Append a system message

§Example
use tiny_loop::{Agent, llm::OpenAIProvider};

let agent = Agent::new(OpenAIProvider::new())
    .system("You are a helpful assistant");
Source

pub fn tools(&self) -> &[ToolDefinition]

Get reference to registered tool definitions

Source

pub fn executor(self, executor: impl ToolExecutor + 'static) -> Self

Set a custom tool executor (default: ParallelExecutor)

§Example
use tiny_loop::{Agent, tool::SequentialExecutor, llm::OpenAIProvider};

let agent = Agent::new(OpenAIProvider::new())
    .executor(SequentialExecutor::new());
Source

pub fn tool<Args, Fut>(self, tool: fn(Args) -> Fut) -> Self
where Fut: Future<Output = String> + Send + 'static, Args: ToolArgs + 'static,

Register a tool function created by #[tool]

To register a tool method with an instance, use Self::bind. To register external tools (e.g. from MCP servers) use Self::external

§Example
use tiny_loop::{Agent, tool::tool, llm::OpenAIProvider};

#[tool]
async fn fetch(
    /// URL to fetch
    url: String,
) -> String {
    todo!()
}

let agent = Agent::new(OpenAIProvider::new())
    .tool(fetch);
Source

pub fn bind<T, Args, Fut>(self, ins: T, tool: fn(T, Args) -> Fut) -> Self
where T: Send + Sync + Clone + 'static, Fut: Future<Output = String> + Send + 'static, Args: ToolArgs + 'static,

Bind an instance to a tool method created by #[tool]

To register a standalone tool function, use Self::tool. To register external tools (e.g. from MCP servers) use Self::external

§Example
use tiny_loop::{Agent, tool::tool, llm::OpenAIProvider};
use std::sync::Arc;

#[derive(Clone)]
struct Database {
    data: Arc<String>,
}

#[tool]
impl Database {
    /// Fetch data from database
    async fn fetch(
        self,
        /// Data key
        key: String,
    ) -> String {
        todo!()
    }
}

let db = Database { data: Arc::new("data".into()) };
let agent = Agent::new(OpenAIProvider::new())
    .bind(db, Database::fetch);
Source

pub fn external<Fut>( self, defs: Vec<ToolDefinition>, exec: impl Fn(String, String) -> Fut + Clone + Send + Sync + 'static, ) -> Self
where Fut: Future<Output = String> + Send + 'static,

Register external tools (e.g. from MCP servers)

To register a standalone tool function, use tool. To register a tool method with an instance, use bind.

§Example
use tiny_loop::{Agent, llm::OpenAIProvider, types::{Parameters, ToolDefinition, ToolFunction}};
use serde_json::{json, Value};

let defs = vec![ToolDefinition {
    tool_type: "function".into(),
    function: ToolFunction {
        name: "get_weather".into(),
        description: "Get weather information".into(),
        parameters: Parameters::from_object(
            json!({
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "City name"
                    }
                },
                "required": ["city"]
            }).as_object().unwrap().clone()
        ),
    },
}];

let external_executor = move |name: String, args: String| {
    async move {
        let _args = serde_json::from_str::<Value>(&args).unwrap();
        "result".into()
    }
};

let agent = Agent::new(OpenAIProvider::new())
    .external(defs, external_executor);
Source

pub async fn step(&mut self) -> Result<Option<String>>

Execute one iteration of the agent loop. Returns Ok(Some(content)) if loop should terminate, Ok(None) to continue

This is usually used to customize the agent loop.

§Example
use tiny_loop::{Agent, llm::OpenAIProvider};

let mut agent = Agent::new(OpenAIProvider::new())
    .system("You are a helpful assistant");

// Custom loop with early break
let mut iterations = 0;
loop {
    println!("Before step {}", iterations);
     
    if let Some(content) = agent.step().await? {
        println!("Completed: {}", content);
        break;
    }
     
    iterations += 1;
    if iterations > 10 {
        println!("Max iterations reached");
        break;
    }
}
Source

pub async fn run(&mut self) -> Result<String>

Run the agent loop until completion. Return the last AI’s response

Source

pub async fn chat(&mut self, prompt: impl Into<String>) -> Result<String>

Run the agent loop with a new user input appended. Return the last AI’s response

Auto Trait Implementations§

§

impl Freeze for Agent

§

impl !RefUnwindSafe for Agent

§

impl !Send for Agent

§

impl !Sync for Agent

§

impl Unpin for Agent

§

impl !UnwindSafe for Agent

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more