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::{token_tracking::TokenTrackingConfig, 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    pub token_tracking_config: Option<TokenTrackingConfig>,
57}
58
59impl DeepAgentConfig {
60    pub fn new(instructions: impl Into<String>, planner: Arc<dyn PlannerHandle>) -> Self {
61        Self {
62            instructions: instructions.into(),
63            planner,
64            tools: Vec::new(),
65            subagent_configs: Vec::new(),
66            summarization: None,
67            tool_interrupts: HashMap::new(),
68            builtin_tools: None,
69            auto_general_purpose: true,
70            enable_prompt_caching: false,
71            checkpointer: None,
72            event_dispatcher: None,
73            enable_pii_sanitization: true, // Enabled by default for security
74            token_tracking_config: None,
75        }
76    }
77
78    pub fn with_tool(mut self, tool: ToolBox) -> Self {
79        self.tools.push(tool);
80        self
81    }
82
83    /// Add a sub-agent configuration
84    pub fn with_subagent_config(mut self, config: SubAgentConfig) -> Self {
85        self.subagent_configs.push(config);
86        self
87    }
88
89    /// Add multiple sub-agent configurations
90    pub fn with_subagent_configs<I>(mut self, configs: I) -> Self
91    where
92        I: IntoIterator<Item = SubAgentConfig>,
93    {
94        self.subagent_configs.extend(configs);
95        self
96    }
97
98    pub fn with_summarization(mut self, config: SummarizationConfig) -> Self {
99        self.summarization = Some(config);
100        self
101    }
102
103    pub fn with_tool_interrupt(mut self, tool_name: impl Into<String>, policy: HitlPolicy) -> Self {
104        self.tool_interrupts.insert(tool_name.into(), policy);
105        self
106    }
107
108    /// Limit which built-in tools are exposed. When omitted, all built-ins are available.
109    /// Built-ins: write_todos, ls, read_file, write_file, edit_file.
110    /// The `task` tool (for subagents) is always available when subagents are registered.
111    pub fn with_builtin_tools<I, S>(mut self, names: I) -> Self
112    where
113        I: IntoIterator<Item = S>,
114        S: Into<String>,
115    {
116        let set: HashSet<String> = names.into_iter().map(|s| s.into()).collect();
117        self.builtin_tools = Some(set);
118        self
119    }
120
121    /// Enable or disable automatic registration of a "general-purpose" subagent.
122    /// Enabled by default; set to false to opt out.
123    pub fn with_auto_general_purpose(mut self, enabled: bool) -> Self {
124        self.auto_general_purpose = enabled;
125        self
126    }
127
128    /// Enable or disable Anthropic prompt caching middleware.
129    /// Disabled by default; set to true to enable caching for better performance.
130    pub fn with_prompt_caching(mut self, enabled: bool) -> Self {
131        self.enable_prompt_caching = enabled;
132        self
133    }
134
135    /// Set the checkpointer for persisting agent state between runs.
136    pub fn with_checkpointer(mut self, checkpointer: Arc<dyn Checkpointer>) -> Self {
137        self.checkpointer = Some(checkpointer);
138        self
139    }
140
141    /// Add an event broadcaster to the agent's event dispatcher.
142    pub fn with_event_broadcaster(
143        mut self,
144        broadcaster: Arc<dyn agents_core::events::EventBroadcaster>,
145    ) -> Self {
146        if self.event_dispatcher.is_none() {
147            self.event_dispatcher = Some(Arc::new(agents_core::events::EventDispatcher::new()));
148        }
149        if let Some(dispatcher) = Arc::get_mut(self.event_dispatcher.as_mut().unwrap()) {
150            dispatcher.add_broadcaster(broadcaster);
151        }
152        self
153    }
154
155    /// Set the event dispatcher directly.
156    pub fn with_event_dispatcher(
157        mut self,
158        dispatcher: Arc<agents_core::events::EventDispatcher>,
159    ) -> Self {
160        self.event_dispatcher = Some(dispatcher);
161        self
162    }
163
164    /// Enable or disable PII sanitization in event data.
165    /// Enabled by default for security. Disable only if you need raw data
166    /// and have other security measures in place.
167    ///
168    /// When enabled:
169    /// - Message previews are truncated to 100 characters
170    /// - Sensitive fields (passwords, tokens, etc.) are redacted
171    /// - PII patterns (emails, phones, credit cards) are removed
172    pub fn with_pii_sanitization(mut self, enabled: bool) -> Self {
173        self.enable_pii_sanitization = enabled;
174        self
175    }
176
177    /// Configure token tracking for monitoring LLM usage and costs.
178    pub fn with_token_tracking_config(mut self, config: TokenTrackingConfig) -> Self {
179        self.token_tracking_config = Some(config);
180        self
181    }
182}
183
184/// Configuration for creating and registering a subagent using a simple, Python-like shape.
185///
186/// Configuration for a sub-agent - a full AI agent with its own LLM, tools, and memory.
187///
188/// A sub-agent is just like the main agent: it has its own system instructions,
189/// tools, LLM, and can maintain its own conversation history. The main agent
190/// delegates tasks to sub-agents via the `task` tool.
191///
192/// ## Required Fields:
193/// - `name`: Unique identifier for this sub-agent
194/// - `description`: What this sub-agent specializes in (shown to main agent)
195/// - `instructions`: System prompt for this sub-agent
196///
197/// ## Optional Fields:
198/// - `model`: LLM to use (defaults to parent agent's model if not specified)
199/// - `tools`: Tools available to this sub-agent (defaults to empty)
200/// - `builtin_tools`: Built-in tools to enable (filesystem, todos, etc.)
201/// - `enable_prompt_caching`: Whether to cache prompts for efficiency
202pub struct SubAgentConfig {
203    // Required fields
204    pub name: String,
205    pub description: String,
206    pub instructions: String,
207
208    // Optional fields - agent configuration
209    pub model: Option<Arc<dyn agents_core::llm::LanguageModel>>,
210    pub tools: Option<Vec<ToolBox>>,
211    pub builtin_tools: Option<HashSet<String>>,
212    pub enable_prompt_caching: bool,
213}
214
215impl SubAgentConfig {
216    /// Create a new sub-agent configuration with required fields only
217    pub fn new(
218        name: impl Into<String>,
219        description: impl Into<String>,
220        instructions: impl Into<String>,
221    ) -> Self {
222        Self {
223            name: name.into(),
224            description: description.into(),
225            instructions: instructions.into(),
226            model: None,
227            tools: None,
228            builtin_tools: None,
229            enable_prompt_caching: false,
230        }
231    }
232
233    /// Set the LLM model for this sub-agent
234    pub fn with_model(mut self, model: Arc<dyn agents_core::llm::LanguageModel>) -> Self {
235        self.model = Some(model);
236        self
237    }
238
239    /// Set the tools for this sub-agent
240    pub fn with_tools(mut self, tools: Vec<ToolBox>) -> Self {
241        self.tools = Some(tools);
242        self
243    }
244
245    /// Enable specific built-in tools (filesystem, todos, etc.)
246    pub fn with_builtin_tools(mut self, tools: HashSet<String>) -> Self {
247        self.builtin_tools = Some(tools);
248        self
249    }
250
251    /// Enable prompt caching for this sub-agent
252    pub fn with_prompt_caching(mut self, enabled: bool) -> Self {
253        self.enable_prompt_caching = enabled;
254        self
255    }
256}
257
258impl IntoIterator for SubAgentConfig {
259    type Item = SubAgentConfig;
260    type IntoIter = std::iter::Once<SubAgentConfig>;
261
262    fn into_iter(self) -> Self::IntoIter {
263        std::iter::once(self)
264    }
265}
266
267/// Configuration for summarization middleware
268#[derive(Clone)]
269pub struct SummarizationConfig {
270    pub messages_to_keep: usize,
271    pub summary_note: String,
272}