use crate::runtime::{AgentEvent, ToolUseResult};
pub struct AgentHookContext {
pub node_name: String,
pub input_message_count: usize,
}
pub struct AgentHookSnapshot {
pub result: ToolUseResult,
pub events: Vec<AgentEvent>,
}
pub trait AgentHook: Send + Sync {
fn before_agent(&self, _ctx: &AgentHookContext) {}
fn after_agent(&self, _snapshot: &AgentHookSnapshot) {}
}
#[derive(Debug, Clone, Default)]
pub struct NoOpAgentHook;
impl AgentHook for NoOpAgentHook {}
#[derive(Debug, Clone)]
pub struct TracingAgentHook;
impl AgentHook for TracingAgentHook {
fn before_agent(&self, ctx: &AgentHookContext) {
tracing::debug!(
node = %ctx.node_name,
input_messages = ctx.input_message_count,
"agent loop starting"
);
}
fn after_agent(&self, snapshot: &AgentHookSnapshot) {
tracing::debug!(
iterations = snapshot.result.iterations,
tool_calls = snapshot.result.tool_calls_executed,
stop_reason = ?snapshot.result.stop_reason,
"agent loop completed"
);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_noop_agent_hook() {
let hook = NoOpAgentHook;
let ctx = AgentHookContext {
node_name: "test".to_string(),
input_message_count: 0,
};
hook.before_agent(&ctx);
}
#[test]
fn test_tracing_agent_hook() {
let hook = TracingAgentHook;
let ctx = AgentHookContext {
node_name: "test".to_string(),
input_message_count: 5,
};
hook.before_agent(&ctx);
}
}