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.
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
sqland anexplanation. Nothing is executed at this step. The two-steptranslatethenexecuteflow 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 aREAD ONLYtransaction, 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. Thesqlfield comes back empty when a question cannot be answered read-only, and awarningis 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"
}
| Field | Description |
|---|---|
question | Required. Natural language question, max 1000 characters. |
database_name | Optional. 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
- Call
/ai-query/translatewith a natural language question. - Review the generated SQL and
explanation. - Call
/ai-query/executewith 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
| Field | Default | Description |
|---|---|---|
statement | Required | SQL to execute. Must be read-only (SELECT, SHOW, DESCRIBE, EXPLAIN, WITH). |
database | Engine default | Database to connect to. |
limit | Max allowed | Row cap. Clamped to the platform maximum. |
offset | 0 | Starting row offset. |
timeout_ms | Default | Statement 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:
status | HTTP | Action |
|---|---|---|
pending | 202 | Poll again. |
in_progress | 202 | Poll again. |
completed | 200 | Read result. |
failed | 200 | Read 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 ONLYtransaction, 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
- Vector Search — run similarity searches over pgvector columns.
- Embedding Pipelines — automatically vectorize your table rows.
- Inference Proxy — call AI models through FoundryDB with your own provider keys.