Query a table exactly
query_tableRun an EXACT, deterministic query over ONE tabular file (a CSV, or the first table of a spreadsheet/PDF/Word document). Use this instead of ask_docs whenever the question needs COUNTING, SUMMING, AVERAGING, MIN/MAX, FILTERING, or exact row lookups over structured data ('how many rows...', 'total amount by region', 'list orders where status is failed') - semantic search undercounts tables, while this executes over EVERY row and returns exact numbers. Use ask_docs for prose/meaning questions and get_file to read a whole document. The query argument is a JSON object: { select?: [column names to return as raw rows], where?: [{col, op, value}, ...] filters combined with AND - ops eq | neq | contains compare text case-insensitively, gt | gte | lt | lte compare numerically (rows whose cell is not a number are skipped and counted in skippedNonNumeric), groupBy?: 'column' gives one result row per distinct value, aggregates?: [{fn, col}] with fn count | sum | avg | min | max ('col' required except for count), limit?: max raw rows (default 50, max 200) }. Column names match the file's header row case-insensitively. Examples: {"where":[{"col":"status","op":"eq","value":"failed"}],"aggregates":[{"fn":"count"}]} counts failed rows; {"groupBy":"region","aggregates":[{"fn":"sum","col":"amount"}]} totals amount per region; {"select":["name","email"],"where":[{"col":"country","op":"eq","value":"FR"}]} returns the matching rows. If you name a column that does not exist, the error lists the file's real columns - retry with one of those. Read-only; nothing is written, so it is safe to call.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | The constrained query object (grammar in the tool description): select?, where?, groupBy?, aggregates?, limit?. | |
| fileId | Yes | The id of the file to query (from list_files / search_files - the same id get_file takes). | |
| handle | No | Optional: name one of the user's OWN profiles by its public @handle (with or without the leading @), as listed by list_profiles - an alternative to projectId, and it takes precedence if both are given. Honored only for an account-wide connection; a single-project connection is already scoped and ignores it. A handle that is not one of the user's own profiles is refused outright, never quietly swapped for another profile. To read context someone ELSE shared with the user or published, use shared_context instead. | |
| projectId | No | Optional: which of the user's projects holds the file. Honored only for an account-wide connection; a single-project connection is already scoped and ignores this. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| rows | No | Raw matching rows (select mode). Either rows or groups is present, never both. | |
| groups | No | Aggregate rows (aggregate / groupBy mode). | |
| columns | Yes | ||
| truncated | Yes | True when rows/groups were clipped by a cap. | |
| tableSource | Yes | Whether the rows came from a native CSV parse, an extracted document table, or a table read out of an image (image numbers may be misread - treat them as approximate). | |
| rowCountTotal | Yes | Total data rows in the table. | |
| rowCountMatched | Yes | Rows that passed the where filter. | |
| skippedNonNumeric | No | Cells skipped as non-numeric during a numeric comparison or aggregate (present only when > 0). |