rune-chain-agent 0.1.0

ReAct agent loop for rune-chain: LLM + tools + scratchpad reasoning
Documentation
//! ReAct agent loop for `rune-chain`: LLM reasoning + tool invocation + scratchpad.
//!
//! `rune-chain-agent` implements the ReAct (Reasoning + Acting) pattern from the paper
//! [ReAct: Synergizing Reasoning and Acting in Language Models](https://arxiv.org/abs/2210.03629).
//! The agent sends the user's question to an LLM, parses the response for a tool call,
//! executes the tool, feeds the result back as an observation, and repeats until the LLM
//! produces a `Final Answer:` or the iteration limit is reached.
//!
//! # Features
//!
//! - [`AgentExecutor`] — configurable ReAct loop with any [`rune_chain_core::Llm`] backend
//! - [`AgentResult`] — structured output: final answer, iteration count, full scratchpad
//! - Implements [`rune_chain_core::Chain`] so agents compose with sequential and conversational chains
//! - Tool dispatch via [`rune_chain_core::Tool`] — synchronous, zero-allocation tool runs
//! - Automatic system prompt generation from registered tools
//! - Configurable `max_iterations` guard prevents runaway loops
//!
//! # Quick Start
//!
//! ```rust,no_run
//! use std::sync::Arc;
//! use rune_chain_core::{Llm, Tool};
//! use rune_chain_agent::AgentExecutor;
//!
//! struct Upper;
//! impl Tool for Upper {
//!     fn name(&self) -> &str { "upper" }
//!     fn description(&self) -> &str { "Converts text to upper case." }
//!     fn run(&self, input: &str) -> String { input.to_uppercase() }
//! }
//!
//! # async fn run() -> Result<(), rune_chain_core::ChainError> {
//! # let llm: Arc<dyn Llm> = unimplemented!();
//! let agent = AgentExecutor::new(llm)
//!     .tool(Upper)
//!     .max_iterations(5);
//!
//! let result = agent.run("Convert 'hello' to upper case.").await?;
//! println!("Answer: {}", result.output);
//! println!("Iterations: {}", result.iterations);
//! # Ok(())
//! # }
//! ```
//!
//! # Using as a `Chain`
//!
//! [`AgentExecutor`] implements [`rune_chain_core::Chain`], so it can slot into any
//! chain composition that expects a `Chain`:
//!
//! ```rust,no_run
//! use std::sync::Arc;
//! use rune_chain_core::{Chain, Llm, prompt_args};
//! use rune_chain_agent::AgentExecutor;
//!
//! # async fn run() -> Result<(), rune_chain_core::ChainError> {
//! # let llm: Arc<dyn Llm> = unimplemented!();
//! let agent = AgentExecutor::new(llm);
//! let output = agent.invoke(prompt_args! { "input" => "What is 2 + 2?" }).await?;
//! println!("{output}");
//! # Ok(())
//! # }
//! ```
//!
//! # ReAct Format
//!
//! The agent instructs the LLM to follow this scratchpad format:
//!
//! ```text
//! Thought: <reason about what to do>
//! Action: <tool_name>
//! Action Input: <input to the tool>
//! Observation: <result of the action>
//! ... (repeat as needed)
//! Thought: I now have enough information.
//! Final Answer: <your final answer>
//! ```

pub mod agent;

pub use agent::{AgentExecutor, AgentResult};