adk_core/callbacks.rs
1use crate::{CallbackContext, Content, LlmRequest, LlmResponse, ReadonlyContext, Result, Tool};
2use std::future::Future;
3use std::pin::Pin;
4use std::sync::Arc;
5
6// Agent callbacks
7/// Callback invoked before an agent runs. Return `Ok(Some(content))` to short-circuit.
8pub type BeforeAgentCallback = Box<
9 dyn Fn(
10 Arc<dyn CallbackContext>,
11 ) -> Pin<Box<dyn Future<Output = Result<Option<Content>>> + Send>>
12 + Send
13 + Sync,
14>;
15/// Callback invoked after an agent completes. Return `Ok(Some(content))` to override.
16pub type AfterAgentCallback = Box<
17 dyn Fn(
18 Arc<dyn CallbackContext>,
19 ) -> Pin<Box<dyn Future<Output = Result<Option<Content>>> + Send>>
20 + Send
21 + Sync,
22>;
23
24/// Result from a BeforeModel callback
25#[derive(Debug)]
26pub enum BeforeModelResult {
27 /// Continue with the (possibly modified) request
28 Continue(LlmRequest),
29 /// Skip the model call and use this response instead
30 Skip(LlmResponse),
31}
32
33// Model callbacks
34// BeforeModelCallback can modify the request or skip the model call entirely
35/// Callback invoked before a model call. Can modify the request or skip the call entirely.
36pub type BeforeModelCallback = Box<
37 dyn Fn(
38 Arc<dyn CallbackContext>,
39 LlmRequest,
40 ) -> Pin<Box<dyn Future<Output = Result<BeforeModelResult>> + Send>>
41 + Send
42 + Sync,
43>;
44/// Callback invoked after a model call. Return `Ok(Some(response))` to override.
45pub type AfterModelCallback = Box<
46 dyn Fn(
47 Arc<dyn CallbackContext>,
48 LlmResponse,
49 ) -> Pin<Box<dyn Future<Output = Result<Option<LlmResponse>>> + Send>>
50 + Send
51 + Sync,
52>;
53
54// Tool callbacks
55/// Callback invoked before a tool executes. Return `Ok(Some(content))` to skip execution.
56pub type BeforeToolCallback = Box<
57 dyn Fn(
58 Arc<dyn CallbackContext>,
59 ) -> Pin<Box<dyn Future<Output = Result<Option<Content>>> + Send>>
60 + Send
61 + Sync,
62>;
63/// Callback invoked after a tool executes. Return `Ok(Some(content))` to override the result.
64pub type AfterToolCallback = Box<
65 dyn Fn(
66 Arc<dyn CallbackContext>,
67 ) -> Pin<Box<dyn Future<Output = Result<Option<Content>>> + Send>>
68 + Send
69 + Sync,
70>;
71
72/// Rich after-tool callback that receives the tool, arguments, and response.
73///
74/// Aligned with the Python/Go ADK model where `after_tool_callback` receives
75/// the full tool execution context: the tool itself, the arguments it was
76/// called with, and the response it produced (or error JSON).
77///
78/// This is the V2 callback surface for first-class tool result handling.
79/// Unlike [`AfterToolCallback`] (which only receives `CallbackContext`),
80/// this callback can inspect and modify tool results without relying on
81/// `ToolOutcome` inspection.
82///
83/// Return `Ok(None)` to keep the original response, or `Ok(Some(value))`
84/// to replace the function response sent to the LLM.
85pub type AfterToolCallbackFull = Box<
86 dyn Fn(
87 Arc<dyn CallbackContext>,
88 Arc<dyn Tool>,
89 serde_json::Value, // args
90 serde_json::Value, // tool response (success result or error JSON)
91 ) -> Pin<Box<dyn Future<Output = Result<Option<serde_json::Value>>> + Send>>
92 + Send
93 + Sync,
94>;
95
96// Instruction providers - dynamic instruction generation
97/// Async function that generates dynamic instructions from context.
98pub type InstructionProvider = Box<
99 dyn Fn(Arc<dyn ReadonlyContext>) -> Pin<Box<dyn Future<Output = Result<String>> + Send>>
100 + Send
101 + Sync,
102>;
103/// Alias for [`InstructionProvider`] used at the global (runner) level.
104pub type GlobalInstructionProvider = InstructionProvider;
105
106// ===== Error Callbacks =====
107
108/// Callback invoked when a tool execution fails (after retries are exhausted).
109///
110/// This is the canonical, framework-level tool-error callback type shared by
111/// `adk-agent` (builder registration) and `adk-plugin` (plugin hooks).
112///
113/// Returns `Ok(Some(value))` to substitute a fallback result as the function
114/// response to the LLM, or `Ok(None)` to let the next callback (or the
115/// original error) propagate.
116pub type OnToolErrorCallback = Box<
117 dyn Fn(
118 Arc<dyn CallbackContext>,
119 Arc<dyn Tool>,
120 serde_json::Value, // args
121 String, // error message
122 ) -> Pin<Box<dyn Future<Output = Result<Option<serde_json::Value>>> + Send>>
123 + Send
124 + Sync,
125>;
126
127// ===== Context Compaction =====
128
129use crate::Event;
130use async_trait::async_trait;
131
132/// Trait for summarizing events during context compaction.
133///
134/// Implementations receive a window of events and produce a single
135/// compacted event containing a summary. The runner calls this when
136/// the compaction interval is reached.
137#[async_trait]
138pub trait BaseEventsSummarizer: Send + Sync {
139 /// Summarize the given events into a single compacted event.
140 /// Returns `None` if no compaction is needed (e.g., empty input).
141 async fn summarize_events(&self, events: &[Event]) -> Result<Option<Event>>;
142}
143
144/// Configuration for automatic context compaction.
145///
146/// Mirrors ADK Python's `EventsCompactionConfig`:
147/// - `compaction_interval`: Number of invocations before triggering compaction
148/// - `overlap_size`: Events from the previous window to include in the next summary
149/// - `summarizer`: The strategy used to produce summaries
150#[derive(Clone)]
151pub struct EventsCompactionConfig {
152 /// Number of completed invocations that triggers compaction.
153 pub compaction_interval: u32,
154 /// How many events from the previous compacted window to include
155 /// in the next compaction for continuity.
156 pub overlap_size: u32,
157 /// The summarizer implementation (e.g., LLM-based).
158 pub summarizer: Arc<dyn BaseEventsSummarizer>,
159}