Skip to content

Threads

Threads persist conversation state across requests. Thread management endpoints (list, update, delete) require a Bearer token from TIE Auth.

Pass a thread_id in your /v1/chat/completions request to maintain conversation state. TIE uses it to persist message history so the LLM has context from previous turns.

  • If omitted, TIE auto-generates a UUID for the thread. Each request starts a new conversation.
  • If provided, TIE resumes the conversation from where it left off. Use any string (e.g. a UUID you generate client-side).

Threads can be scoped to a specific application using the X-App-Id header. This allows multiple apps to share the same TIE backend while keeping their conversation threads separate.

  • X-App-Id provided — the thread is scoped to that app. Only requests with the same X-App-Id can see, rename, or delete it.
  • X-App-Id omitted — the thread is unscoped (shared). It is visible when listing threads without X-App-Id, but hidden from app-scoped lists.
Terminal window
# Create a thread scoped to "vibrantly"
curl -X POST https://your-tie-host/v1/chat/completions \
-H "Authorization: Bearer $TOKEN" \
-H "X-App-Id: vibrantly" \
-H "X-Agent-Id: chatbot" \
-d '{"model": "anthropic/claude-sonnet-4-5", "messages": [{"role": "user", "content": "Hello"}], "thread_id": "my-thread"}'

Each thread can carry an arbitrary JSON metadata object. Use it to store application-specific context that doesn't belong in the conversation itself — for example, where the thread originated, which page it's associated with, or whether it's pinned in a UI.

{
"source": "whatsapp",
"pageType": "whatsapp-dm",
"pageId": "550e8400-e29b-41d4-a716-446655440000",
"isPinned": false
}

Metadata is set and updated via the Update Thread endpoint. It is returned in every thread summary (list and update responses). TIE stores metadata as-is and does not interpret it — your application defines the schema.

Returns threads for the authenticated user. Supports cursor-based pagination, sorting, and date filtering.

Terminal window
GET https://your-tie-host/threads
Authorization: Bearer $TOKEN

Headers:

HeaderTypeDefaultDescription
X-App-IdstringnullFilter threads by app. When set, only threads matching that exact app ID are returned (unscoped threads are excluded). When omitted, all threads are returned (both scoped and unscoped).

Query parameters:

ParameterTypeDefaultDescription
agent_idstringnullFilter threads by agent
cursorstringnullPagination token from a previous response (treat as opaque; do not parse or construct it)
limitinteger20Results per page (1-100)
order_bystringcreated_atSort field: created_at or updated_at
ascbooleanfalseSort direction: true for ascending (oldest first), false for descending (newest first)
created_afterISO 8601 datetimenullOnly return threads created on or after this timestamp
created_beforeISO 8601 datetimenullOnly return threads created on or before this timestamp

Response:

{
"threads": [
{
"thread_id": "847c6285-8fc9-4560-a83f-4e6285809254",
"agent_id": "chatbot",
"app_id": "vibrantly",
"title": "What is the weather in Tokyo?",
"metadata": {
"source": "whatsapp",
"isPinned": false
},
"created_at": "2026-03-25T10:00:00+00:00",
"updated_at": "2026-03-25T10:05:00+00:00"
}
],
"next_cursor": "MjAyNi0wMy0yNVQxMDowMDowMCswMDowMHw4NDdjNjI4NS04ZmM5LTQ1NjAtYTgzZi00ZTYyODU4MDkyNTQ="
}

Pass next_cursor as the cursor query parameter to fetch the next page. When next_cursor is null, there are no more results.

The app_id field is null for unscoped threads. The metadata field is null when no metadata has been set.

Retrieve the full message history for a thread:

Terminal window
POST https://your-tie-host/history
Authorization: Bearer $TOKEN
Content-Type: application/json
{ "thread_id": "<your-thread-id>" }

Response:

{
"messages": [
{
"type": "human",
"content": "What is the weather in Tokyo?",
"metadata": {
"session_id": "8b94776f-31ae-49ac-9f06-3be137d69186",
"platform": "ios",
"app_version": "2.4.1"
}
},
{
"type": "ai",
"content": "The current weather in Tokyo is...",
"metadata": null
}
]
}

The metadata field on user messages contains the key-value pairs sent with the original request. AI messages have metadata: null since metadata is attached at request time, not per-response.

Update a thread's title and/or metadata. The title is automatically set from the first user message, but you can override it. Metadata can be set at any time.

At least one of title or metadata must be provided in the request body.

Terminal window
PATCH https://your-tie-host/threads/<thread-id>
Authorization: Bearer $TOKEN
Content-Type: application/json
# Required only if the thread was created with X-App-Id
X-App-Id: vibrantly
{ "title": "My weather conversation", "metadata": { "isPinned": true } }

Request body:

FieldTypeRequiredDescription
titlestringNoNew title for the thread (1-500 characters, cannot be blank)
metadataobject | nullNoArbitrary metadata dict. Replaces existing metadata entirely. Pass null to clear.

You can send either field alone or both together:

Terminal window
# Rename only
{ "title": "New title" }
# Set metadata only
{ "metadata": { "source": "telegram", "isPinned": false } }
# Clear metadata
{ "metadata": null }

Response:

{
"thread_id": "847c6285-8fc9-4560-a83f-4e6285809254",
"agent_id": "chatbot",
"app_id": "vibrantly",
"title": "My weather conversation",
"metadata": { "isPinned": true },
"created_at": "2026-03-25T10:00:00+00:00",
"updated_at": "2026-03-25T10:10:00+00:00"
}

Permanently delete a thread and all its data (title, metadata, timestamps, agent/app association):

Terminal window
DELETE https://your-tie-host/threads/<thread-id>
Authorization: Bearer $TOKEN
# Required only if the thread was created with X-App-Id
X-App-Id: vibrantly

Response:

{ "status": "deleted", "thread_id": "847c6285-8fc9-4560-a83f-4e6285809254" }
CodeStatusWhen
AUTH_TOKEN_MISSING401No Bearer token provided
THREAD_NOT_FOUND404Thread does not exist or is not owned by the user
VALIDATION_ERROR422Invalid cursor, empty title, title exceeds 500 characters, or empty update body
THREADS_FETCH_FAILED500Unexpected server error while listing threads
THREAD_UPDATE_FAILED500Unexpected server error while updating a thread
THREAD_DELETE_FAILED500Unexpected server error while deleting a thread
SERVICE_UNAVAILABLE501Thread management requires the PostgreSQL memory backend