agent_chain_core/
tools.rs

1//! Tools module for LLM function calling.
2//!
3//! This module provides the `Tool` trait and `#[tool]` macro for creating
4//! tools that can be invoked by AI models.
5
6use async_trait::async_trait;
7use serde::{Deserialize, Serialize};
8
9use crate::messages::{BaseMessage, ToolCall};
10
11// Re-export the tool macro
12pub use agent_chain_macros::tool;
13
14/// Represents a tool's definition for LLM function calling.
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct ToolDefinition {
17    /// The name of the tool
18    pub name: String,
19    /// A description of what the tool does
20    pub description: String,
21    /// JSON schema for the tool's parameters
22    pub parameters: serde_json::Value,
23}
24
25/// A trait for tools that can be invoked by an AI model.
26#[async_trait]
27pub trait Tool: Send + Sync {
28    /// Get the name of the tool.
29    fn name(&self) -> &str;
30
31    /// Get the description of the tool.
32    fn description(&self) -> &str;
33
34    /// Get the JSON schema for the tool's parameters.
35    fn parameters_schema(&self) -> serde_json::Value;
36
37    /// Invoke the tool with the given tool call.
38    async fn invoke(&self, tool_call: ToolCall) -> BaseMessage;
39
40    /// Invoke the tool directly with arguments (without a full ToolCall).
41    /// Returns the result as a JSON value.
42    ///
43    /// This is a convenience method for when you have the args directly.
44    /// The default implementation creates a temporary ToolCall and invokes it.
45    async fn invoke_args(&self, args: serde_json::Value) -> serde_json::Value {
46        let tool_call = ToolCall::new(self.name(), args);
47        let result = self.invoke(tool_call).await;
48        serde_json::Value::String(result.content().to_string())
49    }
50
51    /// Get the tool definition for LLM function calling.
52    fn definition(&self) -> ToolDefinition {
53        ToolDefinition {
54            name: self.name().to_string(),
55            description: self.description().to_string(),
56            parameters: self.parameters_schema(),
57        }
58    }
59}