Guardarrailes en agentes IA: qué son y cómo implementarlos
Los guardarrailes evitan que un agente IA borre datos, filtre información o entre en bucles. Aprende qué son y cómo implementarlos con código desde cero.
Colaboradores: Esther Aznar
Imagina que le pides a un asistente de IA: “elimina los archivos temporales del proyecto”. El asistente cree que sabe cuáles son, pero se equivoca… y borra un archivo importante (.env.local) con datos de configuración que necesitas. Los datos se pierden.
¿Por qué pasó? Porque el asistente hizo exactamente lo que entendió de tu orden, sin pensar si era seguro hacerlo.
Los guardarrailes son límites de seguridad que evitan que esto ocurra. Son como cercar una zona peligrosa: el asistente sigue trabajando, pero no puede entrar en áreas donde puede causar daño.
Antes de empezar
¿Qué es un agente de IA? Es un programa que usa inteligencia artificial (como ChatGPT) para:
- Recibir tu orden
- Decidir qué hacer
- Ejecutar acciones (eliminar un archivo, enviar un email, etc.)
Los ejemplos de código están en TypeScript, pero puedes seguirlos incluso si no sabes programar mucho - los explicaré en términos simples.
Qué es un guardarraíl
Piensa en un parque infantil cercado. La cerca no elige dónde van los niños ni cómo juegan. Solo impide que salgan corriendo hacia la carretera.
Un guardarraíl de IA es básicamente un límite que tú defines de antemano. El asistente sigue siendo inteligente y toma decisiones, pero hay ciertas acciones que no puede hacer, sin importar lo que le pidas.
Ejemplos:
-
“No puedes eliminar archivos de configuración”
-
“No puedes acceder a la base de datos de clientes”
-
“No puedes enviar dinero desde la cuenta”
Hay tres puntos donde puedes poner guardarrailes:
1. Antes (entrada): Revisas lo que el usuario pide antes de pasárselo al asistente.
- Ejemplo: Si alguien escribe “borra todo”, el sistema lo bloquea antes de que el asistente lo intente.
2. Durante (ejecución): Límites en las acciones que el asistente puede ejecutar.
- Ejemplo: El asistente puede leer archivos, pero cuando intenta borrar uno, el sistema verifica: “¿está este archivo en la carpeta permitida? ¿No es un archivo protegido?”
3. Después (salida): Revisas lo que el asistente te devuelve antes de usarlo.
- Ejemplo: Si el asistente genera un comando para ejecutar, verificas que el comando sea seguro antes de ejecutarlo.
Por qué los agentes sin guardarrailes fallan
El problema no es que la IA sea mala. El problema es que hace exactamente lo que entiende de tus órdenes, sin cuestionarse si es seguro.
Ejemplo: Le dices “haz que la aplicación vaya más rápida” y el asistente elimina la base de datos porque cree que es lenta. Técnicamente obedeció tu orden. Pero el resultado es desastroso.
Tres problemas comunes:
1. Acciones irreversibles sin confirmar: El asistente ejecuta órdenes peligrosas de inmediato (borrar un archivo, cambiar configuración) sin pedir confirmación. Es como un trabajador que ejecuta cada orden sin preguntar si está seguro.
2. Compartir información que no debería compartir: El asistente tiene acceso a información sensible (contraseñas, datos de clientes) y la comparte en su respuesta, aunque no debería. No es malicia - simplemente usa toda la información que tiene para responder.
3. Bucles infinitos: El asistente detecta un error, intenta arreglarlo, eso genera otro error, lo intenta de nuevo… y entra en un ciclo infinito que no se detiene solo.
La razón de fondo: Sin guardarrailes, el asistente no sabe qué está permitido y qué no en tu situación específica.
Cómo implementarlos en la práctica
Hay cuatro niveles de protección, de más simple a más fuerte. Empieza por los primeros - no necesitas todos desde el principio.
Nivel 1: El manual de reglas 📋
¿Qué es? Es la instrucción inicial que le das al agente. Como un manual que dice “esto sí, esto no”. Se coloca al principio del system prompt y establece las expectativas desde el inicio.
Ejemplo en la vida real: Es como decirle a un trabajador: “puedes leer los documentos, pero nunca toques la caja fuerte”. Es la regla de oro que guía todas sus decisiones.
const sistemaPregunta = `
Eres un asistente de código.
✅ PUEDO:
- Leer archivos
- Sugerir mejoras
- Explicar errores
❌ NUNCA PUEDO:
- Borrar archivos
- Ver archivos .env
- Tocar la base de datos
`;
El agente usa estas instrucciones para interpretar cada solicitud que recibe. Si alguien dice “borra todo”, el agente debería rechazarlo porque sabe que no puede borrar archivos.
Pro: Es rápido de implementar. Con esto bloqueas casi todos los accidentes comunes. Es el criterio con el que el agente lee cada situación.
Contra: Un usuario persistente podría intentar que ignores estas reglas. El agente está entrenado para ser obediente, y con las palabras correctas podría intentar cumplir órdenes que contradicen el manual. Por eso existen los otros niveles.
Nivel 2: El filtro de seguridad 🛡️
¿Qué es? Antes de que el agente reciba el mensaje del usuario, tu código verifica: “¿esto parece seguro?” Este filtro se ejecuta entre el usuario y el agente, analizando patrones de texto peligrosos.
Ejemplo en la vida real: Es como tener un guardia en la puerta que revisa si alguien intenta entrar con un arma. Si alguien dice una palabra clave peligrosa, nunca entra al edificio.
function esSeguro(mensaje: string): boolean {
const peligros = [
/borrar.*base.*datos/i,
/eliminar.*produccion/i,
/DELETE FROM/i
];
for (const peligro of peligros) {
if (peligro.test(mensaje)) {
return false; // bloqueado aquí, el agente nunca lo ve
}
}
return true;
}
La ventaja es que el agente nunca procesa mensajes peligrosos. Si el mensaje se bloquea aquí, el modelo de IA nunca intenta procesarlo ni puede intentar justificar por qué debería hacerlo de todas formas.
Pro: El agente nunca ve los mensajes maliciosos. No puede intentar interpretarlos de forma rara porque el input nunca llega a él.
Contra: Es una lista de patrones. Siempre hay alguien que encuentra una forma nueva de escribir lo mismo sin activar ningún patrón (por ejemplo, “eliminar la data de producción” en lugar de “eliminar producción”).
¿Hay alternativas más robustas?
Sí. El regex es un buen punto de partida, pero en producción se suele complementar con modelos de clasificación entrenados especificamente para detectar intenciones maliciosas. La idea es la misma — evaluar el mensaje antes de que llegue al agente — pero en lugar de buscar patrones de texto, el modelo entiende la semántica: “eliminar la data de producción” y “borrar todo de la base de datos” activan el mismo flag aunque no compartan ninguna palabra con tus patrones.
Un ejemplo listo para usar es la API de Moderation de OpenAI, que devuelve scores por categoría (violencia, contenido ilícito, acoso…) y es gratuita. Para casos donde necesitas más control o quieres ejecutarlo sin llamadas externas, existen modelos guard pequeños como Llama Guard o ShieldGemma, entrenados específicamente para clasificar si un mensaje es seguro antes de pasarlo al modelo principal.
Nivel 3: Los límites de cada herramienta 🔒
¿Qué es? Cada acción que el agente puede hacer tiene su propio guardarraíl en el código. El agente pide algo, y antes de ejecutarlo, se verifica si es permitido. Es la protección a nivel de función.
Ejemplo en la vida real: Es como un cajero automático. El banco puede darte una tarjeta y tú puedes intentar sacar 10.000€, pero la máquina tiene un límite diario de 600€ hardcodeado. No importa cuánto insistas, cuántas veces lo intentes o cómo lo pidas — el límite no está en la pantalla, está en el sistema. El cajero no negocia.
async function eliminarArchivo(ruta: string) {
// ¿Está en la carpeta permitida?
if (!ruta.includes('/tmp/')) {
return '❌ Solo puedo borrar en /tmp/';
}
// ¿Es un archivo especial que no se toca?
if (ruta.endsWith('.env') || ruta.endsWith('.config')) {
return '❌ Este archivo está protegido';
}
// Si pasó las dos pruebas, ok
borrar(ruta);
return '✅ Archivo borrado';
}
Este nivel es el más robusto porque los límites están en el código, no en la interpretación del agente. Aunque el agente intente saltarse las reglas, el código mismo se lo impide.
Pro: El agente puede intentar lo que quiera; el código no lo permitirá. Es muy difícil de eludir porque no depende de palabras o patrones, sino de lógica pura.
Contra: Necesitas escribir este código para cada acción importante. Es más trabajo, pero es el que más funciona en la práctica.
Nivel 4: La revisión de salida 👀
¿Qué es? Antes de usar la respuesta o los comandos que genera el agente, tu código los revisa. Si el agente genera un comando SQL peligroso, lo bloqueas antes de ejecutarlo. Es el filtro final.
Ejemplo en la vida real: Es como un editor que revisa un documento antes de publicarlo: “este párrafo no se publica”. O un director de seguridad que valida cada acción antes de que ocurra.
function esSQLSeguro(sql: string): boolean {
if (sql.includes('DROP') || sql.includes('TRUNCATE')) {
return false; // bloqueado antes de ejecutar
}
return true;
}
// Antes de ejecutar:
if (esSQLSeguro(sqlDelAgente)) {
ejecutar(sqlDelAgente);
} else {
mostrar('❌ Este comando no es seguro');
}
Este nivel es útil especialmente cuando el agente genera código o comandos que se van a ejecutar. Aunque el agente haya pasado todos los filtros anteriores, este es el último que comprueba que lo que está a punto de suceder es realmente seguro.
Pro: Eres el último filtro. Aunque todo lo anterior falle, esto lo atrapa. Es especialmente importante si el agente genera comandos SQL, código ejecutable o acciones que afectan sistemas reales.
Contra: Si generas mucho contenido que revisar, el usuario espera más tiempo. Además, requiere un esfuerzo adicional para analizar cada salida antes de ejecutarla.
Resumen rápido:
| Nivel | Piénsalo como | Velocidad | Seguridad |
|---|---|---|---|
| 1️⃣ Manual | Un cartel que dice “no toques” | Muy rápido | Básica |
| 2️⃣ Filtro | Un guardia en la puerta | Rápido | Media |
| 3️⃣ Herramientas | Un técnico que revisa cada herramienta | Medio | Alta |
| 4️⃣ Salida | Un editor final | Medio | Muy alta |
¿Cuántos necesitas? Empieza por los primeros dos. Si el agente hace cosas peligrosas (borrar, enviar emails), añade el 3. Si el resultado se usa para ejecutar código, añade el 4.
Errores comunes
Confiar solo en el system prompt
El system prompt es el punto de partida, no el sistema completo. Si el agente tiene herramientas que pueden borrar datos, unas instrucciones que digan “no borres nada” no son suficientes. Los límites en el código no dependen de la interpretación del modelo y son más difíciles de eludir.
Guardarrailes que bloquean demasiado
Un agente que rechaza casi todas las solicitudes porque los filtros son demasiado agresivos no sirve de nada. El objetivo no es que el agente sea inútil: es que sea predecible. Empieza con pocos guardarrailes y añade solo los que respondan a problemas que hayas visto realmente.
No registrar los rechazos
Cuando un guardarraíl bloquea algo, guarda un log. Ese registro te dice qué intentó hacer el agente (o el usuario), con qué frecuencia ocurre, y si tu guardarraíl está bien calibrado o está siendo demasiado restrictivo. Sin logs, estás volando a ciegas. Eso sí: al registrar rechazos, evita guardar el mensaje completo del usuario si puede contener datos sensibles. Guarda solo el patrón que lo bloqueó y el timestamp.
Guardarrailes solo en el cliente
Si tu agente llama a una API o ejecuta código en el servidor, los guardarrailes tienen que estar también en el servidor. Un guardarraíl solo en el cliente puede saltarse directamente llamando al endpoint.
Checklist de implementación
Para los bucles de corrección infinitos, el límite de intentos es lo más sencillo que funciona:
// Límite de intentos para prevenir bucles de corrección infinitos
const MAX_REINTENTOS = 3;
let intentos = 0;
while (intentos < MAX_REINTENTOS) {
const resultado = await agente.ejecutar(instruccion);
if (resultado.exitoso) return resultado;
intentos++;
}
throw new Error(`El agente no completó la tarea en ${MAX_REINTENTOS} intentos`);
-
El system prompt lista explícitamente qué puede y qué no puede hacer el agente
-
Hay validación de entrada antes de enviar solicitudes al modelo
-
Cada herramienta con efectos destructivos (borrar, modificar, enviar) tiene guardarraíl propio en su implementación
-
Los rechazos de guardarrailes se registran en logs
-
Las validaciones críticas están en el servidor, no solo en el cliente
-
Hay un límite de intentos para prevenir bucles de corrección infinitos
Preguntas frecuentes
¿Los guardarrailes ralentizan al agente?
Los del system prompt y los de validación de entrada casi no tienen impacto en rendimiento: son comprobaciones locales que se ejecutan en microsegundos. Lo que sí puede añadir latencia es usar un segundo modelo para clasificar intenciones o validar salidas. Para empezar, quédate con validaciones en código puro.
¿Qué pasa si un usuario intenta saltarse los guardarrailes con una instrucción elaborada?
Es posible. Los guardarrailes basados en patrones de texto tienen puntos ciegos. Para sistemas donde esto es crítico, el enfoque más robusto es combinar guardarrailes a nivel de herramienta (los más difíciles de eludir) con revisión humana antes de ejecutar acciones irreversibles. Sin ese segundo nivel, siempre habrá casos borde.
¿Necesito guardarrailes si el agente solo responde preguntas y no ejecuta acciones?
El riesgo es menor, sí. Pero la validación de salida sigue siendo útil para evitar que el agente incluya en sus respuestas datos que no debería compartir: fragmentos de archivos de configuración que tiene en contexto, por ejemplo.
¿Cuántos guardarrailes son suficientes?
Una acción irreversible, un guardarraíl. Un agente que solo lee y responde necesita pocos. Un agente que escribe en base de datos, envía emails, o modifica archivos necesita guardarrailes en cada una de esas acciones. Empieza por las acciones que no tienen marcha atrás.