The entry point to the replay flow: check HERE FIRST, before running
`explore_data_catalogue` for any exploration question — a saved row that matches
the question, exactly OR in shape, means the answer is seconds away via
`run_saved_query` instead of a ~1-5 minute planning job.
Returns {"count": N, "saved_queries": [{"id", "user_request", "queries",
"query_placeholder", "metadata", "created_at", "updated_at"}, ...]}, the calling
user's rows only.
MATCH ON `metadata`, NOT ON THE LABEL. `metadata` describes what the row actually
asks. It is authored after the save and is null until the placeholder task has run
(roughly 10 s to 5 minutes, depending on the size of the queries):
`summary` one line with the slots in braces, e.g. "13F positions of
{managers} in {symbol}, {date_prior} vs {date_latest}: shares,
value, weight, QoQ change"
`parameters` [{name, type, description, example}] — the slot schema, one
vocabulary across every query in the row. These names are the
keys of `run_saved_query(values=...)`.
`entities` {slot: resolved example} — what the row was saved for
`datasets` the public dataset names the row reads (the same names
`explore_data_coverage` reports)
`topics` classifier topics for the saved request
`result_schema` [{index, summary, slots, columns}] — per query, what its result
set holds
`stale` true when a query no longer plans (checked nightly)
`run_count`, `last_run_at`
Match the user's question against `summary` + `parameters` + `datasets`, NOT
against `user_request` — that is only the label the user typed while saving. SKIP
any row marked `stale: true`. For a row whose `metadata` has not landed yet, fall
back to the label and replay `queries` exactly.
Having picked a row:
- EXACT repeat (same entities, same window) -> `run_saved_query(query_tokens=
<the row's `queries`>)`; it replays as saved.
- SAME SHAPE, other values (saved "the past 8 quarters of sales for TGT"; asked
"KSS's last 8 quarters of sales") -> `run_saved_query(query_tokens=<the row's
`query_placeholder`>, values={...})`, the values keyed by
`metadata.parameters`; add a `prompt` only for slots you cannot type.
- Pick WHICH of the row's queries to run from `result_schema`: the ones that
answer the question, leaving the `_constituents` companion out — it is a
7,000-35,000 row payload. Pass `max_rows` (e.g. 500) whatever you run.
- TELL THE USER which saved row is being reused (its `summary` and `entities`)
and which values were substituted (the replay's `parameters`).
A row that is merely close in TOPIC but asks a different thing is a DIFFERENT
question; confirm with the user before replaying it.
The other fields:
- `queries` is the list of opaque query tokens for an exact replay.
- `query_placeholder` is the list of placeholder-twin tokens, index-aligned with
`queries`, or null while the placeholder task has not run yet (replay
`queries` exactly or list again shortly). Never show a token of either kind to
the user: it is ciphertext, not content, and says nothing about what the query
does.
- `user_request` is the user's own label — worth quoting when you say which row
you reused, but not what to decide on.
- `id` is what `delete_saved_query` takes.
Duplicate `user_request` values are possible — saving does not upsert.
An HTTP 503 here means the backend's saved-queries table has not been created yet,
NOT that the user has nothing saved — report that difference rather than an empty
list.
Requires auth (your MCP client attaches the OAuth bearer automatically).
Rate-limited 100/min.