agents_runtime/agent/
config.rs

1//! Configuration structs and types for Deep Agents
2//!
3//! This module contains all the configuration structures used to build Deep Agents,
4//! including parameter structs that mirror the Python SDK API.
5
6use crate::middleware::{AgentMiddleware, HitlPolicy};
7use agents_core::agent::PlannerHandle;
8use agents_core::persistence::Checkpointer;
9use agents_core::tools::ToolBox;
10use std::collections::{HashMap, HashSet};
11use std::sync::Arc;
12
13/// Parameters for create_deep_agent() that mirror the Python API exactly
14///
15/// This struct matches the Python function signature:
16/// ```python
17/// def create_deep_agent(
18///     tools: Sequence[Union[BaseTool, Callable, dict[str, Any]]] = [],
19///     instructions: str = "",
20///     middleware: Optional[list[AgentMiddleware]] = None,
21///     model: Optional[Union[str, LanguageModelLike]] = None,
22///     subagents: Optional[list[SubAgent | CustomSubAgent]] = None,
23///     context_schema: Optional[Type[Any]] = None,
24///     checkpointer: Optional[Checkpointer] = None,
25///     tool_configs: Optional[dict[str, bool | ToolConfig]] = None,
26/// )
27/// ```
28#[derive(Default)]
29pub struct CreateDeepAgentParams {
30    pub tools: Vec<ToolBox>,
31    pub instructions: String,
32    pub middleware: Vec<Arc<dyn AgentMiddleware>>,
33    pub model: Option<Arc<dyn agents_core::llm::LanguageModel>>,
34    pub subagents: Vec<SubAgentConfig>,
35    pub context_schema: Option<String>,
36    pub checkpointer: Option<Arc<dyn Checkpointer>>,
37    pub tool_configs: HashMap<String, HitlPolicy>,
38}
39
40/// Configuration for building a deep agent instance.
41///
42/// This is the internal configuration used by the builder and runtime.
43pub struct DeepAgentConfig {
44    pub instructions: String,
45    pub planner: Arc<dyn PlannerHandle>,
46    pub tools: Vec<ToolBox>,
47    pub subagent_configs: Vec<SubAgentConfig>,
48    pub summarization: Option<SummarizationConfig>,
49    pub tool_interrupts: HashMap<String, HitlPolicy>,
50    pub builtin_tools: Option<HashSet<String>>,
51    pub auto_general_purpose: bool,
52    pub enable_prompt_caching: bool,
53    pub checkpointer: Option<Arc<dyn Checkpointer>>,
54    pub event_dispatcher: Option<Arc<agents_core::events::EventDispatcher>>,
55    pub enable_pii_sanitization: bool,
56}
57
58impl DeepAgentConfig {
59    pub fn new(instructions: impl Into<String>, planner: Arc<dyn PlannerHandle>) -> Self {
60        Self {
61            instructions: instructions.into(),
62            planner,
63            tools: Vec::new(),
64            subagent_configs: Vec::new(),
65            summarization: None,
66            tool_interrupts: HashMap::new(),
67            builtin_tools: None,
68            auto_general_purpose: true,
69            enable_prompt_caching: false,
70            checkpointer: None,
71            event_dispatcher: None,
72            enable_pii_sanitization: true, // Enabled by default for security
73        }
74    }
75
76    pub fn with_tool(mut self, tool: ToolBox) -> Self {
77        self.tools.push(tool);
78        self
79    }
80
81    /// Add a sub-agent configuration
82    pub fn with_subagent_config(mut self, config: SubAgentConfig) -> Self {
83        self.subagent_configs.push(config);
84        self
85    }
86
87    /// Add multiple sub-agent configurations
88    pub fn with_subagent_configs<I>(mut self, configs: I) -> Self
89    where
90        I: IntoIterator<Item = SubAgentConfig>,
91    {
92        self.subagent_configs.extend(configs);
93        self
94    }
95
96    pub fn with_summarization(mut self, config: SummarizationConfig) -> Self {
97        self.summarization = Some(config);
98        self
99    }
100
101    pub fn with_tool_interrupt(mut self, tool_name: impl Into<String>, policy: HitlPolicy) -> Self {
102        self.tool_interrupts.insert(tool_name.into(), policy);
103        self
104    }
105
106    /// Limit which built-in tools are exposed. When omitted, all built-ins are available.
107    /// Built-ins: write_todos, ls, read_file, write_file, edit_file.
108    /// The `task` tool (for subagents) is always available when subagents are registered.
109    pub fn with_builtin_tools<I, S>(mut self, names: I) -> Self
110    where
111        I: IntoIterator<Item = S>,
112        S: Into<String>,
113    {
114        let set: HashSet<String> = names.into_iter().map(|s| s.into()).collect();
115        self.builtin_tools = Some(set);
116        self
117    }
118
119    /// Enable or disable automatic registration of a "general-purpose" subagent.
120    /// Enabled by default; set to false to opt out.
121    pub fn with_auto_general_purpose(mut self, enabled: bool) -> Self {
122        self.auto_general_purpose = enabled;
123        self
124    }
125
126    /// Enable or disable Anthropic prompt caching middleware.
127    /// Disabled by default; set to true to enable caching for better performance.
128    pub fn with_prompt_caching(mut self, enabled: bool) -> Self {
129        self.enable_prompt_caching = enabled;
130        self
131    }
132
133    /// Set the checkpointer for persisting agent state between runs.
134    pub fn with_checkpointer(mut self, checkpointer: Arc<dyn Checkpointer>) -> Self {
135        self.checkpointer = Some(checkpointer);
136        self
137    }
138
139    /// Add an event broadcaster to the agent's event dispatcher.
140    pub fn with_event_broadcaster(
141        mut self,
142        broadcaster: Arc<dyn agents_core::events::EventBroadcaster>,
143    ) -> Self {
144        if self.event_dispatcher.is_none() {
145            self.event_dispatcher = Some(Arc::new(agents_core::events::EventDispatcher::new()));
146        }
147        if let Some(dispatcher) = Arc::get_mut(self.event_dispatcher.as_mut().unwrap()) {
148            dispatcher.add_broadcaster(broadcaster);
149        }
150        self
151    }
152
153    /// Set the event dispatcher directly.
154    pub fn with_event_dispatcher(
155        mut self,
156        dispatcher: Arc<agents_core::events::EventDispatcher>,
157    ) -> Self {
158        self.event_dispatcher = Some(dispatcher);
159        self
160    }
161
162    /// Enable or disable PII sanitization in event data.
163    /// Enabled by default for security. Disable only if you need raw data
164    /// and have other security measures in place.
165    ///
166    /// When enabled:
167    /// - Message previews are truncated to 100 characters
168    /// - Sensitive fields (passwords, tokens, etc.) are redacted
169    /// - PII patterns (emails, phones, credit cards) are removed
170    pub fn with_pii_sanitization(mut self, enabled: bool) -> Self {
171        self.enable_pii_sanitization = enabled;
172        self
173    }
174}
175
176/// Configuration for creating and registering a subagent using a simple, Python-like shape.
177///
178/// Configuration for a sub-agent - a full AI agent with its own LLM, tools, and memory.
179///
180/// A sub-agent is just like the main agent: it has its own system instructions,
181/// tools, LLM, and can maintain its own conversation history. The main agent
182/// delegates tasks to sub-agents via the `task` tool.
183///
184/// ## Required Fields:
185/// - `name`: Unique identifier for this sub-agent
186/// - `description`: What this sub-agent specializes in (shown to main agent)
187/// - `instructions`: System prompt for this sub-agent
188///
189/// ## Optional Fields:
190/// - `model`: LLM to use (defaults to parent agent's model if not specified)
191/// - `tools`: Tools available to this sub-agent (defaults to empty)
192/// - `builtin_tools`: Built-in tools to enable (filesystem, todos, etc.)
193/// - `enable_prompt_caching`: Whether to cache prompts for efficiency
194pub struct SubAgentConfig {
195    // Required fields
196    pub name: String,
197    pub description: String,
198    pub instructions: String,
199
200    // Optional fields - agent configuration
201    pub model: Option<Arc<dyn agents_core::llm::LanguageModel>>,
202    pub tools: Option<Vec<ToolBox>>,
203    pub builtin_tools: Option<HashSet<String>>,
204    pub enable_prompt_caching: bool,
205}
206
207impl SubAgentConfig {
208    /// Create a new sub-agent configuration with required fields only
209    pub fn new(
210        name: impl Into<String>,
211        description: impl Into<String>,
212        instructions: impl Into<String>,
213    ) -> Self {
214        Self {
215            name: name.into(),
216            description: description.into(),
217            instructions: instructions.into(),
218            model: None,
219            tools: None,
220            builtin_tools: None,
221            enable_prompt_caching: false,
222        }
223    }
224
225    /// Set the LLM model for this sub-agent
226    pub fn with_model(mut self, model: Arc<dyn agents_core::llm::LanguageModel>) -> Self {
227        self.model = Some(model);
228        self
229    }
230
231    /// Set the tools for this sub-agent
232    pub fn with_tools(mut self, tools: Vec<ToolBox>) -> Self {
233        self.tools = Some(tools);
234        self
235    }
236
237    /// Enable specific built-in tools (filesystem, todos, etc.)
238    pub fn with_builtin_tools(mut self, tools: HashSet<String>) -> Self {
239        self.builtin_tools = Some(tools);
240        self
241    }
242
243    /// Enable prompt caching for this sub-agent
244    pub fn with_prompt_caching(mut self, enabled: bool) -> Self {
245        self.enable_prompt_caching = enabled;
246        self
247    }
248}
249
250impl IntoIterator for SubAgentConfig {
251    type Item = SubAgentConfig;
252    type IntoIter = std::iter::Once<SubAgentConfig>;
253
254    fn into_iter(self) -> Self::IntoIter {
255        std::iter::once(self)
256    }
257}
258
259/// Configuration for summarization middleware
260#[derive(Clone)]
261pub struct SummarizationConfig {
262    pub messages_to_keep: usize,
263    pub summary_note: String,
264}