Saltar al contenido
Todos los insights

Cómo se construye un sistema agéntico seguro

9 min de lecturaAI SecurityAgentesArquitectura
Portada: arquitectura de referencia de un sistema agéntico, con el planificador sin privilegios separado de los ejecutores, cada herramienta con su propia credencial y las trazas de acciones saliendo hacia observabilidad

En el artículo sobre AI red teaming aparecía una frase que conviene desarrollar: la mayoría de los hallazgos contra un sistema de IA no se arreglan con un parche, se arreglan con arquitectura. Este artículo va de esa otra mitad.

El punto de partida es incómodo pero libera bastante. Hay que dar por hecho que, alguna vez, el modelo va a obedecer a un atacante. No como quien acepta una derrota, sino como quien diseña un sistema eléctrico dando por hecho que alguna vez habrá un cortocircuito. La pregunta deja de ser cómo conseguir que el modelo nunca se equivoque, que no tiene respuesta, y pasa a ser qué pasa cuando se equivoque. Si la respuesta es "nada grave", el sistema está bien construido.

Todo lo que viene a continuación sale de ahí.

El modelo no es el perímetro

El error de diseño más repetido es tratar el prompt de sistema como si fuera un control de seguridad. Se escriben instrucciones cada vez más firmes, se añaden frases del tipo "no reveles nunca información de otros clientes", y se da el asunto por resuelto.

No funciona, y no por falta de esmero al redactarlas. El prompt de sistema y el contenido que llega de fuera viajan por el mismo canal y son la misma cosa para el modelo: texto. Una instrucción del sistema no tiene más autoridad técnica que un párrafo escondido en un documento; solo tiene más autoridad si el modelo decide dársela, y esa decisión es probabilística.

Un control de seguridad de verdad es el que se cumple aunque el modelo quiera saltárselo. Es decir: permisos, aislamiento y límites. Ahí es donde hay que gastar el esfuerzo.

Arquitectura de referencia de un sistema agéntico seguro: el canal de entrada con la identidad del usuario, el planificador sin privilegios, los ejecutores con una credencial por herramienta, el contenido no confiable marcado y aislado, la puerta de revisión humana en las acciones sensibles y las trazas de acciones saliendo hacia observabilidad

Los siete controles

1. El agente tiene identidad propia

Un agente que consulta la base de datos con la credencial del usuario que abrió la sesión tiene, en la práctica, todos los permisos de ese usuario. Y uno que usa una cuenta de servicio compartida entre todas sus herramientas tiene los de esa cuenta, que suelen ser bastantes.

Lo correcto es que el agente sea un principal más del sistema de identidades, con su propia entrada en el directorio, sus propios permisos y su propia trazabilidad. Cuando además necesita actuar en nombre de alguien, eso se resuelve con delegación explícita y acotada, no reutilizando el token de la sesión.

La prueba de si esto está bien resuelto es sencilla: si nadie sabe responder con qué identidad se ejecutó una acción concreta de hace tres semanas, no lo está.

2. Una credencial por herramienta, con el alcance mínimo

Cada capacidad del agente merece su propia credencial y su propio alcance. La herramienta que consulta pedidos no necesita poder escribir; la que envía correos no necesita leer la base de datos de clientes; la que abre incidencias no necesita cerrarlas.

Esto no es una recomendación abstracta. Es lo que convierte una inyección de prompt exitosa en un incidente menor en vez de en una brecha. Un atacante que consigue que el agente llame a una herramienta solo obtiene lo que esa herramienta puede hacer, y no lo que el agente entero podría hacer.

En sistemas con muchas herramientas conviene además pensar en combinaciones. Dos permisos inocuos por separado pueden ser peligrosos juntos: leer documentos internos y enviar correos al exterior son cada uno razonables, y la suma es una vía de exfiltración.

3. El planificador no ejecuta

Este es el patrón que más rendimiento da y el que menos se aplica.

Consiste en separar en dos piezas lo que normalmente va junto. Una decide qué hay que hacer y produce un plan, y no tiene ninguna credencial ni acceso a ninguna herramienta. Otra recibe ese plan, lo valida contra un esquema y unas reglas, y solo entonces ejecuta.

La ventaja es que el componente que lee contenido no confiable es precisamente el que no puede hacer nada. Aunque un documento manipulado consiga convencer al planificador de que hay que borrar una tabla, el plan resultante se topa con una validación que no acepta esa acción, o que sí la acepta pero requiere aprobación. La instrucción maliciosa nunca llega a tocar un sistema.

El coste es real: hay que definir el esquema de acciones válidas y mantenerlo. A cambio, es lo único de esta lista que corta de raíz una familia entera de ataques en vez de reducir su impacto.

4. El contenido de fuera entra marcado y aislado

Todo lo que el sistema no controla, que suele ser casi todo lo interesante, tiene que entrar identificado como tal: documentos que suben los usuarios, correos, tickets, resultados de búsqueda, respuestas de APIs de terceros.

Marcarlo sirve para tres cosas. Para poder decirle al modelo, en la estructura de la llamada y no solo en una frase, qué parte es dato y qué parte es instrucción. Para poder aplicarle un tratamiento distinto, como quitar contenido oculto, normalizar el texto o recortar longitud. Y sobre todo para que, cuando algo salga mal, se sepa qué fuente lo introdujo.

