gemini_adk_rs/text/
tap.rs

1use async_trait::async_trait;
2
3use super::TextAgent;
4use crate::error::AgentError;
5use crate::state::State;
6
7/// Read-only observation agent. Calls a function with the state but
8/// cannot mutate it. Returns empty string. No LLM call.
9///
10/// There is no `with_middleware_chain` here: a tap runs no inner agent and
11/// has no lifecycle of its own to observe — it *is* the observer. Attach
12/// middleware to the pipeline that contains it instead.
13pub struct TapTextAgent {
14    name: String,
15    func: Box<dyn Fn(&State) + Send + Sync>,
16}
17
18impl TapTextAgent {
19    /// Create a new tap agent for read-only observation.
20    pub fn new(name: impl Into<String>, f: impl Fn(&State) + Send + Sync + 'static) -> Self {
21        Self {
22            name: name.into(),
23            func: Box::new(f),
24        }
25    }
26}
27
28#[async_trait]
29impl TextAgent for TapTextAgent {
30    fn name(&self) -> &str {
31        &self.name
32    }
33
34    async fn run(&self, state: &State) -> Result<String, AgentError> {
35        (self.func)(state);
36        Ok(String::new())
37    }
38}