Hooks
Lifecycle hooks for intercepting agent behavior in PraisonAI Rust SDK
Hooks intercept and modify agent behavior at various lifecycle points – before/after tools, agents, and LLM calls.
Quick Start
- Create a Hook with HookRegistry
rust use praisonai::{HookRegistry, HookEvent, HookInput, HookResult}; let mut registry = HookRegistry::new(); // Add a logging hook registry.add_hook(HookEvent::BeforeTool, |input: &HookInput| { println!("[{}] Event: {:?}", input.session_id, input.event); HookResult::allow() }); - Block Tool Execution
rust use praisonai::{HookRegistry, HookEvent, HookInput, HookResult}; let mut registry = HookRegistry::new(); // Block dangerous tools registry.add_hook(HookEvent::BeforeTool, |input: &HookInput| { if let Some(tool) = &input.tool_name { if tool == "delete_file" { return HookResult::deny("Dangerous tool blocked"); } } HookResult::allow() }); - Hook with Matcher
rust use praisonai::{HookRegistry, HookEvent, HookInput, HookResult}; let mut registry = HookRegistry::new(); // Only match file-related tools registry.add_hook_with_matcher( HookEvent::BeforeTool, "file_*", // Glob pattern |input: &HookInput| { println!("File operation: {:?}", input.tool_name); HookResult::allow() } );
User Interaction Flow
HookEvent
Events that hooks can subscribe to.
pub enum HookEvent {
BeforeTool,
AfterTool,
BeforeAgent,
AfterAgent,
BeforeLLM,
AfterLLM,
SessionStart,
SessionEnd,
OnError,
OnRetry,
OnInit,
OnShutdown,
}| Event | Description |
|---|---|
BeforeTool | Before tool execution |
AfterTool | After tool execution |
BeforeAgent | Before agent processes message |
AfterAgent | After agent processes message |
BeforeLLM | Before LLM call |
AfterLLM | After LLM call |
SessionStart | New session begins |
SessionEnd | Session ends |
OnError | Error occurred |
OnRetry | Retry triggered |
OnInit | Initialization |
OnShutdown | Shutdown |
HookInput
Data provided to hooks.
pub struct HookInput {
pub event: HookEvent,
pub session_id: String,
pub agent_name: Option<String>,
pub tool_name: Option<String>,
pub tool_args: Option<Value>,
pub message: Option<String>,
pub error: Option<String>,
pub extra: HashMap<String, Value>,
}Builder Methods
| Method | Signature | Description |
|---|---|---|
new(event, session_id) | `fn new(HookEvent, impl Into |
) -> Self | Create input | | with_agent(name) | fn with_agent(self, impl Into
) -> Self | Set agent name | | with_tool(name, args) | fn with_tool(self, impl Into
, Value) -> Self | Set tool info | | with_message(msg) | fn with_message(self, impl Into
) -> Self | Set message | | with_error(err) | fn with_error(self, impl Into
) -> Self | Set error | | with_extra(key, value) | fn with_extra(self, impl Into
, Value) -> Self` | Add extra data |
HookResult
Result returned from hook execution.
pub struct HookResult {
pub decision: HookDecision,
pub reason: Option<String>,
pub modified_input: Option<HashMap<String, Value>>,
pub additional_context: Option<String>,
pub suppress_output: bool,
}Factory Methods
| Method | Signature | Description |
|---|---|---|
allow() | fn allow() -> Self | Allow execution |
allow_with_reason(r) | `fn allow_with_reason(impl Into |
) -> Self | Allow with reason | | deny(reason) | fn deny(impl Into
) -> Self | Deny execution | | block(reason) | fn block(impl Into
) -> Self | Block (stronger deny) | | ask(reason) | fn ask(impl Into
) -> Self` | Ask for confirmation |
Instance Methods
| Method | Signature | Description |
|---|---|---|
is_allowed() | fn is_allowed(&self) -> bool | Check if allowed |
is_denied() | fn is_denied(&self) -> bool | Check if denied |
with_modified_input(input) | fn with_modified_input(self, HashMap) -> Self | Modify inputs |
with_context(ctx) | `fn with_context(self, impl Into |
) -> Self | Add context | | suppress() | fn suppress(self) -> Self` | Suppress output |
HookDecision
Decision types for hook outputs.
pub enum HookDecision {
Allow, // default - Allow operation
Deny, // Deny operation
Block, // Block (stronger than deny)
Ask, // Ask for user confirmation
}HookDefinition
Define individual hooks with functions and metadata.
pub struct HookDefinition {
pub id: String,
pub event: HookEvent,
pub matcher: Option<String>,
pub func: HookFn,
pub enabled: bool,
pub name: Option<String>,
}Methods
| Method | Signature | Description |
|---|---|---|
new(event, func) | fn new(HookEvent, impl Fn(&HookInput) -> HookResult) -> Self | Create definition |
with_matcher(pattern) | `fn with_matcher(self, impl Into |
) -> Self | Set matcher pattern | | with_name(name) | fn with_name(self, impl Into
) -> Self | Set name | | matches(target) | fn matches(&self, &str) -> bool | Check if matches target | | execute(input) | fn execute(&self, &HookInput) -> HookResult` | Execute hook |
HookRegistry
Manages a collection of hooks.
pub struct HookRegistry {
hooks: HashMap<HookEvent, Vec<HookDefinition>>,
}Methods
| Method | Signature | Description |
|---|---|---|
new() | fn new() -> Self | Create empty registry |
add_hook(event, func) | fn add_hook(&mut self, HookEvent, impl Fn) -> &mut Self | Add a hook |
add_hook_with_matcher(event, matcher, func) | `fn add_hook_with_matcher(&mut self, HookEvent, impl Into |
, impl Fn) -> &mut Self | Add hook with matcher | | add_definition(hook) | fn add_definition(&mut self, HookDefinition) -> &mut Self | Add hook definition | | remove_hook(id) | fn remove_hook(&mut self, &str) -> bool | Remove hook by ID | | enable_hook(id) | fn enable_hook(&mut self, &str) -> bool | Enable hook | | disable_hook(id) | fn disable_hook(&mut self, &str) -> bool` | Disable hook |
Common Patterns
Rate Limiter Hook
use praisonai::{HookRegistry, HookEvent, HookInput, HookResult};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
let counter = Arc::new(AtomicUsize::new(0));
let max_calls = 100;
let mut registry = HookRegistry::new();
let counter_clone = counter.clone();
registry.add_hook(HookEvent::BeforeTool, move |_input: &HookInput| {
let count = counter_clone.fetch_add(1, Ordering::SeqCst);
if count >= max_calls {
HookResult::deny("Rate limit exceeded")
} else {
HookResult::allow()
}
});Best Practices
Subscribe to specific events
Only subscribe to events you need – reduces overhead and improves performance.
Use priority for ordering
Hooks with higher priority run first. Use for security checks before logging.
Keep hooks fast
Hooks run in the hot path – avoid expensive operations.
Return clear deny reasons
When denying, provide actionable error messages.