Veto vs QueryShield
QueryShield sits between an AI agent and the database as a secure SQL proxy: natural language → SQL via Claude, AST-level validation (SELECT-only, no DDL/DML), per-agent row-level security, and audit logs. Veto does not translate or execute — it returns a deterministic verdict on SQL the agent already produced.
At a glance
| QueryShield | Veto | |
|---|---|---|
| Architecture | Proxy — agent talks to QueryShield, which talks to Postgres | Sidecar gate — agent calls analyze_sql, then runs SQL itself |
| NL → SQL | Yes (Claude) | No — vets SQL/migrations as written |
| Allowed operations | SELECT-only by policy; blocks DDL/DML at AST | All Postgres statements analyzed; destructive ones → block |
| Row-level security | Per-agent RLS enforcement | Not a proxy — use Postgres RLS + Veto verdict layer |
| Touches your DB | Yes — executes validated queries | Never — EXPLAIN on scratch Postgres only |
| LLM in core | Yes — for NL translation | No — deterministic rules only |
When QueryShield fits
You want agents to ask questions in natural language and receive read-only answers, with the proxy enforcing SELECT-only access and tenant isolation. Execution and auditing happen inside the proxy.
When Veto fits
Your agent already writes SQL or migrations (including writes you intend to allow), and you need a deterministic pre-flight check — "is this DELETE safe?" — without routing all traffic through a proxy. Veto is category guardrail, not database access layer.
Different categories
QueryShield and Veto are not direct substitutes. QueryShield controls how agents access data. Veto judges whether a specific statement should run. A read-only proxy won't help when the agent legitimately needs to run migrations — Veto will still flag an unguarded TRUNCATE.