curl -X POST \
--url 'https://{ThoughtSpot-Host}/api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send/stream' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {AUTH_TOKEN}' \
--data-raw '{
"conversation_identifier": "h2I_pTGaRQof",
"messages": [
"Net sales of Jackets"
]
}'
Spotter agent streaming APIs
ThoughtSpotβs Spotter agent streaming API lets you send natural language queries to an existing conversation session and receive the response as a real-time Server-Sent Events (SSE) stream, instead of waiting for the complete response.
For information about creating a conversation session and sending queries to it, see Spotter agent conversation APIs.
Send a query to agent and get streaming responsesπ
To send queries to an ongoing conversation session with Spotter agent and receive streaming responses, use the /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send/stream API endpoint. This API endpoint uses the SSE protocol to deliver data incrementally in real time, rather than waiting for the entire response to be generated before sending it to the client.
The /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send/stream API can be used as an integrated tool for real-time streaming of conversational interactions between agents and the ThoughtSpot backend.
Request parametersπ
| Parameter | Description |
|---|---|
| String. Specify the conversation ID received from the POST /api/rest/2.0/ai/agent/conversation/create API call. |
| Array of strings. Include at least one natural language query. For example, |
Example requestπ
API responseπ
If the API request is successful, the response includes a stream of events, each containing a partial or complete message from the AI agent, rather than a single JSON object.
Each event is a simple text-based message in a specific format, data: <your_data>\n\n; <your_data>\n\n means that each message sent from the server to the client is prefixed with the data: keyword, followed by the actual payload (<your_data>), and ends with two newline characters (\n\n).
The API uses this format so that the clients can reconstruct the AI-generated response as it streams in, chunk by chunk, and show the responses in real-time. In agentic workflows, the receiving client or agent listens to the SSE stream, parses each event, and assembles the full response for its users.
Example responseπ
If the request is valid, the API returns SSE streams. Each line has the form data: [{"type": "β¦β", β¦β}], a JSON array of event objects.
data: [{"type":"ack","node_id":"aGxzcFVrtom8"}]
data: [{"type":"conv_title","title":"Sales 2025 vs 2024","conv_id":"-XIi04l5rrof"}]
data: [{"type":"notification","group_id":"cDEsAQbSnd3J","metadata":{"type":"thinking","tool_title":"Analyzing Sales Performance: 2025 vs 2024"},"code":"TOOL_CALL_NOTIFICATION"}]
data: [{"id":"mNAdvy-NK2l6","type":"text-chunk","group_id":"cDEsAQbSnd3J","metadata":{"format":"markdown","type":"thinking"},"content":"\n\nI need to compare sales performance between 2025 and 2024."}]
data: [{"type":"notification","group_id":"m1MTvttEUa7o","code":"nls_start"}]
data: [{"id":"hxWMDP-pgR3B","type":"answer","group_id":"m1MTvttEUa7o","metadata":{"sage_query":"[sales] [date] = '2025' vs [date] = '2024'","session_id":"431adcf9-1328-4d8c-81a1-0faa7fa37ba6","title":"Compare sales for 2025 vs 2024"},"title":"Compare sales for 2025 vs 2024"}]
data: [{"type":"notification","code":"FINAL_RESPONSE_NOTIFICATION"}]
For the complete response in one payload, use the /send endpoint instead.
SSE event typesπ
The SSE event types streamed in the API response include:
-
ack
Confirms receipt of the request. For example, the type in the first messagedata: [{"type": "ack", "node_id": "BRxCtJ-aGt8l"}], which indicates that the server has received the clientβs request and is acknowledging it. -
conv_title
A conversation title (title,conv_id). -
notification
Progress or status update (group_id,metadata,code). For example,TOOL_CALL_NOTIFICATION,nls_start,FINAL_RESPONSE_NOTIFICATION. -
type
Type can bethinking,text. -
text
Complete text block in markdown format. -
text-chunk
Text fragments in incremental streaming, often in markdown (id,group_id,metadatawithformat) -
content
The actual text content sent incrementally. For example,"I","understand","youβre","interested","in","the","net","sales", and so on. -
answer
Structured answer with metadata (id,group_id,metadatawithsage_query,session_id,titleand more) -
error
In case of failures. -
*-interrupt
If the generation was stopped mid-stream. -
group_id
Groups related chunks together.
For more information and examples, see SSE event payload reference.
Thinking versus output eventsπ
Spotter responses have two phases:
-
A thinking phase, where the AI reasons through the query and calls internal tools, followed by an output phase containing the final response delivered to the user.
Events in the thinking phase carry "metadata": { "type": "thinking" }. All other events are final output.
Every event includes a group_id. Events sharing the same group_id belong together. During the thinking phase, each tool call gets its own group_id. A FINAL_RESPONSE_NOTIFICATION notification marks the boundary between the thinking and output phases.
THINKING PHASE
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ack
ββ group_id: g1 ββ Tool Call 1 ("Searching data") ββββββββββ
β notification (thinking, TOOL_CALL_NOTIFICATION) β
β text-chunk (thinking) β
β answer (thinking) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββ group_id: g2 ββ Tool Call 2 ("Running code") ββββββββββββ
β notification (thinking, TOOL_CALL_NOTIFICATION) β
β text-chunk (thinking) β
β text-chunk (thinking) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
notification (FINAL_RESPONSE_NOTIFICATION) βββ boundary
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
OUTPUT PHASE
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββ group_id: g3 βββββββββββββββββββββββββββββββββββββββββββββ
β text "Here are the results:" β
β answer (final visualization) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
[stream closes]
Notification codes referenceπ
| Code | When it appears |
|---|---|
| Query handling started |
| Generating or retrying TML |
| Generating an answer |
| Identifying data attributes |
| Running change analysis |
| Running forecasting |
| Summarizing results |
| Tool invocation (during thinking phase) |
| Marks the transition from thinking to output |
| Data source discovery in progress or complete |
| An external tool requires user permission before proceeding |
SSE event payload referenceπ
ackπ
data: {
"type": "ack",
"group_id": "a1b2c3",
"id": "evt-001",
"node_id": "resp-node-abc"
}
notification (thinking β tool call)π
data: {
"type": "notification",
"group_id": "g1",
"id": "evt-002",
"code": "TOOL_CALL_NOTIFICATION",
"message": "Searching for relevant data",
"metadata": {
"type": "thinking",
"tool_title": "Searching sales data",
"tool_code": "RUNNING_CODE_EXECUTION",
"tool_name": "code_interpreter"
}
}
notification (thinking - external tool with MCP integration)π
data: {
"type": "notification",
"group_id": "g2",
"id": "evt-003",
"code": "TOOL_CALL_NOTIFICATION",
"message": "Querying Salesforce",
"metadata": {
"type": "thinking",
"tool_title": "Salesforce: Get Opportunities",
"tool_name": "get_opportunities",
"integration_id": "int-sf-123",
"integration_name": "Salesforce"
}
}
notification (approval required)π
Sent when an external MCP tool requires explicit user permission before proceeding. Your application should prompt the user to approve or deny the action before continuing.
data: {
"type": "notification",
"group_id": "g2",
"id": "evt-005",
"code": "approval_required",
"metadata": {
"request_id": "perm-req-789",
"integration_id": "int-sf-123",
"integration_name": "Salesforce",
"tool_name": "get_opportunities",
"annotated_title": "Access Salesforce Opportunities"
}
}
notification (FINAL_RESPONSE_NOTIFICATION)π
data: {
"type": "notification",
"group_id": "g1",
"id": "evt-004",
"code": "FINAL_RESPONSE_NOTIFICATION",
"message": ""
}
textπ
data: {
"type": "text",
"group_id": "g3",
"id": "evt-007",
"content": "Here is the total revenue breakdown by region for Q4 2025:\n\n- **North America:** $4.2M\n- **EMEA:** $2.8M\n- **APAC:** $1.5M"
}
text-chunkπ
Multiple chunks sharing the same id should be appended together to reconstruct the full text item.
data: { "type": "text-chunk", "group_id": "g3", "id": "evt-009", "content": "Based on the analysis, " }
data: { "type": "text-chunk", "group_id": "g3", "id": "evt-009", "content": "revenue grew 12% quarter-over-quarter." }
answerπ
When an answer event is received, the session_id and gen_no fields are returned. You can export the visualization data using the Export Answer Report API to process the results. This allows users to download the answer as a PDF, PNG, CSV, or XLSX file.
data: {
"type": "answer",
"group_id": "g3",
"id": "evt-010",
"title": "Revenue by Region Q4 2025",
"metadata": {
"session_id": "sess-abc-123",
"gen_no": 1,
"transaction_id": "txn-456",
"worksheet_id": "ws-def-789",
"cached": false,
"is_hidden": false
}
}
search_datasetsπ
Emitted as a start/end pair during Auto mode data source discovery.
data: { "type": "search_datasets", "group_id": "g0", "id": "evt-012", "code": "search_datasets_start", "metadata": {} }
data: {
"type": "search_datasets",
"group_id": "g0",
"id": "evt-013",
"code": "search_datasets_end",
"metadata": {
"data_sources": [
{ "worksheet_id": "ws-1", "worksheet_name": "Sales Data", "confidence": "high", "reasoning": "Contains revenue columns" },
{ "worksheet_id": "ws-2", "worksheet_name": "Marketing Data", "confidence": "low", "reasoning": "No revenue columns" }
],
"auto_selected": { "worksheet_id": "ws-1", "worksheet_name": "Sales Data", "confidence": "high", "reasoning": "Best match" }
}
}
fileπ
data: {
"type": "file",
"group_id": "g3",
"id": "evt-014",
"files": [
{ "ts_file_id": "file-abc-001", "display_name": "quarterly_report.csv", "file_type": "csv", "created_at": "2025-11-15T10:30:00Z" },
{ "ts_file_id": "file-abc-002", "display_name": "chart.png", "file_type": "png", "created_at": "2025-11-15T10:30:01Z" }
],
"metadata": { "conv_id": "conv-123" }
}
conv_titleπ
data: {
"type": "conv_title",
"group_id": "g0",
"id": "evt-015",
"title": "Revenue Analysis Q4 2025",
"conv_id": "conv-123"
}
errorπ
data: {
"type": "error",
"group_id": "g3",
"id": "evt-016",
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests",
"display_message": "You've exceeded the rate limit. Please try again in a few minutes."
}
agent-interruptπ
Sent when generation is stopped mid-stream.
data: {
"type": "notification",
"group_id": "g3",
"id": "evt-017",
"code": "agent-interrupt",
"message": "Generation stopped"
}