How to manage threads

In shortStep-by-step guide to listing, inspecting, updating, and deleting conversation threads and messages.

  • 4 min read
  • 15 sections
  • Updated
  • v0.9.2
  • Markdown

10xGraph stores conversation history and state in threads. This guide shows you how to list threads, inspect their messages and state, update state directly, and delete threads when they are no longer needed.

Prerequisites


Step 1: List all threads

TypeScript
const response = await client.threads();
const threads = response.data.threads;

console.log(`Found ${threads.length} thread(s)`);
for (const t of threads) {
  console.log(`  [${t.thread_id}] ${t.thread_name ?? '(no name)'}, updated: ${t.updated_at}`);
}

Filter by name

Search for threads whose name contains a keyword:

TypeScript
const response = await client.threads({ search: 'Paris' });

Paginate

Retrieve 20 threads at a time starting from the first:

TypeScript
const response = await client.threads({ offset: 0, limit: 20 });

Paginate through all threads

TypeScript
async function* allThreads(pageSize = 50) {
  let offset = 0;
  while (true) {
    const res = await client.threads({ offset, limit: pageSize });
    const page = res.data.threads;
    if (page.length === 0) break;
    yield* page;
    offset += page.length;
    if (page.length < pageSize) break;
  }
}

for await (const thread of allThreads()) {
  console.log(thread.thread_id, thread.thread_name);
}

Step 2: Fetch thread details

Get metadata for a single thread (ID, name, user, timestamps):

TypeScript
const details = await client.threadDetails('thread-abc123');
console.log(details.data.thread_data.thread);

Step 3: List messages in a thread

TypeScript
const messages = await client.threadMessages('thread-abc123');

for (const msg of messages.data.messages) {
  const text = msg.content
    .filter(b => b.type === 'text')
    .map(b => (b as any).text as string)
    .join('');
  console.log(`[${msg.role}] ${text.slice(0, 100)}`);
}

Search messages

TypeScript
const results = await client.threadMessages('thread-abc123', {
  search: 'capital of France',
  limit: 10,
});

Step 4: Fetch a single message

TypeScript
const msg = await client.singleMessage('thread-abc123', 'msg-001');
console.log(msg.data.message);

Step 5: Delete a message

Remove an individual message from the thread’s history. Useful for cleaning up tool call messages that should not appear in the conversation:

TypeScript
await client.deleteMessage('thread-abc123', 'msg-001');

Step 6: Inspect thread state

Fetch the full graph state snapshot (the last checkpoint):

TypeScript
const stateResponse = await client.threadState(12345);
console.log(stateResponse.data);

The state object shape depends on your graph’s StateGraph definition.


Step 7: Update thread state

Write a new state snapshot for a thread. Use this to inject values, repair corrupted state, or seed initial data:

TypeScript
await client.updateThreadState(
  12345,
  {},                     // config body (the server derives it from the path thread_id)
  {
    user_preferences: { language: 'fr', timezone: 'Europe/Paris' },
    context_window: [],
  }
);

Step 8: Clear thread state

Remove the state snapshot without deleting the thread or its messages. The thread exists but will start fresh on the next invoke() call:

TypeScript
await client.clearThreadState(12345);

Step 9: Add messages to a thread

Inject messages directly into the thread’s history (useful for synthetic context or importing data):

TypeScript
await client.addThreadMessages(
  'thread-abc123',
  [
    Message.text_message('You are a Paris travel expert.', 'system'),
  ],
  {}                     // config body (the server derives it from the path thread_id)
);

Step 10: Delete a thread

Delete a thread and all its associated state and messages. This is irreversible:

TypeScript
await client.deleteThread('thread-abc123');

Build a thread history viewer

Putting it all together, a basic function that loads and displays a thread history:

TypeScript
import {
  AgentFlowClient,
  Message,
} from '10xgraph-client';

const client = new AgentFlowClient({ baseUrl: 'http://localhost:8000' });

async function showThreadHistory(threadId: string) {
  // Get details
  const details = await client.threadDetails(threadId);
  const thread = details.data.thread_data.thread;
  console.log(`Thread: ${thread.thread_name ?? threadId}`);

  // Get messages
  const msgs = await client.threadMessages(threadId, {
    offset: 0,
    limit: 100,
  });

  for (const msg of msgs.data.messages) {
    const text = msg.content
      .filter(b => b.type === 'text')
      .map(b => (b as any).text as string)
      .join('') || '[non-text content]';
    console.log(`[${msg.role.toUpperCase()}] ${text}`);
  }

  console.log(`\nTotal: ${msgs.data.messages.length} messages`);
}

await showThreadHistory('thread-abc123');

Common errors

Error Cause Fix
AgentFlowError status 404 Thread not found, or no checkpointer configured. Verify thread_id and check 10xgraph.json.
AgentFlowError status 422 Invalid thread_id (empty string or zero), message_id (empty), offset (< 0), or limit (≤ 0). Check the values you pass to each method.
Empty threads list Checkpointer not configured or no threads created yet. Compile the graph with a checkpointer (compile(checkpointer=...)).

What you learned

  • threads() lists all threads with optional search and pagination.
  • threadMessages() lists messages in a thread with search and pagination.
  • threadState() / updateThreadState() / clearThreadState() operate on the graph state snapshot.
  • deleteThread() removes everything, use clearThreadState() if you want to keep the history but reset the state.

Next step

See how-to/client/use-memory-api to learn how to store and retrieve long-term memories.

Last updated for v0.9.2Edit this page on GitHubReport an issue