gemini_adk_rs/text/
sequential.rs

1use std::sync::Arc;
2
3use async_trait::async_trait;
4
5use super::TextAgent;
6use crate::context::AgentEvent;
7use crate::error::AgentError;
8use crate::middleware::MiddlewareChain;
9use crate::state::State;
10
11/// Runs text agents sequentially. Each agent sees state mutations from
12/// previous agents. The final agent's output is the pipeline's output.
13pub struct SequentialTextAgent {
14    name: String,
15    children: Vec<Arc<dyn TextAgent>>,
16    middleware: MiddlewareChain,
17}
18
19impl SequentialTextAgent {
20    /// Create a new sequential agent that runs children in order.
21    pub fn new(name: impl Into<String>, children: Vec<Arc<dyn TextAgent>>) -> Self {
22        Self {
23            name: name.into(),
24            children,
25            middleware: MiddlewareChain::new(),
26        }
27    }
28
29    /// Attach a middleware chain. `AgentEvent::AgentStarted` /
30    /// `AgentEvent::AgentCompleted` are emitted through it around every child,
31    /// so `on_event` observers see each stage of the pipeline.
32    pub fn with_middleware_chain(mut self, chain: MiddlewareChain) -> Self {
33        self.middleware = chain;
34        self
35    }
36}
37
38#[async_trait]
39impl TextAgent for SequentialTextAgent {
40    fn name(&self) -> &str {
41        &self.name
42    }
43
44    async fn run(&self, state: &State) -> Result<String, AgentError> {
45        let mut last_output = String::new();
46        for child in &self.children {
47            let _ = self
48                .middleware
49                .run_on_event(&AgentEvent::AgentStarted {
50                    name: child.name().to_string(),
51                })
52                .await;
53            last_output = child.run(state).await?;
54            let _ = self
55                .middleware
56                .run_on_event(&AgentEvent::AgentCompleted {
57                    name: child.name().to_string(),
58                })
59                .await;
60            // Feed output as input for the next agent.
61            let _ = state.set("input", &last_output);
62        }
63        Ok(last_output)
64    }
65}