Skip to main content

AI Query and Data Explorer

Two tools for safe, read-only access to your managed databases: AI Query translates natural language into SQL, and the Data Explorer lets you run arbitrary read-only queries and inspect schemas through the FoundryDB controller. Neither can mutate your data.

Both work with PostgreSQL and MySQL services in Running status.

AI Query (NL2SQL)

AI Query converts a plain-language question into a read-only SQL query. The translation is powered by Claude (Anthropic). You can translate, review, and optionally execute the result in two separate calls, or execute directly in a single step.

Requires the AI Query feature to be configured (an Anthropic API key in your deployment). Returns 501 if this is not set up.

NL2SQL: review before execute, read-only
SAFETY GATE review before execute · read-only
Userasks NL→ schema+question → LLM →Human reviewconfirm ✓→ execute READ-ONLY →Databaserows back
User questionDB schema (context)LLM (Claude)Human review gateRead-only executeResultsschema introspect (dashed)

How it works, safely

AI Query is built around a deliberate split between generating SQL and running it, so a model never reaches your data on its own:

  • Schema as context. When you call /ai-query/translate, the controller sends the structure of the target database (its tables, columns, and types) together with your question to the model. The model writes SQL against your actual schema rather than guessing at table or column names. The same schema can be inspected directly through the Data Explorer's schema introspection endpoint.
  • Review before execute. Translation only returns the candidate sql and an explanation. Nothing is executed at this step. The two-step translate then execute flow is the safe path: you (or a human in your dashboard, chatbot, or support tool) read the SQL and confirm it before running it. The single-step execute path is a convenience for trusted, scripted callers.
  • Read-only guard. Execution is constrained on two independent layers, so a statement that slips past one is still stopped by the other. The controller checks the statement against an allowlist of read-only statement types (SELECT, SHOW, DESCRIBE, EXPLAIN, WITH) before dispatching it, and the agent then runs it inside a READ ONLY transaction, which the database engine itself enforces. A statement timeout caps how long a query can hold a connection, results are capped at 1000 rows, and every query is recorded in the audit log. The sql field comes back empty when a question cannot be answered read-only, and a warning is set when the model produced a blocked statement.

See the Security Model section for the full layering.

Endpoints

POST /managed-services/{serviceId}/ai-query/translate
POST /managed-services/{serviceId}/ai-query/execute

Translate a Question to SQL

curl -u $USER:$PASS \
-X POST https://api.foundrydb.com/managed-services/$SERVICE_ID/ai-query/translate \
-H "Content-Type: application/json" \
-d '{
"question": "Show the top 10 largest tables by size",
"database_name": "defaultdb"
}'

Response:

{
"sql": "SELECT tablename, pg_total_relation_size(quote_ident(tablename)) AS size FROM pg_tables WHERE schemaname = 'public' ORDER BY size DESC LIMIT 10",
"explanation": "Lists the 10 largest tables in the public schema by total size including indexes.",
"database_type": "postgresql"
}
FieldDescription
questionRequired. Natural language question, max 1000 characters.
database_nameOptional. Target database. Defaults to the service default.

The sql field is empty when the question cannot be answered with a read-only query. A warning field is set when the model generated a blocked statement.

Execute a Query

curl -u $USER:$PASS \
-X POST https://api.foundrydb.com/managed-services/$SERVICE_ID/ai-query/execute \
-H "Content-Type: application/json" \
-d '{
"sql": "SELECT tablename, pg_total_relation_size(quote_ident(tablename)) AS size FROM pg_tables WHERE schemaname = '\''public'\'' ORDER BY size DESC LIMIT 10",
"database_name": "defaultdb"
}'

Response:

{
"columns": ["tablename", "size"],
"rows": [
["orders", 1234567890],
["products", 98765432]
],
"row_count": 2,
"execution_ms": 18,
"truncated": false
}

The execute endpoint accepts any read-only SQL, not only queries produced by translate. Only SELECT, SHOW, DESCRIBE, EXPLAIN, and WITH statements are permitted. The connection runs inside a READ ONLY transaction with a 30-second statement timeout. Results are capped at 1000 rows; truncated is true when the cap is hit.

