pub trait ToolExecutor: Send + Sync {
// Required methods
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
call: &'life1 ToolCall,
) -> Pin<Box<dyn Future<Output = Result<ToolResult, ToolError>> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait;
fn list_tools(&self) -> Vec<ToolSchema>;
// Provided methods
fn execute_with_context<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
call: &'life1 ToolCall,
_ctx: ToolExecutionContext<'life2>,
) -> Pin<Box<dyn Future<Output = Result<ToolResult, ToolError>> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait { ... }
fn tool_guidance(&self) -> Option<String> { ... }
fn tool_mutability(&self, tool_name: &str) -> ToolMutability { ... }
fn call_mutability(&self, call: &ToolCall) -> ToolMutability { ... }
fn tool_concurrency_safe(&self, tool_name: &str) -> bool { ... }
fn call_concurrency_safe(&self, call: &ToolCall) -> bool { ... }
fn call_parallel_classification(
&self,
call: &ToolCall,
) -> (ToolMutability, bool) { ... }
}Expand description
Trait for tool execution backends
This trait defines the interface for executing tool calls and listing available tools. Implementations can wrap tool registries, provide mock tools for testing, or implement custom execution logic.
§Example
use bamboo_agent::agent::core::tools::executor::ToolExecutor;
struct MyExecutor {
tools: HashMap<String, Box<dyn Tool>>,
}
#[async_trait]
impl ToolExecutor for MyExecutor {
async fn execute(&self, call: &ToolCall) -> Result<ToolResult> {
let tool = self.tools.get(&call.function.name)
.ok_or_else(|| ToolError::NotFound(call.function.name.clone()))?;
let args = parse_tool_args(&call.function.arguments)?;
tool.execute(args).await
}
fn list_tools(&self) -> Vec<ToolSchema> {
self.tools.values().map(|t| t.schema()).collect()
}
}Required Methods§
Sourcefn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
call: &'life1 ToolCall,
) -> Pin<Box<dyn Future<Output = Result<ToolResult, ToolError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
call: &'life1 ToolCall,
) -> Pin<Box<dyn Future<Output = Result<ToolResult, ToolError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
Sourcefn list_tools(&self) -> Vec<ToolSchema>
fn list_tools(&self) -> Vec<ToolSchema>
Lists all available tools and their schemas
Returns schemas for all tools that can be executed via this executor
Provided Methods§
Sourcefn execute_with_context<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
call: &'life1 ToolCall,
_ctx: ToolExecutionContext<'life2>,
) -> Pin<Box<dyn Future<Output = Result<ToolResult, ToolError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn execute_with_context<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
call: &'life1 ToolCall,
_ctx: ToolExecutionContext<'life2>,
) -> Pin<Box<dyn Future<Output = Result<ToolResult, ToolError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Executes a tool call with streaming-capable context.
Default implementation falls back to execute() for executors that don’t
support streaming (e.g. remote MCP tools).
Sourcefn tool_guidance(&self) -> Option<String>
fn tool_guidance(&self) -> Option<String>
Server-level usage guidance to surface in the system prompt for whatever
this executor currently exposes — e.g. the instructions an MCP server
returns from initialize. Because it is derived from the live executor,
the text is naturally scoped to what is actually connected/loaded for the
run (a disconnected server contributes nothing).
Returns None when there is no guidance to add (the default for executors
that have none). The string, when present, is appended to the tool-guide
section of the prompt.
Sourcefn tool_mutability(&self, tool_name: &str) -> ToolMutability
fn tool_mutability(&self, tool_name: &str) -> ToolMutability
Returns mutability metadata for a tool name when available. Executors that can inspect concrete tools should override this.
Sourcefn call_mutability(&self, call: &ToolCall) -> ToolMutability
fn call_mutability(&self, call: &ToolCall) -> ToolMutability
Returns mutability metadata for a specific tool call when available. Defaults to name-based classification.
Sourcefn tool_concurrency_safe(&self, tool_name: &str) -> bool
fn tool_concurrency_safe(&self, tool_name: &str) -> bool
Returns whether a tool can safely execute in parallel with other read-only tools. Executors that can inspect concrete tools should override this. Fallback keeps current behavior for known read-only tools.
Sourcefn call_concurrency_safe(&self, call: &ToolCall) -> bool
fn call_concurrency_safe(&self, call: &ToolCall) -> bool
Returns whether a specific tool call can safely run in parallel. Defaults to the tool-name level classification.
Sourcefn call_parallel_classification(
&self,
call: &ToolCall,
) -> (ToolMutability, bool)
fn call_parallel_classification( &self, call: &ToolCall, ) -> (ToolMutability, bool)
Classify a tool call’s mutability AND concurrency-safety together,
returning (mutability, concurrency_safe).
The default delegates to call_mutability and
call_concurrency_safe — i.e. the exact
prior behavior, so every executor that doesn’t override this is
unchanged. Concrete executors that parse the call’s arguments inside BOTH
of those methods (e.g. BuiltinToolExecutor) override this to parse the
arguments a single time while returning the identical pair. The combined
result lets callers that need both (parallel scheduling) avoid a
redundant argument parse per tool call.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".