Skip to main content

Description

Execute a read-only SQL query against the database and return results as a JSON array of objects. A server-side row limit and query timeout are enforced. Optionally, request the execution plan instead of results using the explain parameter. Always use specific column names instead of SELECT *. Use JOINs based on foreign keys discovered via describe_table. Check column cardinality from describe_table to write efficient WHERE and GROUP BY clauses.

Parameters

Response schema

Returns an array of row objects. Each object maps column names to values:
The exact fields depend on the columns in your query.

Example

Request:
Response:

Execution plans

Use the explain and analyze parameters to inspect query performance without writing a separate tool call. EXPLAIN only (no execution):
EXPLAIN ANALYZE (includes actual execution stats):

Safety

  • Read-only — all queries run inside a read-only transaction. INSERT, UPDATE, DELETE, DROP, and all other write operations are rejected.
  • AST validation — SQL is parsed using PostgreSQL’s actual parser (pg_query). Only SELECT statements pass validation. See SQL Validation.
  • Row limit — results are capped at MAX_ROWS (default: 100). Add your own LIMIT clause for smaller result sets.
  • Timeout — queries are cancelled after QUERY_TIMEOUT (default: 10s).
  • Single statement — multi-statement queries (separated by ;) are rejected.

Column masking

If a policy file defines column masks, masked columns are automatically transformed before results are returned. For example, with email masked as redact:
Masking is applied after query execution and is not bypassable — the AI never sees unmasked values. See Column Masking for all mask types and configuration.

Notes

  • If --explain-only mode is enabled, query calls automatically return the EXPLAIN plan instead of executing the query.
  • When using explain: true, provide the SELECT query only — Isthmus prepends EXPLAIN or EXPLAIN ANALYZE automatically. Do not include the EXPLAIN keyword in the sql parameter.
  • With explain: true and analyze: false (default), only the planner’s estimates are shown. The query is not executed.
  • With explain: true and analyze: true, the query is executed inside a read-only transaction, and actual row counts, timing, and buffer usage are included.
  • Column values are JSON-serialized: timestamps become ISO 8601 strings, UUIDs become strings, numeric types preserve precision.
  • Masked columns may change type (e.g. an integer column with mask: "redact" returns the string "***").
  • For large tables, always use LIMIT and filter with WHERE to avoid hitting the row cap or timeout.