La separación de funciones es uno de los controles más viejos del compliance: la persona o la credencial que opera un sistema todos los días no puede ser la que, por su cuenta, cambia lo que ese sistema tiene permitido hacer. ISO 27001 y SOC 2 la piden, y cualquier sistema que mire un regulador tiene que tenerla.

Muchas plataformas de agentes de IA la dejan de lado sin decirlo. Hay una sola API, una sola consola de administración, un solo juego de credenciales, y el plano que corre el agente sobre datos reales de clientes es el mismo donde se edita la política que lo gobierna. Operar y configurar quedan del mismo lado de la frontera de confianza. Los equipos cumplen el requisito por encima, con proceso: asignaciones de roles en un único panel, revisiones periódicas de accesos, un acuerdo sobre quién puede tocar qué. El proceso es mejor que nada, y falla justo en los casos que importan: un token con más alcance del debido, una sesión de operador comprometida, un bug en la única superficie que hace las dos cosas.

Lo que tiene a favor el modelo de un solo plano

Una superficie de control unificada es más simple de construir y de entender, y para mucho software es la decisión correcta. El argumento acá es acotado. Cuando el mismo plano actúa sobre los datos y además define las reglas para actuar sobre ellos, la separación de funciones depende de la disciplina de quienes lo usan. Podés tenerla el lunes y perderla el martes por un grant mal acotado, y nada en la arquitectura te va a avisar.

La inversión: dos planos, separados donde importa

La alternativa estructural divide la superficie que usan los tenants en dos planos que no comparten rol de base de datos, binario ni ruta:

Dos planos: el plano de runtime ejecuta intents bajo un rol de base de datos; el plano de contrato guarda contratos y definiciones de roles bajo otro, y la base de datos le niega al rol de runtime toda escritura en las tablas de contrato.

runtime plane    {tenant}.zarel.ai         runtime-api    PG role: zarel_runtime    token_class: tenant
                 records · chat · tools · flows · events · role assignments

contract plane   {tenant}.admin.zarel.ai   contract-api   PG role: zarel_contract   token_class: contract
                 contracts · entity catalog · role definitions · grants

El plano de runtime opera bajo las reglas: corre el agente y lee y escribe los datos operativos. El plano de contrato define las reglas: qué entidades existen, qué significa cada rol, qué puede hacer el agente. Son binarios distintos, en hosts distintos, autenticados con clases de token distintas, y por debajo se conectan a la base de datos como roles distintos con grants distintos. El rol de runtime puede leer todas las tablas de contrato, porque hace cumplir lo que dicen, y no tiene grant para escribir en ninguna; tampoco hay una ruta de runtime desde donde intentarlo. El plano de contrato rechaza un token emitido para el plano de runtime por su clase y su audiencia, y lo mismo pasa al revés. El aislamiento entre tenants es otro eje, que también se aplica, con Row-Level Security de Postgres: RLS separa tenants, y la división en planos separa funciones. El plano de runtime sí decide quién tiene cada rol (solo si el contrato habilita esa acción, y nunca para un rol de owner), pero qué puede hacer un rol se decide únicamente en el plano de contrato.

Así que ni un token de runtime ni el rol de base de datos del runtime pueden reescribir las reglas del agente: no tienen ni el grant ni la ruta.

Por qué esto mueve la frontera de confianza

Las otras piezas de esta serie hacen lo mismo en otros puntos: el agente propone y el runtime ejecuta, así que un modelo comprometido no puede tomar una acción que su rol no tiene otorgada; los eventos de la máquina de estados y de los flows están encadenados por hash, con checkpoints firmados, así que un auditor puede verificar ese registro en lugar de confiar en él. Acá el punto es el que separa operar de configurar. Como son planos distintos, un token filtrado o un grant demasiado amplio en la superficie operativa no llega a la superficie de control, y una propiedad que el diseño habitual deja librada al proceso pasa a estar en la arquitectura.

Los límites, sin vueltas

