agent_sdk/subagent/
factory.rs1use std::sync::Arc;
30
31use anyhow::{Context, Result};
32
33use crate::llm::LlmProvider;
34use crate::stores::EventStore;
35use crate::tools::ToolRegistry;
36
37use super::{SubagentConfig, SubagentTool};
38
39pub struct SubagentFactory<P>
44where
45 P: LlmProvider + 'static,
46{
47 provider: Arc<P>,
48 event_store_factory: Arc<dyn Fn() -> Arc<dyn EventStore> + Send + Sync>,
49 read_only_registry: Option<Arc<ToolRegistry<()>>>,
50 full_registry: Option<Arc<ToolRegistry<()>>>,
51}
52
53impl<P> SubagentFactory<P>
54where
55 P: LlmProvider + 'static,
56{
57 #[must_use]
59 pub fn new<EF>(provider: Arc<P>, event_store_factory: EF) -> Self
60 where
61 EF: Fn() -> Arc<dyn EventStore> + Send + Sync + 'static,
62 {
63 Self {
64 provider,
65 event_store_factory: Arc::new(event_store_factory),
66 read_only_registry: None,
67 full_registry: None,
68 }
69 }
70
71 #[must_use]
75 pub fn with_read_only_registry(mut self, registry: ToolRegistry<()>) -> Self {
76 self.read_only_registry = Some(Arc::new(registry));
77 self
78 }
79
80 #[must_use]
82 pub fn with_full_registry(mut self, registry: ToolRegistry<()>) -> Self {
83 self.full_registry = Some(Arc::new(registry));
84 self
85 }
86
87 pub fn create_read_only(&self, config: SubagentConfig) -> Result<SubagentTool<P>> {
96 let registry = self
97 .read_only_registry
98 .as_ref()
99 .context("read-only registry not set; call with_read_only_registry first")?;
100 let event_store_factory = Arc::clone(&self.event_store_factory);
101 Ok(SubagentTool::new(
102 config,
103 Arc::clone(&self.provider),
104 Arc::clone(registry),
105 move || event_store_factory(),
106 ))
107 }
108
109 pub fn create_full_access(&self, config: SubagentConfig) -> Result<SubagentTool<P>> {
115 let registry = self
116 .full_registry
117 .as_ref()
118 .context("full registry not set; call with_full_registry first")?;
119 let event_store_factory = Arc::clone(&self.event_store_factory);
120 Ok(SubagentTool::new(
121 config,
122 Arc::clone(&self.provider),
123 Arc::clone(registry),
124 move || event_store_factory(),
125 ))
126 }
127
128 #[must_use]
130 pub fn create_with_registry(
131 &self,
132 config: SubagentConfig,
133 registry: Arc<ToolRegistry<()>>,
134 ) -> SubagentTool<P> {
135 let event_store_factory = Arc::clone(&self.event_store_factory);
136 SubagentTool::new(config, Arc::clone(&self.provider), registry, move || {
137 event_store_factory()
138 })
139 }
140
141 #[must_use]
143 pub fn provider(&self) -> Arc<P> {
144 Arc::clone(&self.provider)
145 }
146}
147
148impl<P> Clone for SubagentFactory<P>
149where
150 P: LlmProvider + 'static,
151{
152 fn clone(&self) -> Self {
153 Self {
154 provider: Arc::clone(&self.provider),
155 event_store_factory: Arc::clone(&self.event_store_factory),
156 read_only_registry: self.read_only_registry.clone(),
157 full_registry: self.full_registry.clone(),
158 }
159 }
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165
166 #[test]
167 fn test_subagent_config_builder() {
168 let config = SubagentConfig::new("test")
169 .with_system_prompt("You are a test agent")
170 .with_max_turns(5)
171 .with_timeout_ms(30000);
172
173 assert_eq!(config.name, "test");
174 assert_eq!(config.system_prompt, "You are a test agent");
175 assert_eq!(config.max_turns, Some(5));
176 assert_eq!(config.timeout_ms, Some(30000));
177 }
178}