everruns_core/tool_hooks.rs
1//! Neutral contracts for capability-contributed per-tool execution hooks.
2
3use crate::tool_context::ToolContext;
4use async_trait::async_trait;
5use everruns_contracts::tool_types::{ToolCall, ToolDefinition, ToolResult};
6
7/// Decision returned by a [`PreToolUseHook`] before a tool is dispatched.
8#[derive(Debug, Clone)]
9pub enum PreToolUseDecision {
10 /// Continue with the possibly transformed call.
11 Continue(ToolCall),
12 /// Block this call without affecting sibling calls in the batch.
13 Block {
14 /// Call that was blocked.
15 tool_call: ToolCall,
16 /// Error text recorded for the model and audit stream.
17 reason: String,
18 /// Optional message for a user-facing runtime.
19 user_message: Option<String>,
20 },
21 /// Do not run this call yet; record `result` as its outcome instead.
22 ///
23 /// For gates that park the turn on a durable request rather than answer
24 /// in-process (hosted tool approval): `result` carries a structured payload
25 /// that a post-act hook turns into a pause, and its `error` is what the
26 /// model reads. Like `Block`, the tool is never invoked and the chain stops.
27 Defer {
28 /// Call that was deferred.
29 tool_call: ToolCall,
30 /// Outcome recorded for the call in place of running it.
31 result: ToolResult,
32 },
33}
34
35/// Capability hook invoked before each individual tool execution.
36#[async_trait]
37pub trait PreToolUseHook: Send + Sync {
38 /// Transform or block a tool call before dispatch.
39 async fn before_exec(
40 &self,
41 tool_call: ToolCall,
42 tool_def: &ToolDefinition,
43 context: &ToolContext,
44 ) -> PreToolUseDecision;
45}
46
47/// Ordering for capability-contributed post-tool hooks.
48#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
49pub enum PostToolExecHookPriority {
50 /// Inspect or block output before normal mutating hooks.
51 Guardrail = 0,
52 /// Default ordering for transformation and observability hooks.
53 Normal = 100,
54}
55
56/// Capability hook invoked after each individual tool execution.
57#[async_trait]
58pub trait PostToolExecHook: Send + Sync {
59 /// Ordering within the capability-contributed hook phase.
60 fn priority(&self) -> PostToolExecHookPriority {
61 PostToolExecHookPriority::Normal
62 }
63
64 /// Inspect or transform one tool result before engine event emission.
65 async fn after_exec(
66 &self,
67 tool_call: &ToolCall,
68 tool_def: &ToolDefinition,
69 result: &mut ToolResult,
70 context: &ToolContext,
71 );
72}