pub trait EnhancedPlugin: Send + Sync {
// Required method
fn name(&self) -> &str;
// Provided methods
fn priority(&self) -> i32 { ... }
fn before_tool_call<'life0, 'life1, 'async_trait>(
&'life0 self,
_tool: Arc<dyn Tool>,
args: Value,
_ctx: Arc<dyn CallbackContext>,
_plugin_ctx: &'life1 PluginContext,
) -> Pin<Box<dyn Future<Output = Result<BeforeToolCallResult>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn after_tool_call<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_tool: Arc<dyn Tool>,
_args: &'life1 Value,
result: Value,
_ctx: Arc<dyn CallbackContext>,
_plugin_ctx: &'life2 PluginContext,
) -> Pin<Box<dyn Future<Output = Result<AfterToolCallResult>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn before_model_call<'life0, 'life1, 'async_trait>(
&'life0 self,
request: LlmRequest,
_ctx: Arc<dyn CallbackContext>,
_plugin_ctx: &'life1 PluginContext,
) -> Pin<Box<dyn Future<Output = Result<BeforeModelCallResult>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn after_model_call<'life0, 'life1, 'async_trait>(
&'life0 self,
response: LlmResponse,
_ctx: Arc<dyn CallbackContext>,
_plugin_ctx: &'life1 PluginContext,
) -> Pin<Box<dyn Future<Output = Result<AfterModelCallResult>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn close<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
}Expand description
Enhanced plugin trait with fine-grained hooks and default no-op implementations.
Implement only the hooks you need. All methods have default implementations that pass through inputs unchanged (identity function behavior).
§Priority
Plugins execute in ascending priority order (lower values run first). The default priority is 100. Recommended ranges:
| Range | Use Case |
|---|---|
| 0–25 | Security plugins (auth, validation, rate limiting) |
| 26–50 | Caching plugins |
| 51–75 | Transformation plugins (sanitization, injection) |
| 76–100 | Logging and metrics plugins |
| 100+ | Application-specific plugins |
§Thread Safety
All implementations must be Send + Sync to support concurrent async execution.
The PluginContext provides thread-safe shared state access via
tokio::sync::RwLock.
Required Methods§
Provided Methods§
Sourcefn priority(&self) -> i32
fn priority(&self) -> i32
Execution priority. Lower values execute first. Default: 100.
When multiple plugins are registered, they execute hooks in ascending priority order. Plugins with the same priority execute in registration order.
Sourcefn before_tool_call<'life0, 'life1, 'async_trait>(
&'life0 self,
_tool: Arc<dyn Tool>,
args: Value,
_ctx: Arc<dyn CallbackContext>,
_plugin_ctx: &'life1 PluginContext,
) -> Pin<Box<dyn Future<Output = Result<BeforeToolCallResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn before_tool_call<'life0, 'life1, 'async_trait>(
&'life0 self,
_tool: Arc<dyn Tool>,
args: Value,
_ctx: Arc<dyn CallbackContext>,
_plugin_ctx: &'life1 PluginContext,
) -> Pin<Box<dyn Future<Output = Result<BeforeToolCallResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Called before a tool is executed.
Receives the tool reference, call arguments, callback context, and shared plugin context.
§Returns
Ok(BeforeToolCallResult::Continue(args))— pass (possibly modified) args to the next plugin in the chain, and ultimately to the tool execution.Ok(BeforeToolCallResult::ShortCircuit(result))— skip tool execution entirely and use this synthetic result. No further plugins in the chain are invoked.Err(e)— stop the pipeline and propagate the error. The tool is not executed.
Sourcefn after_tool_call<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_tool: Arc<dyn Tool>,
_args: &'life1 Value,
result: Value,
_ctx: Arc<dyn CallbackContext>,
_plugin_ctx: &'life2 PluginContext,
) -> Pin<Box<dyn Future<Output = Result<AfterToolCallResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn after_tool_call<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_tool: Arc<dyn Tool>,
_args: &'life1 Value,
result: Value,
_ctx: Arc<dyn CallbackContext>,
_plugin_ctx: &'life2 PluginContext,
) -> Pin<Box<dyn Future<Output = Result<AfterToolCallResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Called after a tool executes successfully.
Receives the tool reference, the arguments that were used for execution (after any modifications by before-hooks), the result, callback context, and shared plugin context.
§Returns
Ok(AfterToolCallResult::Continue(result))— pass (possibly modified) result to the next plugin in the chain, and ultimately return to the agent.Err(e)— stop the pipeline and propagate the error.
Sourcefn before_model_call<'life0, 'life1, 'async_trait>(
&'life0 self,
request: LlmRequest,
_ctx: Arc<dyn CallbackContext>,
_plugin_ctx: &'life1 PluginContext,
) -> Pin<Box<dyn Future<Output = Result<BeforeModelCallResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn before_model_call<'life0, 'life1, 'async_trait>(
&'life0 self,
request: LlmRequest,
_ctx: Arc<dyn CallbackContext>,
_plugin_ctx: &'life1 PluginContext,
) -> Pin<Box<dyn Future<Output = Result<BeforeModelCallResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Called before a model (LLM) call is made.
Receives the LLM request, callback context, and shared plugin context.
§Returns
Ok(BeforeModelCallResult::Continue(request))— pass (possibly modified) request to the next plugin in the chain, and ultimately to the LLM provider.Ok(BeforeModelCallResult::ShortCircuit(response))— skip the model call entirely and use this synthetic response. No further plugins in the chain are invoked.Err(e)— stop the pipeline and propagate the error. The model is not called.
Sourcefn after_model_call<'life0, 'life1, 'async_trait>(
&'life0 self,
response: LlmResponse,
_ctx: Arc<dyn CallbackContext>,
_plugin_ctx: &'life1 PluginContext,
) -> Pin<Box<dyn Future<Output = Result<AfterModelCallResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn after_model_call<'life0, 'life1, 'async_trait>(
&'life0 self,
response: LlmResponse,
_ctx: Arc<dyn CallbackContext>,
_plugin_ctx: &'life1 PluginContext,
) -> Pin<Box<dyn Future<Output = Result<AfterModelCallResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Called after a model (LLM) call completes.
Receives the LLM response, callback context, and shared plugin context.
§Returns
Ok(AfterModelCallResult::Continue(response))— pass (possibly modified) response to the next plugin in the chain, and ultimately return to the agent.Err(e)— stop the pipeline and propagate the error.
Sourcefn close<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn close<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Called when the plugin is being shut down.
Override this method to perform cleanup operations such as flushing buffers, closing connections, or persisting state.
The default implementation is a no-op.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".