use letta::client::{ClientConfig, LettaClient};
use letta::types::*;
fn get_test_client() -> LettaClient {
let config = ClientConfig::new("http://localhost:8283").unwrap();
LettaClient::new(config).unwrap()
}
#[tokio::test]
async fn test_list_groups() {
let client = get_test_client();
let result = client.groups().list(None).await;
let groups = result.expect("Failed to list groups");
println!("Found {} groups", groups.len());
for group in groups.iter().take(5) {
println!("Group: {:?} - Type: {:?}", group.id, group.manager_type);
}
}
#[tokio::test]
async fn test_create_round_robin_group() {
let client = get_test_client();
let agent1 = client
.agents()
.create(CreateAgentRequest {
name: Some("Group Test Agent 1".to_string()),
model: Some("letta/letta-free".to_string()),
embedding: Some("letta/letta-free".to_string()),
agent_type: Some(AgentType::MemGPT),
system: Some("You are agent 1 in a group test.".to_string()),
tools: Some(vec!["send_message".to_string()]),
..Default::default()
})
.await
.expect("Failed to create agent 1");
let agent2 = client
.agents()
.create(CreateAgentRequest {
name: Some("Group Test Agent 2".to_string()),
model: Some("letta/letta-free".to_string()),
embedding: Some("letta/letta-free".to_string()),
agent_type: Some(AgentType::MemGPT),
system: Some("You are agent 2 in a group test.".to_string()),
tools: Some(vec!["send_message".to_string()]),
..Default::default()
})
.await
.expect("Failed to create agent 2");
let group_request = GroupCreate {
agent_ids: vec![agent1.id.clone(), agent2.id.clone()],
description: "Test round-robin group".to_string(),
manager_config: Some(GroupCreateManagerConfig::RoundRobin(RoundRobinManager {
max_turns: Some(10),
})),
shared_block_ids: None,
};
let group = client
.groups()
.create(group_request)
.await
.expect("Failed to create group");
println!("Created group: {:?}", group.id);
println!("Manager type: {:?}", group.manager_type);
println!("Agent count: {}", group.agent_ids.len());
let fetched_group = client
.groups()
.get(&group.id)
.await
.expect("Failed to get group");
assert_eq!(group.id, fetched_group.id);
assert_eq!(group.manager_type, fetched_group.manager_type);
let message_result = client
.groups()
.send_message(
&group.id,
vec![MessageCreate {
role: MessageRole::User,
content: "Hello group!".into(),
..Default::default()
}],
)
.await;
match message_result {
Ok(response) => {
println!("Group responded with {} messages", response.messages.len());
}
Err(e) => {
println!(
"Note: Group messaging returned error (expected on local server): {}",
e
);
}
}
let _ = client.groups().delete(&group.id).await;
let _ = client.agents().delete(&agent1.id).await;
let _ = client.agents().delete(&agent2.id).await;
}
#[tokio::test]
async fn test_group_agent_management() {
let client = get_test_client();
let mut agents = Vec::new();
for i in 1..=3 {
let agent = client
.agents()
.create(CreateAgentRequest {
name: Some(format!("Group Management Agent {}", i)),
model: Some("letta/letta-free".to_string()),
embedding: Some("letta/letta-free".to_string()),
agent_type: Some(AgentType::MemGPT),
system: Some(format!("You are agent {} for group management test.", i)),
tools: Some(vec!["send_message".to_string()]),
..Default::default()
})
.await
.expect(&format!("Failed to create agent {}", i));
agents.push(agent);
}
let group_request = GroupCreate {
agent_ids: vec![agents[0].id.clone(), agents[1].id.clone()],
description: "Test group for agent management".to_string(),
manager_config: Some(GroupCreateManagerConfig::RoundRobin(RoundRobinManager {
max_turns: None,
})),
shared_block_ids: None,
};
let group = client
.groups()
.create(group_request)
.await
.expect("Failed to create group");
println!("Created group with {} agents", group.agent_ids.len());
let group_agents = client
.groups()
.get(&group.id)
.await
.expect("Failed to list agents in group");
println!("Group has {} agents", group_agents.agent_ids.len());
assert_eq!(group_agents.agent_ids.len(), 2);
client
.groups()
.update(
&group.id,
GroupUpdate {
agent_ids: Some(vec![
agents[0].id.clone(),
agents[1].id.clone(),
agents[2].id.clone(),
]),
manager_config: Some(GroupUpdateManagerConfig::RoundRobin(
RoundRobinManagerUpdate { max_turns: None },
)),
shared_block_ids: group_agents.shared_block_ids.clone(),
description: Some(group_agents.description.clone()),
},
)
.await
.expect("Failed to add third agent to group");
println!("Added third agent to group");
let updated_group = client
.groups()
.get(&group.id)
.await
.expect("Failed to get updated group after adding agent");
assert_eq!(updated_group.agent_ids.len(), 3);
client
.groups()
.update(
&group.id,
GroupUpdate {
agent_ids: Some(vec![agents[1].id.clone(), agents[2].id.clone()]),
manager_config: Some(GroupUpdateManagerConfig::RoundRobin(
RoundRobinManagerUpdate { max_turns: None },
)),
shared_block_ids: group_agents.shared_block_ids.clone(),
description: Some(group_agents.description.clone()),
},
)
.await
.expect("Failed to update group configuration");
let updated_group = client
.groups()
.get(&group.id)
.await
.expect("Failed to get updated group after removing agent");
assert_eq!(updated_group.agent_ids.len(), 2);
let _ = client.groups().delete(&group.id).await;
for agent in agents {
let _ = client.agents().delete(&agent.id).await;
}
}
#[tokio::test]
#[ignore = "Supervisor groups require a specific supervisor agent setup"]
async fn test_create_supervisor_group() {
let _client = get_test_client();
let manager_config = GroupCreateManagerConfig::Supervisor(SupervisorManager {
manager_agent_id: LettaId::new_prefixed("agent", uuid::Uuid::new_v4()),
});
let json = serde_json::to_string(&manager_config).unwrap();
assert!(json.contains("\"manager_type\":\"supervisor\""));
}
#[tokio::test]
async fn test_agent_list_groups() {
let client = get_test_client();
let agent = client
.agents()
.create(CreateAgentRequest {
name: Some("Agent Groups List Test".to_string()),
model: Some("letta/letta-free".to_string()),
embedding: Some("letta/letta-free".to_string()),
agent_type: Some(AgentType::MemGPT),
system: Some("You are an agent to test group listing.".to_string()),
tools: Some(vec!["send_message".to_string()]),
..Default::default()
})
.await
.expect("Failed to create agent");
let agent2 = client
.agents()
.create(CreateAgentRequest {
name: Some("Agent Groups List Test 2".to_string()),
model: Some("letta/letta-free".to_string()),
embedding: Some("letta/letta-free".to_string()),
agent_type: Some(AgentType::MemGPT),
system: Some("You are the second agent in the group.".to_string()),
tools: Some(vec!["send_message".to_string()]),
..Default::default()
})
.await
.expect("Failed to create agent 2");
let group = client
.groups()
.create(GroupCreate {
agent_ids: vec![agent.id.clone(), agent2.id.clone()],
description: "Test group for agent list groups".to_string(),
manager_config: Some(GroupCreateManagerConfig::RoundRobin(RoundRobinManager {
max_turns: Some(5),
})),
shared_block_ids: None,
})
.await
.expect("Failed to create group");
let groups = client
.agents()
.list_groups(&agent.id)
.await
.expect("Failed to list agent groups");
println!("Agent {} belongs to {} groups", agent.id, groups.len());
assert!(groups.len() >= 1, "Agent should belong to at least 1 group");
assert!(
groups.iter().any(|g| g.id == group.id),
"Agent's group list should contain the created group"
);
let _ = client.groups().delete(&group.id).await;
let _ = client.agents().delete(&agent.id).await;
let _ = client.agents().delete(&agent2.id).await;
}