Skip to main content

Setup for database administrators (DBAs)

Surface: SDK or Gateway Modes supported: Hosted Hybrid Local Tiers: Free Solo Teams

Who this is for

You own the databases. When an AI agent gets a database tool, your job is to make sure it can read what it needs and nothing more -- no silent UPDATE, no DROP, no permission changes.

What you typically want governed

  • Reads, yes. SELECT, EXPLAIN, SHOW, DESCRIBE, CTEs.
  • Writes, no (or only with approval). INSERT / UPDATE / DELETE / MERGE.
  • Schema and grants, never. DROP, ALTER, GRANT, TRUNCATE.

Control Zero classifies a query into a canonical semantic class -- database:read, database:write, or database:admin -- regardless of SQL dialect, so one rule covers every spelling. A multi-statement piggyback like SELECT 1; DROP TABLE x resolves to database:admin, so a deny-admin rule still catches it.

Which surface to install

If the agent is code you control, use the SDK and call guard() before each query. If the agent talks to a database through an API you cannot edit, put the Gateway in front of it.

pip install controlzero

Starter policy

Read-only database access. Reads pass; everything else is denied. Drop this in controlzero.yaml:

version: '1'
settings:
default_action: deny
default_on_missing: deny
default_on_tamper: quarantine
rules:
- id: allow-db-read
allow: 'database:read'
reason: 'SELECT / EXPLAIN / SHOW / DESCRIBE / CTE are permitted via the canonical read class.'
- id: deny-db-write
deny: 'database:write'
reason: 'No data modification: INSERT / UPDATE / DELETE / MERGE blocked.'
- id: deny-db-admin
deny: 'database:admin'
reason: 'No schema or permission changes: DROP / ALTER / GRANT / TRUNCATE blocked.'

The SDK derives the class from the SQL you pass, so you write the rule once:

from controlzero import Client

cz = Client(policy_file="./controlzero.yaml")

read = cz.guard("database", method="SELECT", args={"sql": "SELECT id FROM orders"})
print(read.decision) # "allow"

drop = cz.guard("database", method="DROP", args={"sql": "DROP TABLE orders"})
print(drop.decision) # "deny"

cz.close()

If you would rather allow writes only after a human signs off, see First approval flow. Approvals are Beta and available on every deployment, including the hosted (SaaS) plan (off by default).

What you'll see

  • Each query's decision in the Audit Log, classified as database:read / write / admin, with the matched rule and reason.
  • A denied write or drop shows decision: deny and the rule that stopped it, so you have a record of exactly what the agent attempted.

Next steps