Skip to main content
Threads are AI-powered conversation sessions grounded in your Knowledge Stack documents. The assistant retrieves relevant chunks from your knowledge base, cites its sources, and streams responses in real time via Server-Sent Events (SSE).

Create a thread

Start by creating a thread. You can optionally set its title and place it in a specific folder.
curl -X POST https://api-staging.knowledgestack.ai/v1/threads \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Q3 Revenue Analysis",
    "parent_path_part_id": "<folder-path-part-id>"
  }'
Request fields
FieldTypeDescription
parent_path_part_idUUIDOptional. Folder to store the thread in. When omitted, the thread is placed in your personal threads folder automatically
titlestringOptional. Thread title (max 255 characters). Mutually exclusive with message_for_title
message_for_titlestringOptional. Pass a message here to have the API auto-generate a title from it. The message is not sent as a conversation message. Mutually exclusive with title
Response
{
  "id": "t1a2b3c4-...",
  "path_part_id": "pp1a2b3-...",
  "title": "Q3 Revenue Analysis",
  "materialized_path": "/shared/finance/threads/q3-revenue-analysis",
  "tenant_id": "tn1a2b3-...",
  "created_at": "2024-10-15T09:00:00Z",
  "updated_at": "2024-10-15T09:00:00Z"
}
Save the id — you need it for all subsequent thread operations.

Send a message

Send a user message to the thread. The API returns immediately with a workflow_id; the assistant response is generated asynchronously and delivered via the SSE stream.
curl -X POST https://api-staging.knowledgestack.ai/v1/threads/<thread-id>/user_message \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "input_text": "What were the key revenue drivers in Q3?"
  }'
Request fields
FieldTypeDescription
input_textstringThe user’s message text
Response (202)
{
  "workflow_id": "thread-agent:01929abc-..."
}
The 202 Accepted status means the message was received and the agent is generating a response. Connect to the SSE stream to receive it.

Stream the response

GET /v1/threads/{thread_id}/stream opens an SSE connection. The server pushes events as the assistant generates its response, allowing you to display content token-by-token.
curl -N -X GET "https://api-staging.knowledgestack.ai/v1/threads/<thread-id>/stream" \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Accept: text/event-stream"
Stream query parameters
ParameterDescription
last_message_idUUID of the last message you received. Use this to resume a dropped stream without missing events
last_entry_idLast SSE entry ID received. Paired with last_message_id to replay missed entries
The SSE stream stays open until the assistant finishes generating. Keep the connection alive and handle reconnections using the last_message_id and last_entry_id parameters.

List messages

Once generation is complete, retrieve all messages in the thread:
curl -X GET "https://api-staging.knowledgestack.ai/v1/threads/<thread-id>/messages" \
  -H "Authorization: Bearer <your-api-key>"
The response is a paginated list of ThreadMessageResponse objects.

Message structure

{
  "id": "m1a2b3c4-...",
  "sequence": 2,
  "role": "ASSISTANT",
  "content": {
    "text": "The key revenue drivers in Q3 were...",
    "is_error": false,
    "citations": [
      {
        "chunk_id": "c1a2b3-...",
        "quote": "Product revenue grew 34% YoY driven by...",
        "start_char": 0,
        "length": 48,
        "document_id": "d1a2b3-...",
        "document_name": "Q3 Earnings Report.pdf",
        "version_number": 1
      }
    ],
    "references": []
  },
  "created_at": "2024-10-15T09:01:12Z"
}

Message roles

RoleDescription
USERA message sent by the user
ASSISTANTA response generated by the AI
SYSTEMA system-level message (e.g. thread configuration)

Citations

Each assistant message includes a citations array of EnrichedCitation objects. Each citation links the assistant’s text back to the exact chunk it was sourced from.
FieldDescription
chunk_idID of the source chunk
quoteThe exact text quoted from the chunk
start_char0-based character offset of the quote within the chunk
lengthLength of the quoted string
document_idID of the source document
document_nameHuman-readable document name
version_numberDocument version the chunk belongs to
path_part_idPath part ID for direct navigation
materialized_pathFull path of the chunk in the folder hierarchy

Full conversation flow

1
Create a thread
2
THREAD=$(curl -sX POST https://api-staging.knowledgestack.ai/v1/threads \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Policy Questions"}')
THREAD_ID=$(echo $THREAD | jq -r '.id')
3
Send a message
4
curl -X POST "https://api-staging.knowledgestack.ai/v1/threads/$THREAD_ID/user_message" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input_text": "What is the maximum file size for uploads?"}'
5
Open the SSE stream
6
curl -N "https://api-staging.knowledgestack.ai/v1/threads/$THREAD_ID/stream" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: text/event-stream"
7
Read completed messages
8
curl "https://api-staging.knowledgestack.ai/v1/threads/$THREAD_ID/messages" \
  -H "Authorization: Bearer $API_KEY"

Submit feedback

Collect user feedback on thread messages to improve quality or flag errors. The feedback endpoint is an upsert — submitting again with the same target_id updates the existing record.
curl -X POST https://api-staging.knowledgestack.ai/v1/feedback \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "target_type": "MESSAGE",
    "target_id": "<message-id>",
    "rating": "DOWN",
    "reason": "BAD_CITATIONS",
    "comment": "The cited document does not support this claim."
  }'
Request fields
FieldTypeRequiredDescription
target_typestringYesEntity to rate: THREAD, MESSAGE, DOCUMENT, DOCUMENT_VERSION, or CHUNK
target_idUUIDYesID of the entity being rated
ratingstringYesUP (positive) or DOWN (negative)
reasonstringNoReason code for negative feedback (see below)
commentstringNoFree-text comment (max 4000 characters)
Feedback reason codes
CodeUse when
INCORRECTThe answer is factually wrong
MISSING_INFOImportant information was left out
NOT_RELEVANTThe response didn’t address the question
BAD_CITATIONSCitations don’t support the claim
HALLUCINATIONThe assistant invented information not in the knowledge base
OCR_ERRORSource text was misread during ingestion
PARSING_ERRORDocument structure was incorrectly parsed
STRUCTURE_ISSUEHeadings, sections, or hierarchy are wrong
TABLE_ERRORTable data was extracted incorrectly
FORMATTINGResponse formatting is poor
OTHERAny other issue
Collecting DOWN feedback with a reason helps you identify whether quality issues originate in ingestion (OCR, parsing) or retrieval (bad citations, hallucination), so you can target improvements effectively.