Query a connected database
Ask a business question and get an answer backed by governed, read-only SQL.
This recipe shows how to ask a business question and get an answer backed by governed, read-only SQL — without the agent or user writing any SQL themselves.
The question
"How many orders shipped last month?" — asked against a connected PostgreSQL database.
Prerequisites
The project must have a database source connected and synced. Check with discover: the database source should show status: "indexed".
Step 1: Search the database source
curl -X POST "$ECHO_URL/projects/$PROJECT_ID/knowledge/search" \
-H "X-API-Key: $SERVICE_KEY" \
-H "Content-Type: application/json" \
-d '{ "query": "orders shipped last month", "sources": ["database"], "top_k": 5 }'The hits identify the relevant tables and columns — public.orders, the shipped_at column, the status column.
Step 2: Understand the schema
Fetch the table's ref to see its full schema, column types, and relations:
curl -X POST "$ECHO_URL/projects/$PROJECT_ID/knowledge/fetch" \
-H "X-API-Key: $SERVICE_KEY" \
-H "Content-Type: application/json" \
-d '{ "ref": "database:postgresql:analytics:public.orders" }'The response includes column definitions, detected relationships (foreign keys, inferred joins), and sensitivity classifications.
The governance model
When an agent queries a connected database, every query runs under strict governance:
- Read-only role — verified at connection time. The credentials cannot write.
- Query validation — the SQL is checked before execution.
- Enforced limits and timeouts — no unbounded scans.
- Cost gate — expensive queries are blocked.
- Per-user audit trail — every query is logged with who ran it.
- Results flow to the agent, never to Echo's storage — raw rows are never persisted.
What Echo stores about a database
Echo stores knowledge *about* the database — schema, catalog, column types, sensitivity classifications, statistics — but never the data itself. Sensitive columns are classified before anything is persisted. Tagged columns keep statistics only: their values are masked, never stored, never sent to a model.
Next: Configuration.