Los dos planos comparten una base de datos. Corren sobre una sola instancia de PostgreSQL. La separación la hacen cumplir roles de base de datos distintos con grants de mínimo privilegio, binarios distintos, hosts y clases de token distintos; no hay almacenamientos separados, así que hablar de "sistemas físicamente separados" sería exagerar. Tener bases separadas complicaría RLS y la operación, y lo que pide la separación de funciones es quién puede escribir qué, algo que los grants ya deciden.

Una sola clave firma las dos clases de token. El servicio de runtime lee la clave de cada tenant, que firma tanto los tokens de runtime como los de contrato, porque la necesita para verificar los suyos. Un token de runtime robado no puede pasar al otro plano; un servicio de runtime comprometido por completo podría emitirse un token de contrato. Lo que igual no puede hacer es escribir en una tabla de contrato con su propio rol de base de datos.

No separa un paso operativo de otro. Dos pasos de runtime, autorizados cada uno por separado, pueden sumar entre los dos una violación del control dual. Venkat Peri, que trabaja en infraestructura de IA agéntica para gestión patrimonial en Advisor360°, lo describe en The Agentic Auth Problem Nobody Is Actually Solving: una violación que "solo se hace visible cuando mirás el arco de la ejecución y no un momento aislado dentro de ella" [1]. Ninguna división entre planos llega a eso. Tiene que ser una regla que lleve el propio flow.

Hay más planos que dos. Las acciones de operador y del ciclo de vida de los tenants corren en una superficie de plataforma aparte, y los secretos de los canales están en su propio servicio de custodia; a los dos se llega solo desde la red interna. Los dos de este artículo son los que usan los tenants.

Todavía sin certificación. ISO 27001 y SOC 2 piden segregación de funciones, y los dos planos son la forma en que esta arquitectura está diseñada para responder a eso. Zarel no tiene hoy ninguna certificación; está diseñado con ellas como objetivo.

La garantía vive en los grants y en las rutas. La hace cumplir una configuración que viene con el deployment, y se puede verificar inspeccionando esa configuración. Un deployment que le diera grants de más al rol de runtime la debilitaría, y por eso la configuración tiene que estar abierta a inspección.

Lo que está en juego

En una auditoría real, la pregunta por la separación de funciones es directa: mostrame que las credenciales que operan este sistema no pueden, por sí solas, cambiar lo que tiene permitido hacer. Una plataforma de un solo plano responde con una matriz de control de accesos y un proceso para revisarla. Un deployment de dos planos responde mostrando los dos roles: estos son los grants de la credencial de runtime, y ninguno escribe en una tabla de contrato; esta es la ruta que cambiaría la política, en un host contra el que esa credencial no se puede autenticar.

Para comprobarlo no hace falta nuestro código, porque los grants están en el catálogo de la propia base de datos. En un deployment de Zarel, has_table_privilege('zarel_runtime', 'contract.roles', 'INSERT') devuelve false, igual que cualquier otra escritura sobre una tabla de contrato, y un token de runtime enviado al host de administración se rechaza por su clase antes de que se verifique la firma. Para verlo en un deployment en marcha, escribinos.

Este es el caso de la separación de funciones dentro de una línea más amplia: la comunicación y la propuesta pueden ser probabilísticas, pero la autoridad, la consecuencia, el registro y el derecho a cambiar las reglas tienen que ser determinísticos, declarados y estar separados en la estructura. El argumento general está en No se combate el probabilismo con probabilismo; el de la ejecución, en El agente propone; el runtime aprieta el botón; la capa de prueba, en Una auditoría en la que no hace falta confiar.


Las citas están traducidas por el autor. Los originales, en inglés:

  1. Peri, The Agentic Auth Problem Nobody Is Actually Solving: "only becomes visible when you look at the arc of the execution rather than any single moment in it".

Nicolás Moreno construye Zarel: operaciones de IA gobernadas, donde la IA propone y el contrato dispone.