OriginChain docs
examples · ask · 1 / 6

1. Simple count question

← Ask examples
what this does

The smallest possible Ask call. We send a plain-English question in the "nl" field and the engine compiles it into a Plan tree, runs it, and returns rows. No schema hint, no flags - just the question.

when to use it
  • You're prototyping and don't yet know which schemas a question will touch.
  • The question is unambiguous against your registered schemas - one table is an obvious fit.
  • You want a quick sanity check that the Ask endpoint is wired up before you layer on schemas hints or show_plan.

For production hot paths, pass a schemas list (next example) so the compiler doesn't have to consider every schema in the tenant.

the schema

Register this once with POST /v1/tenants/:t/schemas (Content-Type: text/plain).

namespace   = "shop"
table       = "customers"
primary_key = ["id"]

[[columns]]
name = "id"
ty   = "str"
required = true

[[columns]]
name = "email"
ty   = "str"

[[columns]]
name = "region"
ty   = "str"
seed data

Load three customers so the count returns a real number.

# One-time seed of three customers - skip if you've already loaded data.
curl -X POST "https://$OC_HOST/v1/tenants/$OC_TENANT/rows/shop.customers/_batch" \
  -H "Authorization: Bearer $OC_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    { "id": "c_1", "email": "alice@example.com", "region": "IN" },
    { "id": "c_2", "email": "bob@example.com",   "region": "US" },
    { "id": "c_3", "email": "carol@example.com", "region": "DE" }
  ]'
the request
POST /v1/tenants/:t/ask
curl -X POST "https://$OC_HOST/v1/tenants/$OC_TENANT/ask" \
  -H "Authorization: Bearer $OC_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "nl": "how many customers do I have?"
  }'
what you get back
{
  "rows": [
    { "count": 3 }
  ],
  "cache": "miss"
}

Every Ask response has the same shape: rows (an array of objects keyed by column), cache ("hit", "miss", or "skip"), and an optional plan field when you asked for it.

how it works
  • The Ask endpoint canonicalises the question (lowercase, collapse whitespace) and looks it up in the plan cache keyed by question + schemas list.
  • First call is a miss. The compiler walks the registered schemas, recognises "how many" as a COUNT, and produces a Plan tree like Aggregate(count) → Scan(shop.customers).
  • The executor runs the plan and the count rolls up to one row.
  • The plan is stored under that cache key for next time - the actual rows are not cached, only the plan.
common mistakes
  • Sending "question" instead of "nl". The engine reads the body field nl. Anything else returns 400 missing_field.
  • Expecting the rows array to be cached. Cache hits replay the compiled plan, not the result set. If the underlying rows changed since the previous call, you'll see the new count on a "hit".
  • Ambiguous questions on a busy tenant. "How many customers" works if customers is the only obvious table. Once you have a crm.customers and a shop.customers, narrow with a schemas hint (next example).