En arquitecturas RAG hay un detalle que decide el resultado: el filtrado por permisos tiene que ocurrir en la recuperación, no en la respuesta. Si el índice devuelve fragmentos de todos los clientes y se confía en que el modelo no mencione los que no tocan, la fuga es cuestión de tiempo. Si el índice solo devuelve lo que ese usuario puede ver, el modelo no puede filtrar lo que nunca ha visto.

5. Revisión humana donde la equivocación cuesta

Poner a una persona a aprobar todo es inviable y acaba en aprobaciones automáticas de tanto repetirlas, que es peor que no tenerlas. La decisión no es cuánta supervisión, sino dónde.

El criterio que funciona es el de la reversibilidad. Las acciones que se deshacen solas o con un clic pueden ir directas. Las que mueven dinero, borran datos, se comunican con terceros o cambian permisos pasan por una puerta. Y esa puerta tiene que enseñar lo que se va a hacer en términos entendibles, no un volcado de JSON que nadie lee.

Conviene además que el umbral sea configurable por importe o por volumen, porque el mismo tipo de acción cambia de categoría con la escala: emitir una factura de cien euros y una de cien mil son la misma llamada con distinto riesgo.

Diagrama de decisión sobre revisión humana: si la acción es reversible sin coste, se ejecuta directa; si es irreversible, mueve dinero, sale al exterior o cambia permisos, pasa por una puerta de aprobación con la acción explicada en lenguaje claro y con umbral configurable

6. Se registran las acciones, no la conversación

Casi todos los sistemas guardan los mensajes. Muy pocos guardan lo que de verdad hace falta cuando algo va mal: qué herramienta se llamó, con qué parámetros, con qué identidad, qué devolvió, cuánto tardó y qué plan la originó.

Sin ese registro, un incidente no se puede reconstruir. Con él, se responde en una tarde a las tres preguntas que van a hacer: qué hizo el agente, quién se lo pidió y a qué datos llegó.

La forma sensata de montarlo hoy es con trazas de OpenTelemetry, que ya tiene convenciones específicas para sistemas de IA generativa, y enviarlas donde ya se miran el resto de trazas y registros de la casa. Un sistema de observabilidad separado solo para el agente es un sistema que nadie mira.

7. Límites y una parada que alguien haya probado

Un agente sin límites es un agente que, ante un bucle o una instrucción hostil, seguirá intentándolo. Los límites que conviene fijar desde el principio son cuatro: gasto por tarea y por día, número de acciones por tarea, tiempo máximo de ejecución y número de reintentos.

Y encima de todo, una forma de pararlo. No un despliegue de emergencia, sino un interruptor real: una variable, una regla, algo que corte en segundos y que además esté probado. Un interruptor que nunca se ha accionado no es un interruptor, es una suposición.

Lo que no funciona

Merece la pena nombrar los controles que dan sensación de seguridad y no la dan.

Instrucciones más firmes en el prompt. Ya está explicado arriba. Ayudan en el caso normal y no sostienen el caso adversario.

Listas negras de frases. Bloquear "ignora las instrucciones anteriores" y sus variantes es perder una carrera por definición: el atacante tiene infinitas formas de decir lo mismo, y encima puede decirlo en otro idioma, codificado o partido en trozos.

Un clasificador de inyecciones como único control. Un detector delante del modelo es útil como capa más, y baja el ruido. Pero tiene falsos negativos, y un control con falsos negativos no puede ser el único que separa a un atacante de una acción irreversible.

Confiar en que el modelo mejore. Los modelos han mejorado mucho y seguirán haciéndolo, pero ninguno resuelve el problema de fondo, que es que no hay separación entre el canal de datos y el de instrucciones. Mientras eso siga así, la defensa vive fuera del modelo.

Cómo se comprueba que todo esto funciona

Un diseño sobre papel no demuestra nada. La forma de saber si los controles aguantan es atacarlos, que es exactamente el ejercicio del AI red teaming: se intenta que el agente ejecute instrucciones escondidas, que use una herramienta que no le toca, que devuelva datos de otro usuario, y se mide cuántas veces se consigue.

Lo interesante de hacerlo después de aplicar la arquitectura es que los resultados cambian de naturaleza. Los ataques siguen funcionando a nivel de modelo, porque eso no se arregla, pero dejan de producir impacto. Y ese es justamente el resultado que se busca: no un sistema al que no se le pueda decir nada raro, sino uno donde decirle algo raro no sirva de nada.

Por dónde empezar si el sistema ya está en producción

Rehacer la arquitectura entera no suele ser una opción. El orden que mejor rendimiento da por esfuerzo invertido es este.

Primero, inventariar las herramientas y sus credenciales. En la mitad de los casos aquí ya aparece algo que no debería estar, y es la corrección más barata de todas.

Segundo, poner trazas de acciones. No arregla nada por sí solo, pero sin esto no se puede medir si el resto de cambios sirve, ni responder cuando pase algo.

Tercero, meter la puerta de aprobación en las dos o tres acciones irreversibles que ya se sabe cuáles son.

Cuarto, separar el planificador de la ejecución, que es el cambio más profundo y el que conviene planificar con calma.

Y con eso hecho, atacarlo para ver qué queda.

En KAIX LABS construimos sistemas de este tipo y también los atacamos, y la experiencia es que las dos cosas se entienden mejor juntas: cuesta diseñar bien una defensa sin haber intentado romperla antes. Si tenéis un agente en producción o a punto de salir, una conversación de treinta minutos suele ordenar bastante por dónde empezar.