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}