use crate::command::chat::teammate::TeammateManager;
use crate::command::chat::tools::derived_shared::DerivedAgentShared;
use crate::command::chat::tools::{
PlanDecision, Tool, ToolResult, parse_tool_args, schema_to_tool_params,
};
use schemars::JsonSchema;
use serde::Deserialize;
use serde_json::Value;
use std::sync::{Arc, Mutex, atomic::AtomicBool};
#[derive(Deserialize, JsonSchema)]
struct AgentTeamParams {
members: Vec<AgentTeamMember>,
}
#[derive(Deserialize, JsonSchema)]
struct AgentTeamMember {
name: String,
#[serde(default)]
role: Option<String>,
prompt: String,
}
#[allow(dead_code)]
pub struct AgentTeamTool {
pub shared: DerivedAgentShared,
pub teammate_manager: Arc<Mutex<TeammateManager>>,
}
impl AgentTeamTool {
pub const NAME: &'static str = "AgentTeam";
}
impl Tool for AgentTeamTool {
fn name(&self) -> &str {
Self::NAME
}
fn description(&self) -> &str {
r#"
Create multiple teammates at once for parallel collaboration.
This is a convenience wrapper around CreateTeammate — it creates several teammates
in one call, each with their own agent loop running independently.
All teammates communicate via SendMessage tool (broadcast with @mentions).
Usage:
- members: Array of {name, role?, prompt} objects
Example:
```json
{
"members": [
{"name": "Frontend", "role": "React developer", "prompt": "Create a React Todo app..."},
{"name": "Backend", "role": "Express developer", "prompt": "Create an Express API..."}
]
}
```
Best for:
- Full-stack development (Frontend + Backend + DevOps)
- Multi-domain research tasks
- Any task that benefits from parallel work by specialized agents
"#
}
fn parameters_schema(&self) -> Value {
schema_to_tool_params::<AgentTeamParams>()
}
fn execute(&self, arguments: &str, _cancelled: &Arc<AtomicBool>) -> ToolResult {
let params: AgentTeamParams = match parse_tool_args(arguments) {
Ok(p) => p,
Err(e) => return e,
};
if params.members.is_empty() {
return ToolResult {
output: "Team must have at least one member".to_string(),
is_error: true,
images: vec![],
plan_decision: PlanDecision::None,
};
}
if params.members.len() > 10 {
return ToolResult {
output: "Team size limited to 10 members".to_string(),
is_error: true,
images: vec![],
plan_decision: PlanDecision::None,
};
}
let create_tool = crate::command::chat::tools::create_teammate::CreateTeammateTool {
shared: self.shared.clone(),
teammate_manager: Arc::clone(&self.teammate_manager),
};
let mut results = Vec::new();
let cancelled = Arc::new(AtomicBool::new(false));
for member in ¶ms.members {
let role = member.role.clone().unwrap_or_else(|| member.name.clone());
let args = serde_json::json!({
"name": member.name,
"role": role,
"prompt": member.prompt,
})
.to_string();
let result = create_tool.execute(&args, &cancelled);
results.push(format!("- {}: {}", member.name, result.output));
}
ToolResult {
output: format!("## Team Created\n\n{}", results.join("\n")),
is_error: false,
images: vec![],
plan_decision: PlanDecision::None,
}
}
fn requires_confirmation(&self) -> bool {
false
}
}