Skip to content

Ask endpoints

An ask endpoint accepts a natural-language question, generates a SELECT against the database’s schema, runs it, and returns both the answer and the SQL. Unlike the in-product agent, this is a public endpoint your end users can call.

{
"slug": "ask",
"name": "Ask the data",
"kind": "ask",
"method": "POST",
"sql": "",
"input": [
{ "name": "question", "type": "text", "required": true, "maxLength": 500 }
],
"output": "answer",
"auth": "public",
"askConfig": {
"allowedTables": ["orders", "customers"],
"context": "Currency is USD. Customers without orders are inactive.",
"maxRows": 50
},
"rateLimit": { "perMin": 5, "perDay": 200 },
"captcha": true
}

The sql field is ignored — the runtime fills it from the model’s output. Input must include exactly one question field of type text.

  1. Builds a schema snapshot for askConfig.allowedTables (or every table when the array is empty).
  2. Composes a prompt: schema + optional askConfig.context + the user’s question + a strict “SELECT only, single statement” system message.
  3. Sends to Workers AI; rejects any output that fails assertReadOnly.
  4. Wraps the generated SQL: SELECT * FROM (<generated>) LIMIT <maxRows>.
  5. Executes against the DO, returns columns / rows / SQL / explanation.
{
"ok": true,
"data": {
"sql": "SELECT COUNT(*) AS n FROM orders WHERE created_at > date('now','-7 day')",
"explanation": "Counted orders with created_at within the last 7 days.",
"columns": ["n"],
"rows": [[42]]
}
}

askConfig.allowedTables is the only safety net between an arbitrary user question and your full schema. Producers should:

  • Allow-list narrowly. Only the tables you’d be comfortable showing in a public report.
  • Lean on captcha + rate limits. ask calls cost both Workers AI inference and DB reads.
  • Pair with auth: "session" if you want each user to only see their own rows. $user_id is bound automatically; instruct the model in askConfig.context to filter by it.