Skip to main content

aether_core/events/
observer.rs

1use crate::events::{AgentEvent, TraceContext};
2use std::sync::Arc;
3
4/// Observer of the agent's event stream. Observers receive the same events
5/// the agent sends on its event channel, synchronously and in order —
6/// including events that channel consumers such as UIs and session
7/// persistence filter out downstream.
8pub trait AgentObserver: Send {
9    fn on_event(&mut self, message: &AgentEvent);
10
11    /// Called with the rendered system prompt for the next chat request
12    fn on_system_prompt(&mut self, _prompt: &str) {}
13
14    /// Trace context to propagate to whatever executes `tool_id`, available once
15    /// the observer has seen that tool's
16    /// [`ExecutionStarted`](crate::events::ToolEvent::ExecutionStarted).
17    fn tool_trace_context(&self, _tool_id: &str) -> Option<TraceContext> {
18        None
19    }
20}
21
22/// Instrumentation for one inbound MCP request, held by the server handling it.
23pub trait McpRequestInstrumentation: Send {
24    /// Context beneath the request, for application work the request spawns.
25    fn trace_context(&self) -> Option<TraceContext>;
26
27    /// Completes the request. `error` is the public operation error, if any.
28    fn finish(self: Box<Self>, error: Option<&str>);
29}
30
31/// Creates observers isolated to one agent or one inbound MCP request.
32pub trait ObserverFactory: Send + Sync {
33    /// A fresh observer for one agent, continuing the parent trace when supplied.
34    fn agent(&self, agent_name: Option<&str>, parent: Option<&TraceContext>) -> Box<dyn AgentObserver>;
35
36    /// Instrumentation for one inbound `tools/call` request.
37    fn tool_call_request(&self, tool_name: &str, parent: Option<&TraceContext>) -> Box<dyn McpRequestInstrumentation>;
38}
39
40pub type DynObserverFactory = Arc<dyn ObserverFactory>;