A YAML file declares every table, column, join and function an agent may use. Queries outside the model are rejected before they reach the warehouse.
Policy: read-only · no SELECT * · PII blocked
| Table | Column | Type | Notes |
|---|---|---|---|
| customers | id | integer | PK |
| text | PII ✗ | ||
| full_name | text | PII ✗ | |
| country | text | ISO-3166 | |
| created_at | timestamp | ||
| orders | id | integer | |
| customer_id | integer | FK→customers | |
| status | text | placed|shipped|cancelled | |
| total_cents | integer | tax incl. | |
| placed_at | timestamp | ||
| order_items | id | integer | |
| order_id | integer | FK→orders | |
| product_id | integer | FK→products | |
| quantity | integer | ||
| unit_price_cents | integer | ||
| products | id | integer | PK |
| sku | text | ||
| name | text | ||
| category | text |
Allowed joins: orders.customer_id = customers.id · order_items.order_id = orders.id · order_items.product_id = products.id
The demo above is a simplified JS validator. The real tool uses sqlglot — catches undeclared columns through CTEs, OR-injected join conditions, dialect-specific functions, and more.
Wire check in front of your agent's SQL tool. Exit 0 = query runs. Exit 1 = violation list returned to the agent so it can rewrite.
What the CLI catches that this demo doesn't:
"Orders" ≠ orders