pub trait Tool: Send + Sync {
// Required methods
fn descriptor(&self) -> ToolDescriptor;
fn execute<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
args: Value,
ctx: &'life1 ToolCallContext<'life2>,
) -> Pin<Box<dyn Future<Output = Result<ToolResult, ToolError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
// Provided methods
fn validate_args(&self, args: &Value) -> Result<(), ToolError> { ... }
fn execute_effect<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
args: Value,
_ctx: &'life1 ToolCallContext<'life2>,
) -> Pin<Box<dyn Future<Output = Result<ToolExecutionEffect, ToolError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
}Expand description
Tool trait for implementing agent tools.
§Example
ⓘ
use tirea::contracts::runtime::tool_call::{Tool, ToolDescriptor, ToolExecutionEffect, ToolResult};
use tirea::contracts::runtime::state::AnyStateAction;
use tirea::contracts::ToolCallContext;
use tirea_state::State;
#[derive(State)]
struct MyToolState {
pub count: i64,
}
enum MyToolAction {
Increment,
}
struct CounterTool;
#[async_trait]
impl Tool for CounterTool {
fn descriptor(&self) -> ToolDescriptor {
ToolDescriptor::new("counter", "Counter", "Increment a counter")
}
async fn execute(
&self,
args: Value,
ctx: &ToolCallContext<'_>,
) -> Result<ToolResult, ToolError> {
let current = ctx
.snapshot_of::<MyToolState>()
.map(|state| state.count)
.unwrap_or(0);
Ok(ToolExecutionEffect::from(
ToolResult::success("counter", json!({"count": current + 1}))
).with_action(
AnyStateAction::new::<MyToolState>(MyToolAction::Increment)
))
}
}Required Methods§
Sourcefn descriptor(&self) -> ToolDescriptor
fn descriptor(&self) -> ToolDescriptor
Get the tool descriptor.
Provided Methods§
Sourcefn validate_args(&self, args: &Value) -> Result<(), ToolError>
fn validate_args(&self, args: &Value) -> Result<(), ToolError>
Validate tool arguments against the descriptor’s JSON Schema before execution.
The default implementation uses validate_against_schema with
descriptor().parameters. Override to customise or skip validation.
Sourcefn execute_effect<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
args: Value,
_ctx: &'life1 ToolCallContext<'life2>,
) -> Pin<Box<dyn Future<Output = Result<ToolExecutionEffect, ToolError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn execute_effect<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
args: Value,
_ctx: &'life1 ToolCallContext<'life2>,
) -> Pin<Box<dyn Future<Output = Result<ToolExecutionEffect, ToolError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Execute tool and return structured effects.
The default implementation delegates to Tool::execute and wraps the
result without converting any context writes into state actions.
Tools that mutate persisted state should override this method and emit
explicit typed actions via AnyStateAction::new....