Skip to content
Raw Markdown

ask_question

Ask a natural-language question about a project's data, or continue a chat. Cassis grounds the question against the published ontology, plans the answer, and generates the SQL.

When the plan has a genuine fork, an assumption you could resolve differently, the tool surfaces the plan first and waits for explicit confirmation before executing.

Each chat is pinned to the published ontology version current when it started. Follow-ups in the same chat keep that version even if a newer one is published meanwhile. Omit chat_id to start a new chat on the latest published version.

What comes back depends on the data source. Connected to an executable warehouse, Cassis runs the SQL and returns the answer, the SQL, and results. On a schema-only source, it generates SQL in that dialect but never runs it, so results is always null.

Parameters

Passed by the client, not typed by the user.

NameTypeNotes
project_idUUID, requiredThe Cassis project to query
questionstringNatural-language question. For follow-ups it can reference earlier messages (“now group by circuit”). Ignored when execute_pending_plan=true. Defaults to an empty string
chat_idstringPassed by the client on follow-ups, plan refinement, or plan execution. Omitted to start a new chat
execute_pending_planbooleanSet true to execute the plan surfaced on the previous turn (when status="needs_execution"). Requires chat_id and the user’s explicit approval. Defaults to false

Response

FieldNotes
chat_idAlways set. The client stores it to continue the chat
status"answered", "needs_execution", "not_answerable", or "error"
answerThe assistant’s text response. Present on every status. On needs_execution it carries the plan’s intent when the assistant added no prose of its own
sqlThe generated SQL. Populated when status="answered"
resultsColumnar: {columns, rows, total_rows, truncated}, rows as positional lists. Null when the SQL was not executed, and always null on a schema-only source. Zero rows means the query ran and matched nothing
objects_usedQualified names of the ontology objects the answer used
planThe plan awaiting execution, when status="needs_execution". Its assumptions[] carry text and, for a fork, options and selected
ontology_versionThe published version this answer was grounded on. Pinned when the chat starts
errorPopulated when status="error" or status="not_answerable"

not_answerable is terminal for that question. It means the approved plan cannot run against the current ontology or data: an undefined concept, structural drift, or missing data. The reason is in answer and error. Retrying the same question will not help; refine the question or fix the ontology.

Example: a straight answer

The user types “Who won the most races in 2023?” and Cassis returns:

chat_id: "chat_01JZ8K4M2R"
status: "answered"
answer: "Max Verstappen won 19 out of 22 races in 2023,
         far ahead of Pérez (2) and Sainz (1)."
sql: |
  SELECT d.full_name, COUNT(*) AS wins FROM public.results r
    JOIN public.races ra ON r.race_id = ra.race_id
    JOIN public.drivers d ON r.driver_id = d.driver_id
    WHERE ra.year = 2023 AND r.position = 1
    GROUP BY d.full_name ORDER BY wins DESC
results:
  columns: ["full_name", "wins"]
  rows: [["Max Verstappen", 19], ["Sergio Pérez", 2], ["Carlos Sainz", 1]]
  total_rows: 3
  truncated: false
objects_used: [public.results, public.races, public.drivers]
ontology_version: 3

Example: plan, then execution

“Compare total points scored by all drivers in 2022 vs 2023, including sprint results.” has a fork, so the first call returns a plan rather than an answer:

chat_id: "chat_01JZ8K6T7Q"
status: "needs_execution"
plan:
  intent: "UNION query combining public.results and
           public.sprint_results, grouped by season."
  assumptions:
    - text: "Sprint points included in the total"
    - text: "Points rolled up across all drivers per season"
  objects: [public.races, public.results, public.sprint_results]

Surface the assumptions to the user. If they want a different option, send a revised question naming it rather than executing the default. On approval, the client re-calls the tool with the same chat_id and execute_pending_plan=true, and Cassis executes:

chat_id: "chat_01JZ8K6T7Q"
status: "answered"
answer: "In 2023 drivers scored 2,458 points combined, up from
         2,350 in 2022. Sprint points are included in both totals."

Example: a follow-up

The client keeps the chat_id from the previous turn, so “Now break it down by constructor for 2023” needs no restated scope and answers against the same pinned ontology version.

Limits (question timeout, row caps) are in Limits and errors.