Skip to main content

agent_code_lib/services/
coordinator.rs

1//! Multi-agent coordinator.
2//!
3//! Routes tasks to specialized agents based on the task type.
4//! The coordinator acts as an orchestrator, spawning agents with
5//! appropriate configurations and aggregating their results.
6//!
7//! # Agent types
8//!
9//! - `general-purpose`: default agent with full tool access
10//! - `explore`: fast read-only agent for codebase exploration
11//! - `plan`: planning agent restricted to analysis tools
12//!
13//! Agents are defined as configurations that customize the tool
14//! set, system prompt, and permission mode.
15
16use serde::{Deserialize, Serialize};
17use std::collections::HashMap;
18
19/// Definition of a specialized agent type.
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct AgentDefinition {
22    /// Unique agent type name.
23    pub name: String,
24    /// Description of what this agent specializes in.
25    pub description: String,
26    /// System prompt additions for this agent type.
27    pub system_prompt: Option<String>,
28    /// Model override (if different from default).
29    pub model: Option<String>,
30    /// Tools to include (if empty, use all).
31    pub include_tools: Vec<String>,
32    /// Tools to exclude.
33    pub exclude_tools: Vec<String>,
34    /// Whether this agent runs in read-only mode.
35    pub read_only: bool,
36    /// Maximum turns for this agent type.
37    pub max_turns: Option<usize>,
38}
39
40/// Registry of available agent types.
41pub struct AgentRegistry {
42    agents: HashMap<String, AgentDefinition>,
43}
44
45impl AgentRegistry {
46    /// Create the registry with built-in agent types.
47    pub fn with_defaults() -> Self {
48        let mut agents = HashMap::new();
49
50        agents.insert(
51            "general-purpose".to_string(),
52            AgentDefinition {
53                name: "general-purpose".to_string(),
54                description: "General-purpose agent with full tool access.".to_string(),
55                system_prompt: None,
56                model: None,
57                include_tools: Vec::new(),
58                exclude_tools: Vec::new(),
59                read_only: false,
60                max_turns: None,
61            },
62        );
63
64        agents.insert(
65            "explore".to_string(),
66            AgentDefinition {
67                name: "explore".to_string(),
68                description: "Fast read-only agent for searching and understanding code."
69                    .to_string(),
70                system_prompt: Some(
71                    "You are a fast exploration agent. Focus on finding information \
72                     quickly. Use Grep, Glob, and FileRead to answer questions about \
73                     the codebase. Do not modify files."
74                        .to_string(),
75                ),
76                model: None,
77                include_tools: vec![
78                    "FileRead".into(),
79                    "Grep".into(),
80                    "Glob".into(),
81                    "Bash".into(),
82                    "WebFetch".into(),
83                ],
84                exclude_tools: Vec::new(),
85                read_only: true,
86                max_turns: Some(20),
87            },
88        );
89
90        agents.insert(
91            "plan".to_string(),
92            AgentDefinition {
93                name: "plan".to_string(),
94                description: "Planning agent that designs implementation strategies.".to_string(),
95                system_prompt: Some(
96                    "You are a software architect agent. Design implementation plans, \
97                     identify critical files, and consider architectural trade-offs. \
98                     Do not modify files directly."
99                        .to_string(),
100                ),
101                model: None,
102                include_tools: vec![
103                    "FileRead".into(),
104                    "Grep".into(),
105                    "Glob".into(),
106                    "Bash".into(),
107                ],
108                exclude_tools: Vec::new(),
109                read_only: true,
110                max_turns: Some(30),
111            },
112        );
113
114        Self { agents }
115    }
116
117    /// Look up an agent definition by type name.
118    pub fn get(&self, name: &str) -> Option<&AgentDefinition> {
119        self.agents.get(name)
120    }
121
122    /// Register a custom agent type.
123    pub fn register(&mut self, definition: AgentDefinition) {
124        self.agents.insert(definition.name.clone(), definition);
125    }
126
127    /// List all available agent types.
128    pub fn list(&self) -> Vec<&AgentDefinition> {
129        let mut agents: Vec<_> = self.agents.values().collect();
130        agents.sort_by_key(|a| &a.name);
131        agents
132    }
133}