Skip to content

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

  1. Thread Lifecycle - Clean up old threads regularly
  2. Metadata Usage - Tag threads with user/session info
  3. Error Handling - Handle run failures gracefully
  4. Pagination - Use pagination for long message histories
  5. 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 identifier
  • Dictionary<string, string> Metadata - Custom metadata
  • long CreatedAt - Creation timestamp

AssistantMessage

  • string Id - Message identifier
  • string ThreadId - Parent thread
  • string Role - Message role (user/assistant)
  • string Content - Message content
  • List<Attachment> Attachments - File attachments

CreateRunRequest

  • string AssistantId - Assistant to use
  • ChatModel Model - Optional model override
  • string Instructions - Optional instruction override
  • List<AssistantTool> Tools - Optional tool override