Threads
Overview
Threads represent conversation sessions with assistants in LlmTornado. They maintain message history and context across multiple interactions, making it easy to build stateful conversations. Threads work together with Assistants to provide a complete conversational AI experience.
Quick Start
csharp
using LlmTornado;
using LlmTornado.Threads;
TornadoApi api = new TornadoApi("your-api-key");
// Create a thread
HttpCallResult<TornadoThread> thread = await api.Threads.CreateThread();
Console.WriteLine($"Thread ID: {thread.Data.Id}");
// Add a message to the thread
HttpCallResult<AssistantMessage> message = await api.Threads.CreateMessage(
thread.Data.Id,
new CreateMessageRequest("Hello, can you help me?"));
Console.WriteLine($"Message added: {message.Data.Id}");Prerequisites
- The LlmTornado package installed
- A valid API key with threads access
- Understanding of Assistants
- Familiarity with conversation patterns
Basic Usage
Create a Thread
csharp
HttpCallResult<TornadoThread> thread = await api.Threads.CreateThread();
Console.WriteLine($"Created thread: {thread.Data.Id}");Create Thread with Initial Messages
csharp
HttpCallResult<TornadoThread> thread = await api.Threads.CreateThread(
new CreateThreadRequest
{
Messages = new List<CreateMessageRequest>
{
new CreateMessageRequest("Hello!"),
new CreateMessageRequest("I need help with programming.")
}
});Retrieve a Thread
csharp
HttpCallResult<TornadoThread> thread = await api.Threads.RetrieveThread("thread_id");
Console.WriteLine($"Thread metadata: {thread.Data.Metadata}");Modify a Thread
csharp
HttpCallResult<TornadoThread> updated = await api.Threads.ModifyThread(
"thread_id",
new ModifyThreadRequest
{
Metadata = new Dictionary<string, string>
{
{"user_id", "12345"},
{"session", "active"}
}
});Delete a Thread
csharp
HttpCallResult<bool> deleted = await api.Threads.DeleteThread("thread_id");
Console.WriteLine($"Thread deleted: {deleted.Data}");Working with Messages
Add a Message
csharp
HttpCallResult<AssistantMessage> message = await api.Threads.CreateMessage(
"thread_id",
new CreateMessageRequest("What is the weather today?"));List Messages
csharp
HttpCallResult<ListResponse<AssistantMessage>> messages =
await api.Threads.ListMessages("thread_id");
foreach (AssistantMessage message in messages.Data.Items)
{
Console.WriteLine($"{message.Role}: {message.Content}");
}Retrieve a Specific Message
csharp
HttpCallResult<AssistantMessage> message =
await api.Threads.RetrieveMessage("thread_id", "message_id");
Console.WriteLine($"Content: {message.Data.Content}");Modify a Message
csharp
HttpCallResult<AssistantMessage> updated = await api.Threads.ModifyMessage(
"thread_id",
"message_id",
new ModifyMessageRequest
{
Metadata = new Dictionary<string, string>
{
{"edited", "true"}
}
});Delete a Message
csharp
HttpCallResult<bool> deleted = await api.Threads.DeleteMessage(
"thread_id",
"message_id");Running Assistants on Threads
Create and Run
csharp
// Create a run to get assistant response
HttpCallResult<TornadoRun> run = await api.Threads.CreateRun(
"thread_id",
new CreateRunRequest("assistant_id")
{
Model = ChatModel.OpenAi.Gpt4.O241120,
Instructions = "You are a helpful assistant."
});
// Wait for completion
while (run.Data.Status == "queued" || run.Data.Status == "in_progress")
{
await Task.Delay(1000);
run = await api.Threads.RetrieveRun("thread_id", run.Data.Id);
}
// Get the assistant's response
HttpCallResult<ListResponse<AssistantMessage>> messages =
await api.Threads.ListMessages("thread_id");Stream Run Results
csharp
await api.Threads.StreamRun(
"thread_id",
new CreateRunRequest("assistant_id"),
async (chunk) =>
{
Console.Write(chunk);
});Advanced Usage
Complete Conversation Flow
csharp
// 1. Create thread
HttpCallResult<TornadoThread> thread = await api.Threads.CreateThread();
// 2. Add user message
await api.Threads.CreateMessage(
thread.Data.Id,
new CreateMessageRequest("Explain quantum computing"));
// 3. Run assistant
HttpCallResult<TornadoRun> run = await api.Threads.CreateRun(
thread.Data.Id,
new CreateRunRequest("assistant_id"));
// 4. Wait for completion
while (run.Data.Status == "in_progress")
{
await Task.Delay(1000);
run = await api.Threads.RetrieveRun(thread.Data.Id, run.Data.Id);
}
// 5. Get response
HttpCallResult<ListResponse<AssistantMessage>> messages =
await api.Threads.ListMessages(thread.Data.Id);
AssistantMessage lastMessage = messages.Data.Items.First();
Console.WriteLine($"Assistant: {lastMessage.Content}");Multi-Turn Conversation
csharp
string threadId = (await api.Threads.CreateThread()).Data.Id;
string assistantId = "your_assistant_id";
async Task<string> SendMessage(string text)
{
// Add user message
await api.Threads.CreateMessage(
threadId,
new CreateMessageRequest(text));
// Run assistant
HttpCallResult<TornadoRun> run = await api.Threads.CreateRun(
threadId,
new CreateRunRequest(assistantId));
// Wait for completion
while (run.Data.Status == "in_progress")
{
await Task.Delay(1000);
run = await api.Threads.RetrieveRun(threadId, run.Data.Id);
}
// Get latest message
HttpCallResult<ListResponse<AssistantMessage>> messages =
await api.Threads.ListMessages(threadId);
return messages.Data.Items.First().Content;
}
// Have a conversation
string response1 = await SendMessage("What is machine learning?");
Console.WriteLine($"AI: {response1}");
string response2 = await SendMessage("Can you give me an example?");
Console.WriteLine($"AI: {response2}");Best Practices
- Thread Lifecycle - Clean up old threads regularly
- Metadata Usage - Tag threads with user/session info
- Error Handling - Handle run failures gracefully
- Pagination - Use pagination for long message histories
- Rate Limiting - Respect API rate limits
Common Issues
Run Stuck in Progress
- Solution: Implement timeout and retry logic
- Prevention: Monitor run status and set reasonable timeouts
Messages Out of Order
- Solution: Use message timestamps to sort
- Prevention: Always fetch latest messages after runs
Thread Context Lost
- Solution: Retrieve thread before continuing conversation
- Prevention: Store thread IDs persistently
API Reference
TornadoThread
string Id- Thread identifierDictionary<string, string> Metadata- Custom metadatalong CreatedAt- Creation timestamp
AssistantMessage
string Id- Message identifierstring ThreadId- Parent threadstring Role- Message role (user/assistant)string Content- Message contentList<Attachment> Attachments- File attachments
CreateRunRequest
string AssistantId- Assistant to useChatModel Model- Optional model overridestring Instructions- Optional instruction overrideList<AssistantTool> Tools- Optional tool override
Related Topics
- Assistants - Creating and managing assistants
- Vector Stores - Knowledge bases for assistants
- Chat Basics - Core conversation concepts
- Files - File attachments