Typical Workflow

  1. Call /ai-query/translate with a natural language question.
  2. Review the generated SQL and explanation.
  3. Call /ai-query/execute with the SQL once you are satisfied it is correct.

This two-step approach lets you inspect the query before it runs, which is useful in dashboards, chatbots, and support tools where you want a human review step.

Data Explorer

The Data Explorer provides brokered read-only query execution and schema introspection through the controller. It is designed for internal tools, dashboards, and scripts that need database access without direct database credentials.

Tasks are asynchronous. You POST to submit a task and GET to poll for the result.

Endpoints

POST /managed-services/{id}/data-explorer/query
GET /managed-services/{id}/data-explorer/query?task_id={task_id}
POST /managed-services/{id}/data-explorer/schema
GET /managed-services/{id}/data-explorer/schema?task_id={task_id}

Run a Query

Submit:

curl -u $USER:$PASS \
-X POST https://api.foundrydb.com/managed-services/$SERVICE_ID/data-explorer/query \
-H "Content-Type: application/json" \
-d '{
"statement": "SELECT id, name, created_at FROM products ORDER BY created_at DESC",
"database": "defaultdb",
"limit": 100,
"offset": 0,
"timeout_ms": 5000
}'

Response (202 Accepted):

{ "task_id": "a1b2c3d4-..." }

Poll:

curl -u $USER:$PASS \
"https://api.foundrydb.com/managed-services/$SERVICE_ID/data-explorer/query?task_id=a1b2c3d4-..."

While the task is running, the poll response has status: "pending" or status: "in_progress" with HTTP 202. Once complete, it returns HTTP 200:

{
"task_id": "a1b2c3d4-...",
"status": "completed",
"result": {
"columns": [
{ "name": "id", "type": "int8" },
{ "name": "name", "type": "text" },
{ "name": "created_at", "type": "timestamptz" }
],
"rows": [
[1001, "Widget Pro", "2026-06-20T08:32:00Z"]
],
"row_count": 1,
"truncated": false
}
}

Request Body Fields

FieldDefaultDescription
statementRequiredSQL to execute. Must be read-only (SELECT, SHOW, DESCRIBE, EXPLAIN, WITH).
databaseEngine defaultDatabase to connect to.
limitMax allowedRow cap. Clamped to the platform maximum.
offset0Starting row offset.
timeout_msDefaultStatement timeout in milliseconds. Clamped to the platform maximum.

Introspect a Schema

Submit:

curl -u $USER:$PASS \
-X POST https://api.foundrydb.com/managed-services/$SERVICE_ID/data-explorer/schema \
-H "Content-Type: application/json" \
-d '{ "database": "defaultdb" }'

The request body is optional. If omitted, the service's default database is introspected.

Poll:

curl -u $USER:$PASS \
"https://api.foundrydb.com/managed-services/$SERVICE_ID/data-explorer/schema?task_id=a1b2c3d4-..."

Response when complete:

{
"task_id": "a1b2c3d4-...",
"status": "completed",
"result": {
"tables": [
{
"name": "products",
"schema": "public",
"columns": [
{ "name": "id", "type": "int8", "nullable": false },
{ "name": "name", "type": "text", "nullable": false },
{ "name": "created_at", "type": "timestamptz", "nullable": true }
]
}
]
}
}

Polling Pattern

The response status field and HTTP status code together tell you whether to keep polling:

statusHTTPAction
pending202Poll again.
in_progress202Poll again.
completed200Read result.
failed200Read error_message.

Poll every 500ms to 1 second for typical queries. Tasks complete quickly for simple queries.

Security Model

Both AI Query and the Data Explorer enforce read-only access at multiple layers:

  • The controller checks the statement against an allowlist of read-only statement types before dispatching the task.
  • The agent runs the query inside a READ ONLY transaction, so any statement that slips through the allowlist check is rejected by the database engine.
  • A statement timeout prevents long-running queries from holding connections.
  • All queries are recorded in the platform audit log with the submitting user, service ID, database, and statement text.

What's Next