agent_works/multi_agent/config.rs
1//! Multi-agent configuration.
2//!
3//! Controls whether multi-agent capabilities are enabled and sets resource limits.
4//! Multi-agent is enabled by default — users who don't need it can disable via
5//! `.without_multi_agent()` or feature gate.
6
7/// Permission mode for spawned child agents.
8///
9/// Controls whether sub-agents run with full tool access or are restricted by
10/// the parent's [`ToolPolicy`](agent_base::ToolPolicy). The mode is resolved at
11/// the runtime layer on every spawn, so it cannot be bypassed by the LLM.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
13pub enum ChildPermissionMode {
14 /// Child agents have full permission — every tool auto-approves.
15 ///
16 /// This matches the historical behaviour (children carried no tool policy),
17 /// so it is the default to avoid surprising existing users.
18 #[default]
19 Full,
20 /// Child agents have no permission — the parent's "dangerous tools" are
21 /// denied when the parent has a [`ToolPolicy`](agent_base::ToolPolicy); if
22 /// the parent has none, every tool is denied via [`DenyAllToolPolicy`](agent_base::DenyAllToolPolicy).
23 None,
24 /// The parent agent decides per-spawn via `SpawnAgentArgs.full_permission`.
25 PerSpawn,
26}
27
28/// Configuration for the multi-agent subsystem.
29///
30/// # Default
31///
32/// Multi-agent is **enabled** by default with limits of 8 sub-agents and depth 1.
33/// Disable it with:
34///
35/// ```rust,ignore
36/// use agent_works::AgentBuilder;
37///
38/// let agent = AgentBuilder::new(client)
39/// .without_multi_agent()
40/// .build()?;
41/// ```
42///
43/// # Limits
44///
45/// Limits only take effect when `enabled` is `true`.
46#[derive(Clone, Debug)]
47pub struct MultiAgentConfig {
48 /// Enable multi-agent capabilities.
49 ///
50 /// When `true` (default): all 6 multi-agent tools are registered, and the main
51 /// agent's system prompt is augmented with usage guidance.
52 ///
53 /// When `false`: no multi-agent tools are registered, and the system
54 /// prompt does not mention multi-agent capabilities.
55 pub enabled: bool,
56
57 /// Maximum number of concurrent sub-agents.
58 ///
59 /// Default: 8. Only enforced when `enabled` is `true`.
60 pub max_sub_agents: usize,
61
62 /// Maximum nesting depth for sub-agents.
63 ///
64 /// Default: 1 (only direct children of root can spawn). A value of 0 means
65 /// no sub-agents can be spawned at all. Only enforced when `enabled` is `true`.
66 pub max_agent_depth: i32,
67
68 /// Permission mode for spawned child agents.
69 ///
70 /// Default: [`ChildPermissionMode::Full`].
71 pub child_permission_mode: ChildPermissionMode,
72}
73
74impl Default for MultiAgentConfig {
75 fn default() -> Self {
76 Self {
77 enabled: true,
78 max_sub_agents: 8,
79 max_agent_depth: 1,
80 child_permission_mode: ChildPermissionMode::Full,
81 }
82 }
83}
84
85impl MultiAgentConfig {
86 /// Create a config with multi-agent enabled and default limits.
87 pub fn enabled() -> Self {
88 Self {
89 enabled: true,
90 ..Default::default()
91 }
92 }
93
94 /// Create a config with multi-agent enabled and custom limits.
95 pub fn with_limits(max_sub_agents: usize, max_agent_depth: i32) -> Self {
96 Self {
97 enabled: true,
98 max_sub_agents,
99 max_agent_depth,
100 child_permission_mode: ChildPermissionMode::Full,
101 }
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn default_is_enabled() {
111 let config = MultiAgentConfig::default();
112 assert!(config.enabled);
113 assert_eq!(config.max_sub_agents, 8);
114 assert_eq!(config.max_agent_depth, 1);
115 }
116
117 #[test]
118 fn default_permission_mode_is_full() {
119 assert_eq!(
120 MultiAgentConfig::default().child_permission_mode,
121 ChildPermissionMode::Full
122 );
123 assert_eq!(
124 MultiAgentConfig::enabled().child_permission_mode,
125 ChildPermissionMode::Full
126 );
127 assert_eq!(
128 MultiAgentConfig::with_limits(4, 2).child_permission_mode,
129 ChildPermissionMode::Full
130 );
131 }
132
133 #[test]
134 fn enabled_shortcut() {
135 let config = MultiAgentConfig::enabled();
136 assert!(config.enabled);
137 assert_eq!(config.max_sub_agents, 8);
138 assert_eq!(config.max_agent_depth, 1);
139 }
140
141 #[test]
142 fn with_limits() {
143 let config = MultiAgentConfig::with_limits(4, 2);
144 assert!(config.enabled);
145 assert_eq!(config.max_sub_agents, 4);
146 assert_eq!(config.max_agent_depth, 2);
147 }
148}