Un agente de IA con acceso a una base de datos escribe SQL que nadie revisó. La mayoría de las veces acierta. Cuando no, el error es un DELETE sin WHERE, una lectura de la tabla de clientes que no tenía por qué hacer o un SELECT * que trae la tabla entera.
Los guardrails de prompt y de salida (los que filtran lo que el modelo lee o responde) no ven esa sentencia. Un guardrail de base de datos sí: revisa cada sentencia SQL entre el agente y la base, antes de que se ejecute, y decide con reglas, no con otro modelo. Esta guía explica cómo implementarlo paso a paso, con lo que Vericto hace hoy.
Nuestra posición. Construimos Vericto, guardrails de base de datos para agentes de IA. Los pasos sirven con cualquier herramienta; los ejemplos usan la nuestra, y decimos también qué queda fuera.
1. Haz el inventario: qué agente, qué base, qué identidad
Antes de escribir una regla, anota cada agente que toca una base: un asistente text-to-SQL, un agente de soporte, un agente de código con un servidor MCP de base de datos, un job que genera SQL. Para cada uno, qué base usa y con qué credencial.
Dale a cada agente su propia identidad. Vericto reconoce al agente por la API key que hace la llamada (API de runtime, SDK, CLI y MCP) o por el usuario de base de datos de la sesión (proxy TCP). Un agente que comparte credencial con tu aplicación no se puede acotar ni bloquear por separado.
2. Pon el control en el camino del SQL
Un guardrail que el agente puede saltarse es una sugerencia. Elige la vía según dónde corre el agente:
- Proxy TCP (PostgreSQL y MySQL): se pone entre la aplicación y la base, sin cambios de código. Es la única vía que es un control para todo: bloquea, enmascara y aplica la allowlist antes de que la sentencia llegue a la base.
- API de runtime y SDK (Python y Node, los seis dialectos): tu código pregunta antes de ejecutar y ejecuta la query que vuelve aprobada.
- MCP: un agente de código llama a
check_sqlmientras escribe el SQL, antes de que exista un commit. - CLI y GitHub Action: las migraciones y los archivos SQL se revisan en el pull request, con exit code según el veredicto.
Un agente LangChain en Python pasa por el SDK cambiando una línea:
pip install "vericto[langchain]"
export VERICTO_API_KEY=vtro_... # API key with the proxy:evaluate scope
export VERICTO_DATABASE_ID=<database-id> # the database you registered
from langchain_community.agent_toolkits import SQLDatabaseToolkit, create_sql_agent
from vericto.langchain import VerictoSQLDatabase
# Was: db = SQLDatabase.from_uri("postgresql+psycopg://app@db/app")
db = VerictoSQLDatabase.from_uri("postgresql+psycopg://app@db/app")
agent = create_sql_agent(llm, toolkit=SQLDatabaseToolkit(db=db, llm=llm))
Un agente de código se conecta al servidor MCP remoto con una API key de scope ci_dryrun:execute:
claude mcp add --scope user --transport http vericto https://mcp.vericto.com/mcp \
--header 'Authorization: Bearer ${VERICTO_API_KEY}'
3. Empieza en observe
No actives el bloqueo el primer día. Al conectar tu primera base, elige el observe mode: durante 7 días cada BLOCK se degrada a FLAG, nada se detiene y el dashboard muestra cada sentencia que se habría bloqueado, con la regla y el nodo del árbol que la disparó.
Deja que los agentes trabajen. Lo que vas a ver suele caer en tres grupos: errores reales del agente (lo que quieres frenar), flujos legítimos que una regla toca (lo que hay que ajustar antes de aplicar) y lecturas sin límite marcadas con VERICTO-050.
Mientras dura el observe mode tu base no está protegida: todo se reenvía. Úsalo para calibrar, no como estado final.
4. Acota a cada agente
Las reglas estándar frenan lo destructivo. No frenan una lectura bien escrita de una tabla que el agente no debería tocar, que es justo lo que produce una instrucción inyectada. Para eso, en Team y Enterprise:
- Una allowlist por agente: las tablas y columnas que puede usar, en solo lectura o lectura y escritura. Todo lo demás se deniega con
VERICTO-087. Empieza en observe y se simula contra las queries del agente de los últimos 7 días antes de pasar a enforce. - Columnas sensibles: marca emails, teléfonos o tarjetas y decide si la query que las lee se bloquea, se marca o devuelve el valor enmascarado. En el proxy TCP la base devuelve el valor ya enmascarado; en la API, el agente recibe la query aprobada que debe ejecutar.
5. Escribe las reglas de tu negocio
Lo que es peligroso en tu stack no está en ninguna lista estándar. Una regla custom (desde Builder) es una condición YAML sobre el AST. Esta bloquea un DELETE sin WHERE solo en payments:
rule: block-delete-on-payments
node_type: DeleteStmt
condition:
relation: payments
where_clause: null
Una regla nueva empieza en monitor: se evalúa y se registra, y nunca bloquea. Antes de promoverla, el simulador de reglas la reproduce contra el historial de queries de tu workspace (30 días en Builder, 90 en Team) y dice qué flujos legítimos habría bloqueado. Nada se ejecuta contra tu base.
6. Pasa a enforce, capa por capa
Cuando el registro esté limpio, sal del observe mode en Dashboard → Rules: desde ese momento un BLOCK detiene la sentencia. Promueve las reglas custom y las allowlists de a una, empezando por las bases de producción con agentes.
Un bloqueo tiene que servirle al agente. Cada veredicto BLOCKED vuelve con la regla que se disparó y una corrección sugerida, para que el agente reescriba la sentencia en lugar de reintentarla o trabarse:
BLOCKED 1 of 3 statements must not ship as written.
line 4 · VERICTO-001 (critical)
Fix: DELETE FROM users WHERE id = $1
7. Prepara el día malo
Si un agente entra en un bucle de DELETE o empieza a leer fuera de su tarea, primero se lo detiene y después se entiende por qué. Con el kill switch por agente, el owner o un admin bloquea su API key, su usuario de base de datos o todos los agentes del workspace con un motivo obligatorio. En las vías de API el bloqueo es inmediato; en el proxy TCP llega en la siguiente sincronización de reglas (30 segundos si la configuras así).
Escribe quién decide bloquear y desbloquear, y haz un simulacro al menos cada trimestre. El playbook de incidentes trae una plantilla de runbook para completar.
8. Guarda la evidencia
Cada decisión queda en el audit trail, también los bloqueos: lo que un agente intenta después de una negativa es justo lo que quieres revisar. Los reportes exportados van firmados y se pueden verificar sin conexión.
Checklist antes de darle producción a un agente
- Una identidad por agente: su API key o su usuario de base de datos.
- El SQL del agente pasa por un control que no se puede saltar (el proxy TCP en Postgres y MySQL).
- Al menos una semana en observe, con los falsos positivos revisados.
- Una allowlist de tablas y columnas y las columnas sensibles etiquetadas.
- Las reglas de tu negocio simuladas contra el tráfico real antes de aplicarlas.
- Un kill switch probado en un simulacro y un responsable con nombre.
Lo que un guardrail de base de datos no hace
- No reemplaza los roles, permisos y el row-level security de tu base: es defensa en profundidad.
- No ve el prompt ni detecta una inyección: limita lo que la sentencia resultante puede hacer.
- No gobierna el resto de lo que hace el agente (otras herramientas, APIs, gasto): solo su acceso a datos por SQL.
- Fuera del proxy TCP, el enmascaramiento y la query aprobada dependen de que la aplicación ejecute lo que vuelve.
El objetivo no es decirles que no a los agentes. Es poder decirles que sí en datos de producción, sabiendo que cada sentencia pasa por un control que no depende de que el modelo acierte.