limit_agent/tool.rs
1//! Tool trait and built-in tools for agent execution.
2//!
3//! This module provides the core [`Tool`] trait for defining executable tools
4//! that can be registered with a [`ToolRegistry`](crate::ToolRegistry) and called by AI agents.
5//!
6//! # Defining Custom Tools
7//!
8//! Implement the [`Tool`] trait to create custom tools:
9//!
10//! ```
11//! use async_trait::async_trait;
12//! use limit_agent::{Tool, AgentError};
13//! use serde_json::{json, Value};
14//!
15//! struct CalculatorTool;
16//!
17//! #[async_trait]
18//! impl Tool for CalculatorTool {
19//! fn name(&self) -> &str {
20//! "calculate"
21//! }
22//!
23//! async fn execute(&self, args: Value) -> Result<Value, AgentError> {
24//! let a = args["a"].as_f64().unwrap_or(0.0);
25//! let b = args["b"].as_f64().unwrap_or(0.0);
26//! let op = args["op"].as_str().unwrap_or("+");
27//!
28//! let result = match op {
29//! "+" => a + b,
30//! "-" => a - b,
31//! "*" => a * b,
32//! "/" => a / b,
33//! _ => return Err(AgentError::ToolError("Unknown operator".into())),
34//! };
35//!
36//! Ok(json!({ "result": result }))
37//! }
38//! }
39//! ```
40//!
41//! # Built-in Tools
42//!
43//! - [`EchoTool`] — Simple echo tool for testing, returns its input unchanged
44
45use crate::error::AgentError;
46use async_trait::async_trait;
47use serde_json::Value;
48
49/// Trait for defining executable tools.
50///
51/// Tools are the primary way for AI agents to interact with the world.
52/// Each tool has a name and an async execute method that takes JSON
53/// arguments and returns a JSON result.
54///
55/// # Thread Safety
56///
57/// All tools must be `Send + Sync` because they may be executed concurrently
58/// across multiple threads.
59pub trait Tool: Send + Sync {
60 /// Returns the unique name of this tool.
61 ///
62 /// Tool names should be descriptive and follow a consistent naming
63 /// convention (e.g., `snake_case`).
64 fn name(&self) -> &str;
65
66 /// Executes the tool with the given arguments.
67 ///
68 /// # Arguments
69 ///
70 /// * `args` - JSON value containing the tool parameters. The structure
71 /// depends on the tool's parameter schema.
72 ///
73 /// # Returns
74 ///
75 /// A JSON value containing the tool's output, or an error if execution failed.
76 ///
77 /// # Errors
78 ///
79 /// Returns [`AgentError::ToolError`] if the tool execution fails.
80 fn execute<'life0, 'async_trait>(
81 &'life0 self,
82 args: Value,
83 ) -> ::core::pin::Pin<
84 Box<
85 dyn ::core::future::Future<Output = Result<Value, AgentError>>
86 + ::core::marker::Send
87 + 'async_trait,
88 >,
89 >
90 where
91 'life0: 'async_trait,
92 Self: 'async_trait;
93}
94
95/// A simple echo tool that returns its input unchanged.
96///
97/// Primarily useful for testing the tool registration and execution pipeline.
98pub struct EchoTool;
99
100impl EchoTool {
101 /// Creates a new EchoTool instance.
102 pub fn new() -> Self {
103 EchoTool
104 }
105}
106
107impl Default for EchoTool {
108 fn default() -> Self {
109 Self::new()
110 }
111}
112
113#[async_trait]
114impl Tool for EchoTool {
115 fn name(&self) -> &str {
116 "echo"
117 }
118
119 async fn execute(&self, args: Value) -> Result<Value, AgentError> {
120 // Echo back the input arguments unchanged
121 Ok(args)
122 }
123}