Skip to main content

brainwires_tool_system/
executor.rs

1//! Tool Executor trait
2//!
3//! Defines the [`ToolExecutor`] trait for abstracted tool execution.
4//! Framework crates like `brainwires-agents` depend on this trait
5//! to call tools without coupling to any concrete implementation.
6
7use anyhow::Result;
8use async_trait::async_trait;
9
10use brainwires_core::{Tool, ToolContext, ToolResult, ToolUse};
11
12/// Trait for executing tools in an agent context.
13///
14/// Implement this on your tool executor to integrate with framework agents
15/// like `TaskAgent`. The trait is object-safe and can be used as
16/// `Arc<dyn ToolExecutor>`.
17///
18/// # Example
19///
20/// ```rust,ignore
21/// use brainwires_tool_system::ToolExecutor;
22/// use brainwires_core::{Tool, ToolContext, ToolResult, ToolUse};
23/// use async_trait::async_trait;
24///
25/// struct MyExecutor;
26///
27/// #[async_trait]
28/// impl ToolExecutor for MyExecutor {
29///     async fn execute(&self, tool_use: &ToolUse, context: &ToolContext) -> anyhow::Result<ToolResult> {
30///         Ok(ToolResult::success(tool_use.id.clone(), "done".to_string()))
31///     }
32///
33///     fn available_tools(&self) -> Vec<Tool> {
34///         vec![]
35///     }
36/// }
37/// ```
38#[async_trait]
39pub trait ToolExecutor: Send + Sync {
40    /// Execute a tool and return its result.
41    ///
42    /// The `tool_use` contains the tool name and input parameters.
43    /// The `context` provides working directory and execution metadata.
44    async fn execute(&self, tool_use: &ToolUse, context: &ToolContext) -> Result<ToolResult>;
45
46    /// Return the list of tools available for the AI to invoke.
47    fn available_tools(&self) -> Vec<Tool>;
48}
49
50/// Decision returned by a [`ToolPreHook`] before a tool call.
51#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
52pub enum PreHookDecision {
53    /// Allow the tool call to proceed normally.
54    Allow,
55    /// Reject the call; inject this message as `ToolResult::error`.
56    Reject(String),
57}
58
59/// Pluggable pre-execution hook for semantic tool validation.
60///
61/// Implement this to intercept tool calls before execution and validate
62/// call intent against current agent state (not just JSON schema).
63/// Hook is set via `AgentContext::with_pre_execute_hook()`.
64#[async_trait]
65pub trait ToolPreHook: Send + Sync {
66    /// Called before tool execution to validate or reject the call.
67    async fn before_execute(
68        &self,
69        tool_use: &ToolUse,
70        context: &ToolContext,
71    ) -> Result<PreHookDecision>;
72}