Visit Later
N/a
Related
- Chart & Table Response Spec — comprehensive guide for frontend rendering (chartConfig shapes per chart type, rows format, detection logic)
General Notes
- Used for two scenarios: continuing an active conversation (clarification follow-up) or reopening a completed conversation (widget editing)
- If conversation status is "completed", it gets reopened to "active" status
- AI may respond with another clarification or generate/update the widget
- On widget update (edit flow), the existing widget document is updated with new SQL/config
- When the first AI call on a new conversation produces SQL that returns 0 rows, the handler transparently retries the AI once with adaptive thinking enabled, prompting it to re-examine filters/joins. Skipped on edits (where an empty result may be intentional filter tightening). The retry is flagged via
aiMetadata.emptyResultRetryon the persisted assistant message. - Each retry-path AI call (SQL error, empty result, chart row-limit, missing stackField, missing yAxisLabel) uses per-model retry params from
modelCapabilities.js— adaptive thinking +xhigheffort on Opus 4.7, scaled down on other models. First-turn calls run without thinking for minimum latency. - The system prompt is sent with
cache_control: ephemeralso the ~27K-token prefix is served from cache on retries, edits, and multi-turn conversations (cache read/write tokens accumulated onconversation.totalCacheReadInputTokens/totalCacheCreationInputTokens).
Flow
Test cases
Method & URL
POST v1/conversations/:conversationId/messages
Request
Headers
authorization
- Required
- Type : <string>
- Bearer session token
Query
Body
message
- Required
- Type : <string>
- The user's follow-up message or edit instruction
Path parameter
conversationId
- Required
- Type : <string>
- The ID of the conversation
Response
2xx
success
- Type : true (boolean)
- This indicates that request was executed successfully
message
- Type : <string> | null
- Generic message
data
- Type : <object>
data.type
- Type : "clarification" | "chart" | "table" (string)
data.conversationId
- Type : <string>
- ID of the conversation
data.message
- Type : <string> | null
- Present when data.type is "clarification"
- The AI's clarification question
data.widget
- Type : <object> | null
- Present when data.type is "chart" or "table"
- The created or updated widget document
data.widget.id
- Type : <string>
data.widget.title
- Type : <string>
data.widget.type
- Type : <string>
- Enum : chart | table
data.widget.chartType
- Type : <string> | null
- Enum : line | bar | pie | donut | stackedBar | scatterPlot
- null when type is "table"
- scatterPlot supports up to 50 data points (all other chart types are limited to 10)
data.widget.chartConfig
- Type : <object> | null
- Frontend rendering config (axes, colors, etc.)
- null when type is "table"
- stackedBar requires a stackField property in chartConfig (the field used to split bar segments)
data.widget.columns
- Type : <object>[] | null
- Array of column definitions for table rendering
- Populated when type is "table", null when type is "chart"
data.widget.columns[].field
- Type : <string>
- Key used to read the value from each row object — must exactly match the SQL column alias
data.widget.columns[].label
- Type : <string>
- String displayed as the column header in the UI
data.widget.position
- Type : <number>
data.widget.latestExplanation
- Type : <string> | null
- Plain-language explanation of the chart, up to 5000 chars
- Populated for type "chart" only, always null for type "table"
data.widget.latestExplanationGeneratedAt
- Type : <string (ISO timestamp)> | null
- When the explanation was generated
- Populated for type "chart" only, always null for type "table"
data.rows
- Type : <object>[] | null
- Present when data.type is "chart" or "table"
- Query result rows
data.totalCount
- Type : <number> | null
- Present when data.type is "table"
- Total matching rows (for pagination)
404
success
- Type : false (boolean)
message
- Type : <string>
- Conversation not found