pub trait ToolPolicy: Send + Sync {
// Required method
fn evaluate_approval<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
tool_name: &'life1 str,
args: &'life2 Value,
) -> Pin<Box<dyn Future<Output = Option<ApprovalRequest>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
// Provided methods
fn before_call(
&self,
tool_name: &str,
args: &Value,
ctx: &ToolContext,
) -> AgentResult<()> { ... }
fn after_call(
&self,
tool_name: &str,
args: &Value,
result: &ToolOutput,
ctx: &ToolContext,
) -> AgentResult<()> { ... }
}Expand description
Policy-based control over tool execution.
Implement this trait to customise how tools are approved, monitored, and validated during an agent run. The pipeline calls each hook at a specific point in the tool lifecycle:
evaluate_approval → before_call → (tool executes) → after_call§Example: auto-approve read-only tools
struct ReadOnlyPolicy;
#[async_trait]
impl ToolPolicy for ReadOnlyPolicy {
async fn evaluate_approval(&self, tool_name: &str, _args: &Value) -> Option<ApprovalRequest> {
if tool_name == "read_file" || tool_name == "search" {
None // auto-approve — no prompt for user
} else {
Some(ApprovalRequest { message: format!("Allow {}?", tool_name) })
}
}
}All hooks have default no-op implementations, so you only need to override the ones you care about.
Required Methods§
Sourcefn evaluate_approval<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
tool_name: &'life1 str,
args: &'life2 Value,
) -> Pin<Box<dyn Future<Output = Option<ApprovalRequest>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn evaluate_approval<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
tool_name: &'life1 str,
args: &'life2 Value,
) -> Pin<Box<dyn Future<Output = Option<ApprovalRequest>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Called before every tool call.
Return None to auto-approve (skip the approval handler entirely).
Return Some(ApprovalRequest) to defer to the configured
ApprovalHandler.
This is the primary hook for implementing permission guards — for example, auto-approving read-only operations while prompting for destructive ones.
Provided Methods§
Sourcefn before_call(
&self,
tool_name: &str,
args: &Value,
ctx: &ToolContext,
) -> AgentResult<()>
fn before_call( &self, tool_name: &str, args: &Value, ctx: &ToolContext, ) -> AgentResult<()>
Called immediately before a tool executes, after approval has been granted (or auto-approved).
Use this for:
- Input validation (reject malformed arguments before the tool runs).
- Auditing / logging the raw call.
- Rate-limiting or quota enforcement.
Return an Err to cancel the tool call before execution. The error
message is surfaced to the LLM so it can correct its approach.
Sourcefn after_call(
&self,
tool_name: &str,
args: &Value,
result: &ToolOutput,
ctx: &ToolContext,
) -> AgentResult<()>
fn after_call( &self, tool_name: &str, args: &Value, result: &ToolOutput, ctx: &ToolContext, ) -> AgentResult<()>
Called immediately after a tool executes, before the result is returned to the LLM.
Use this for:
- Output scrubbing / redaction (strip secrets from tool results).
- Truncation or formatting of large outputs.
- Recording metrics or audit trails.
The result is the raw ToolOutput produced by the tool. You can
inspect it but not modify it through this hook — if you need to
transform the output, use a middleware instead.
Return an Err to reject the result. The error message is surfaced
to the LLM.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".