use letta::types::memory::Block;
use letta::types::{
AgentType, CreateAgentRequest, CreateMessagesRequest, MessageCreate, MessageCreateContent,
MessageRole, UpdateMessageRequest, UpdateUserMessage, UpdateUserMessageContent,
};
use letta::{ClientConfig, LettaClient};
use serial_test::serial;
#[tokio::test]
async fn test_local_server_message_operations() {
let config = ClientConfig::new("http://localhost:8283").unwrap();
let client = LettaClient::new(config).unwrap();
println!("Creating test agent for message operations...");
let create_request = CreateAgentRequest::builder()
.name("Message Test Agent")
.agent_type(AgentType::MemGPT)
.model("letta/letta-free")
.embedding("letta/letta-free")
.memory_block(Block::human("The human's name is User"))
.memory_block(Block::persona("I am a helpful assistant"))
.build();
let agent = client.agents().create(create_request).await.unwrap();
let agent_id = &agent.id;
println!("Created test agent: {} ({})", agent.name, agent_id);
println!("Testing message list for agent: {}", agent_id);
let messages = client.messages().list(agent_id, None).await.unwrap();
println!("✅ Found {} existing messages", messages.len());
println!("Testing message creation...");
let message_request = CreateMessagesRequest {
messages: vec![MessageCreate {
role: MessageRole::User,
content: MessageCreateContent::String(
"Hello! This is a test message from the Rust SDK.".to_string(),
),
name: None,
otid: None,
sender_id: None,
batch_item_id: None,
group_id: None,
}],
max_steps: Some(3), ..Default::default()
};
let response = client
.messages()
.create(agent_id, message_request)
.await
.unwrap();
println!("✅ Message sent successfully!");
println!(" Stop reason: {:?}", response.stop_reason);
println!(" Usage: {:?} total tokens", response.usage.total_tokens);
println!(
" Received {} messages in response",
response.messages.len()
);
for (i, message) in response.messages.iter().enumerate() {
match message {
letta::types::LettaMessageUnion::UserMessage(msg) => {
println!(" Message {}: [User] {}", i + 1, msg.content);
}
letta::types::LettaMessageUnion::AssistantMessage(msg) => {
println!(" Message {}: [Assistant] {}", i + 1, msg.content);
}
letta::types::LettaMessageUnion::SystemMessage(msg) => {
println!(" Message {}: [System] {}", i + 1, msg.content);
}
letta::types::LettaMessageUnion::ReasoningMessage(msg) => {
println!(" Message {}: [Reasoning] {}", i + 1, msg.reasoning);
}
_ => {
println!(" Message {}: [Other] {:?}", i + 1, message);
}
}
}
let updated_messages = client.messages().list(agent_id, None).await.unwrap();
println!(
"✅ After sending message, found {} messages in current page",
updated_messages.len()
);
println!("✅ Message API operations completed successfully!");
println!("✅ All message API tests passed!");
println!("Cleaning up test agent...");
client
.agents()
.delete(agent_id)
.await
.expect("Failed to delete test agent");
println!("✅ Test agent deleted");
}
#[tokio::test]
async fn test_local_server_message_reset() {
let config = ClientConfig::new("http://localhost:8283").unwrap();
let client = LettaClient::new(config).unwrap();
println!("Creating test agent for message reset...");
let create_request = CreateAgentRequest::builder()
.name("Reset Test Agent")
.agent_type(AgentType::MemGPT)
.model("letta/letta-free")
.embedding("letta/letta-free")
.build();
let agent = client.agents().create(create_request).await.unwrap();
let agent_id = &agent.id;
println!("Created test agent: {} ({})", agent.name, agent_id);
println!("Testing message reset for agent: {}", agent_id);
let messages_before = client.messages().list(agent_id, None).await.unwrap();
println!("Messages before reset: {}", messages_before.len());
let reset_agent = client.messages().reset(agent_id, Some(true)).await.unwrap();
println!("✅ Agent messages reset successfully");
println!(" Agent name: {}", reset_agent.name);
let messages_after = client.messages().list(agent_id, None).await.unwrap();
println!("Messages after reset: {}", messages_after.len());
println!("✅ Message reset test completed");
println!("Cleaning up test agent...");
client
.agents()
.delete(agent_id)
.await
.expect("Failed to delete test agent");
println!("✅ Test agent deleted");
}
#[tokio::test]
#[serial]
async fn test_update_user_message() {
let config = ClientConfig::new("http://localhost:8283").unwrap();
let client = LettaClient::new(config).unwrap();
println!("Creating test agent for message update...");
let create_request = CreateAgentRequest::builder()
.name("Update Test Agent")
.agent_type(AgentType::MemGPT)
.model("letta/letta-free")
.embedding("letta/letta-free")
.memory_block(Block::human("The human's name is User"))
.memory_block(Block::persona("I am a helpful assistant"))
.build();
let agent = client.agents().create(create_request).await.unwrap();
let agent_id = &agent.id;
println!("Created test agent: {} ({})", agent.name, agent_id);
let create_request = CreateMessagesRequest {
messages: vec![MessageCreate {
role: MessageRole::User,
content: "Original message content".into(),
..Default::default()
}],
..Default::default()
};
let _response = client
.messages()
.create(agent_id, create_request)
.await
.unwrap();
let messages = client.messages().list(agent_id, None).await.unwrap();
let user_message_id = messages
.iter()
.find_map(|msg| match msg {
letta::types::LettaMessageUnion::UserMessage(user_msg)
if user_msg.content == "Original message content" =>
{
Some(user_msg.id.clone())
}
_ => None,
})
.expect("Should find the user message we created");
let update_request = UpdateMessageRequest::UserMessage(UpdateUserMessage {
content: UpdateUserMessageContent::String("Updated message content".to_string()),
});
let updated_message = client
.messages()
.update(agent_id, &user_message_id, update_request)
.await
.unwrap();
match updated_message {
letta::types::LettaMessageUnion::UserMessage(user_msg) => {
assert_eq!(user_msg.content, "Updated message content");
println!("✅ Message update successful!");
}
_ => panic!("Expected user message in response"),
}
println!("Cleaning up test agent...");
client
.agents()
.delete(agent_id)
.await
.expect("Failed to delete test agent");
println!("✅ Test agent deleted");
}
#[tokio::test]
#[serial]
async fn test_create_async_message() {
let config = ClientConfig::new("http://localhost:8283").unwrap();
let client = LettaClient::new(config).unwrap();
println!("Creating test agent for async message creation...");
let create_request = CreateAgentRequest::builder()
.name("Async Message Test Agent")
.agent_type(AgentType::MemGPT)
.model("letta/letta-free")
.embedding("letta/letta-free")
.memory_block(Block::human("The human's name is User"))
.memory_block(Block::persona("I am a helpful assistant"))
.build();
let agent = client.agents().create(create_request).await.unwrap();
let agent_id = &agent.id;
println!("Created test agent: {} ({})", agent.name, agent_id);
let create_request = CreateMessagesRequest {
messages: vec![MessageCreate {
role: MessageRole::User,
content: "Tell me a joke".into(),
..Default::default()
}],
..Default::default()
};
let run = client
.messages()
.create_async(agent_id, create_request)
.await
.unwrap();
assert_eq!(run.id.prefix(), Some("run")); println!("✅ Async message created with run ID: {}", run.id);
if let Some(status) = run.status {
match status {
letta::types::JobStatus::Created
| letta::types::JobStatus::Running
| letta::types::JobStatus::Pending => {
println!(" Run status: {:?}", status);
}
_ => panic!("Unexpected initial status: {:?}", status),
}
}
println!("Cleaning up test agent...");
client
.agents()
.delete(agent_id)
.await
.expect("Failed to delete test agent");
println!("✅ Test agent deleted");
}
#[tokio::test]
#[serial]
async fn test_message_pagination() {
use futures::StreamExt;
use letta::types::PaginationParams;
let config = ClientConfig::new("http://localhost:8283").unwrap();
let client = LettaClient::new(config).unwrap();
println!("Creating test agent for pagination test...");
let create_request = CreateAgentRequest::builder()
.name("Message Pagination Test Agent")
.agent_type(AgentType::MemGPT)
.model("letta/letta-free")
.embedding("letta/letta-free")
.memory_block(Block::human("The human's name is User"))
.memory_block(Block::persona("I am a helpful assistant"))
.build();
let agent = client.agents().create(create_request).await.unwrap();
let agent_id = &agent.id;
println!("Created test agent: {} ({})", agent.name, agent_id);
println!("Checking existing messages...");
let existing_messages = client.messages().list(agent_id, None).await.unwrap();
println!("Found {} existing messages", existing_messages.len());
if existing_messages.len() < 3 {
println!("Creating one test message (Letta server can be slow)...");
let message_request = CreateMessagesRequest {
messages: vec![MessageCreate {
role: MessageRole::User,
content: "Pagination test message".into(),
..Default::default()
}],
max_steps: Some(1),
..Default::default()
};
match client.messages().create(agent_id, message_request).await {
Ok(response) => {
println!(
" Created message (got {} messages in response)",
response.messages.len()
);
}
Err(e) => {
eprintln!(" Warning: Failed to create message: {:?}", e);
eprintln!(" Will proceed with existing messages only");
}
}
}
println!("\nTesting paginated iteration with limit 3...");
let mut stream = client
.messages()
.paginated(agent_id, Some(PaginationParams::new().limit(3)));
let mut count = 0;
while let Some(result) = stream.next().await {
match result {
Ok(message) => {
println!(" Found message: {:?}", message);
count += 1;
if count >= 10 {
break; }
}
Err(e) => {
eprintln!(" Error during pagination: {:?}", e);
break;
}
}
}
println!("Total messages found via pagination: {}", count);
assert!(count > 0, "Should find at least one message");
println!("\nTesting collect with pagination...");
let collected_messages = client
.messages()
.paginated(agent_id, Some(PaginationParams::new().limit(5)))
.take(10)
.collect::<Vec<_>>()
.await
.into_iter()
.collect::<Result<Vec<_>, _>>()
.unwrap();
println!("Collected {} messages", collected_messages.len());
assert!(
!collected_messages.is_empty(),
"Should collect at least one message"
);
println!("\nCleaning up test agent...");
match client.agents().delete(agent_id).await {
Ok(_) => println!("✅ Test agent deleted"),
Err(e) => println!("Warning: Failed to delete test agent: {:?}", e),
}
}