Skip to main content

adk_agent/workflow/
sequential_agent.rs

1#[cfg(feature = "skills")]
2use crate::skill_shim::{SelectionPolicy, SkillIndex};
3use crate::workflow::LoopAgent;
4use adk_core::{
5    AfterAgentCallback, Agent, BeforeAgentCallback, EventStream, InvocationContext, Result,
6};
7use async_trait::async_trait;
8use std::sync::Arc;
9
10/// Sequential agent executes sub-agents once in order
11pub struct SequentialAgent {
12    loop_agent: LoopAgent,
13}
14
15impl SequentialAgent {
16    /// Create a new sequential agent with the given name and sub-agents.
17    pub fn new(name: impl Into<String>, sub_agents: Vec<Arc<dyn Agent>>) -> Self {
18        Self { loop_agent: LoopAgent::new(name, sub_agents).with_max_iterations(1) }
19    }
20
21    /// Set the agent description.
22    pub fn with_description(mut self, desc: impl Into<String>) -> Self {
23        self.loop_agent = self.loop_agent.with_description(desc);
24        self
25    }
26
27    /// Add a before-agent callback.
28    pub fn before_callback(mut self, callback: BeforeAgentCallback) -> Self {
29        self.loop_agent = self.loop_agent.before_callback(callback);
30        self
31    }
32
33    /// Add an after-agent callback.
34    pub fn after_callback(mut self, callback: AfterAgentCallback) -> Self {
35        self.loop_agent = self.loop_agent.after_callback(callback);
36        self
37    }
38
39    /// Set a preloaded skills index for this agent.
40    #[cfg(feature = "skills")]
41    pub fn with_skills(mut self, index: SkillIndex) -> Self {
42        self.loop_agent = self.loop_agent.with_skills(index);
43        self
44    }
45
46    /// Auto-load skills from `.skills/` in the current working directory.
47    #[cfg(feature = "skills")]
48    pub fn with_auto_skills(self) -> Result<Self> {
49        self.with_skills_from_root(".")
50    }
51
52    /// Auto-load skills from `.skills/` under a custom root directory.
53    #[cfg(feature = "skills")]
54    pub fn with_skills_from_root(mut self, root: impl AsRef<std::path::Path>) -> Result<Self> {
55        self.loop_agent = self.loop_agent.with_skills_from_root(root)?;
56        Ok(self)
57    }
58
59    /// Customize skill selection behavior.
60    #[cfg(feature = "skills")]
61    pub fn with_skill_policy(mut self, policy: SelectionPolicy) -> Self {
62        self.loop_agent = self.loop_agent.with_skill_policy(policy);
63        self
64    }
65
66    /// Limit injected skill content length.
67    #[cfg(feature = "skills")]
68    pub fn with_skill_budget(mut self, max_chars: usize) -> Self {
69        self.loop_agent = self.loop_agent.with_skill_budget(max_chars);
70        self
71    }
72}
73
74#[async_trait]
75impl Agent for SequentialAgent {
76    fn name(&self) -> &str {
77        self.loop_agent.name()
78    }
79
80    fn description(&self) -> &str {
81        self.loop_agent.description()
82    }
83
84    fn sub_agents(&self) -> &[Arc<dyn Agent>] {
85        self.loop_agent.sub_agents()
86    }
87
88    async fn run(&self, ctx: Arc<dyn InvocationContext>) -> Result<EventStream> {
89        self.loop_agent.run(ctx).await
90    }
91}