Conversations in T3Router allow you to maintain context across multiple message exchanges. The Client manages conversation state through thread IDs and message history, enabling natural multi-turn interactions.
A thread is a unique identifier that groups related messages together. When you send your first message, T3Router automatically creates a thread ID (UUID) and maintains it for subsequent messages in the same conversation.
use t3router::t3::client::Client;use t3router::t3::message::{Message, Type};use t3router::t3::config::Config;let mut client = Client::new(cookies, session_id);client.init().await?;let config = Config::new();// First message creates a new threadclient.send( "gemini-2.5-flash-lite", Some(Message::new(Type::User, "Hello!".to_string())), Some(config.clone()),).await?;// Get the thread IDif let Some(thread_id) = client.get_thread_id() { println!("Thread ID: {}", thread_id);}
Use new_conversation() to reset the thread and start fresh:
// First conversationclient.send( "gemini-2.5-flash-lite", Some(Message::new(Type::User, "Tell me about Paris".to_string())), Some(config.clone()),).await?;// Start a completely new conversationclient.new_conversation();client.send( "gemini-2.5-flash-lite", Some(Message::new(Type::User, "Now tell me about Tokyo".to_string())), Some(config.clone()),).await?;
for msg in client.get_messages() { let role = match msg.role { Type::User => "User", Type::Assistant => "Assistant", }; println!("{}: {}", role, msg.content);}
Manually append messages to the conversation history:
client.append_message(Message::new( Type::User, "What are the top 3 attractions?".to_string()));// Send without a new message to use the appended messagelet response = client.send( "gemini-2.5-flash-lite", None, Some(config),).await?;
let mut client = Client::new(cookies, session_id);client.init().await?;let config = Config::new();// Turn 1let response1 = client.send( "gemini-2.5-flash-lite", Some(Message::new( Type::User, "I'm planning a trip to Paris. What are the top 3 attractions?".to_string() )), Some(config.clone()),).await?;println!("Assistant: {}", response1.content);// Turn 2 - maintains context from turn 1let response2 = client.send( "gemini-2.5-flash-lite", Some(Message::new( Type::User, "Tell me more about the first one.".to_string() )), Some(config.clone()),).await?;println!("Assistant: {}", response2.content);// Turn 3 - still maintains full contextlet response3 = client.send( "gemini-2.5-flash-lite", Some(Message::new( Type::User, "What's the best time to visit?".to_string() )), Some(config.clone()),).await?;println!("Assistant: {}", response3.content);
client.new_conversation();// Set up game contextclient.append_message(Message::new( Type::User, "Let's play a word association game.".to_string()));client.append_message(Message::new( Type::Assistant, "Great! I'm ready to play. Go ahead with your first word!".to_string()));client.append_message(Message::new( Type::User, "Ocean".to_string()));client.append_message(Message::new( Type::Assistant, "Waves".to_string()));// Continue the gameclient.append_message(Message::new( Type::User, "Beach".to_string()));let response = client.send( "gemini-2.5-flash-lite", None, Some(config),).await?;println!("Assistant: {}", response.content);
println!("Thread ID: {:?}", client.get_thread_id());println!("Messages in conversation: {}", client.get_messages().len());// Check if conversation has startedif client.get_thread_id().is_some() { println!("Active conversation in progress");} else { println!("No active conversation");}
use t3router::t3::message::ContentType;use std::path::Path;client.new_conversation();// Text messagelet response1 = client.send( "gemini-2.5-flash-lite", Some(Message::new(Type::User, "What makes a good landscape photo?".to_string())), Some(config.clone()),).await?;println!("Text response: {}", response1.content);// Image generation in same conversationlet save_path = Path::new("output/landscape.png");let response2 = client.send_with_image_download( "gemini-imagen-4", Some(Message::new( Type::User, "Now create an example based on what you described".to_string() )), Some(config.clone()), Some(save_path),).await?;if matches!(response2.content_type, ContentType::Image) { println!("Image generated in same conversation!");}println!("Total messages: {}", client.get_messages().len());
// Attempting to send with no messagesclient.new_conversation();let response = client.send("model", None, Some(config)).await?;// Returns: Message with content "Error: No messages to send"// Correct approachclient.append_message(Message::new(Type::User, "Hello".to_string()));let response = client.send("model", None, Some(config)).await?;