# Agentes de planificación y ejecución para cambios de producción más seguros

Un agente planificador no debería poder convertir su propia recomendación en un cambio de producción. Dale margen para inspeccionar, comparar y argumentar. Dale a un agente ejecutor independiente un conjunto pequeño de permisos de acción y haz que demuestre que la acción solicitada coincide con un cambio aprobado.

Esa separación parece burocrática hasta que ves a un agente arrastrar una suposición plausible pero equivocada a través de una frontera de API. La mayoría de los fallos no son ataques de caricatura. Un agente lee un runbook desactualizado, confunde un nombre de host de staging con el de producción o sigue texto no confiable incluido en una incidencia. Si el mismo proceso tiene la credencial y la autoridad para actuar, el error se convierte en un cambio antes de que nadie tenga tiempo de detectarlo.

## Un plan es evidencia, no autorización

Los agentes de planificación y ejecución necesitan distintos niveles de autoridad porque la planificación produce una afirmación sobre el mundo, mientras que la ejecución lo modifica. Un buen plan todavía puede basarse en datos antiguos, un contexto incompleto del repositorio o instrucciones copiadas de una fuente no confiable. Tratar un plan como permiso mezcla dos decisiones que merecen revisarse por separado.

Un planificador debe recopilar datos, explicar la incertidumbre, proponer alternativas y producir una solicitud limitada. No debería tener un token de producción solo porque necesita mencionar un endpoint en un informe. Si necesita datos de un sistema protegido, expón una operación de lectura diseñada para ese propósito que devuelva únicamente los datos necesarios, o haz que una persona proporcione el resultado relevante.

El ejecutor tiene otro trabajo. Recibe una solicitud concreta y decide si encaja en su autoridad limitada. No vuelve a abrir el debate de diseño, navega por incidencias arbitrarias ni acepta una frase como «arregla el despliegue». Esa frase puede bastar en una conversación. Como contrato para un proceso con credenciales, no sirve.

Esta distinción también corrige una costumbre que los equipos llaman «humano en el circuito» cuando en realidad quieren decir «una persona echó un vistazo a una conversación larga». Un revisor no puede reconstruir de forma fiable todas las llamadas a herramientas que un agente podría realizar a partir de un texto en prosa. Sí puede revisar una solicitud breve y estructurada que indique el objetivo, la operación, las entradas, el efecto esperado y la forma de revertirla.

El control AC-5 de NIST SP 800-53 pide separar funciones para reducir la posibilidad de que una persona abuse de un sistema sin ser detectada. El texto se refiere a personas, pero el razonamiento se aplica perfectamente a los agentes. No copies una jerarquía de aprobaciones antigua en una instrucción. Separa las capacidades en las credenciales y las interfaces de herramientas reales.

## El ejecutor debe ser más limitado que el plan

El ejecutor debería tener menos libertad que el planificador, no solo una instrucción distinta. Un agente independiente que pueda ejecutar comandos de shell arbitrarios con una credencial cloud amplia no ha reducido el riesgo de forma significativa. Todavía puede reinterpretar una solicitud vaga, descubrir otros recursos y realizar cambios no relacionados.

Empieza con un catálogo de acciones. Cada acción debe indicar una operación y aceptar un conjunto pequeño de parámetros. Por ejemplo, `deploy_service_revision` puede aceptar un nombre de servicio, un identificador de revisión inmutable y un entorno de destino. No debería aceptar un fragmento de shell ni una URL arbitraria.

La restricción más útil suele ser semántica y no técnica. Una credencial puede permitir despliegues, pero un envoltorio del ejecutor todavía puede rechazar una etiqueta mutable como `latest`, rechazar producción si no hay un ID de cambio y rechazar un servicio fuera de su lista permitida. Esas comprobaciones convierten supuestos que normalmente viven en un runbook en código capaz de rechazar una solicitud insegura.

No confundas una herramienta limitada con un resultado limitado. Un token de API que puede actualizar `billing-api` también podría cambiar la distribución del tráfico, las variables de entorno y la configuración de autoscaling. Separa esas operaciones si la API lo permite. Si no lo permite, coloca delante una pequeña pasarela que acepte únicamente la operación que estás dispuesto a automatizar.

Un ejecutor creíble suele tener estos límites:

- Usa una identidad separada para cada entorno.
- Recibe únicamente acciones con nombre, no un shell general.
- Valida los nombres de destino y las entradas inmutables antes de llamar a un proveedor.
- Tiene una vida útil corta y ninguna ruta para generar credenciales más amplias.
- Emite un registro duradero de la solicitud y el resultado.

A menudo los equipos se resisten porque las herramientas genéricas son más rápidas de conectar. Son más rápidas para la primera demostración. Una herramienta amplia como `run_command` resulta cara la primera vez que alguien tiene que explicar por qué un agente eliminó el recurso equivocado después de leer un comando copiado en una incidencia.

## La entrega necesita una solicitud de cambio verificable por una máquina

El planificador debe entregar un artefacto estructurado que el ejecutor pueda validar sin interpretar intenciones. Los planes en texto libre invitan al ejecutor a completar las lagunas con su propio razonamiento, lo que devuelve la autoridad de planificación al camino de acción.

Una solicitud práctica puede verse así:

```json
{
  "request_id": "chg-2025-0417-redis-timeout",
  "environment": "production",
  "action": "deploy_service_revision",
  "target": {
    "service": "checkout-api",
    "revision": "sha256:8f31c2..."
  },
  "expected_effect": "Run the approved checkout-api revision",
  "rollback": {
    "action": "deploy_service_revision",
    "revision": "sha256:31aa09..."
  },
  "approval": {
    "approved_by": "release-manager",
    "approved_request_hash": "b2c4..."
  }
}
```

El hash importa. Sin él, un revisor puede aprobar la solicitud que vio mientras el ejecutor recibe una versión modificada. El registro de aprobación debe vincularse a una representación canónica de los campos exactos que utilizará el ejecutor. Si el sistema serializa JSON de forma diferente en distintos lugares, define primero la canonicalización. Un hash de texto improvisado es una trampa cuando el orden de los campos o los valores predeterminados omitidos pueden cambiar el contenido.

El ejecutor debe rechazar la solicitud con motivos claros. Una respuesta útil muestra qué comprobación falló sin revelar ningún secreto:

```json
{
  "status": "denied",
  "request_id": "chg-2025-0417-redis-timeout",
  "reason": "revision must be an immutable digest",
  "executed": false
}
```

Esa negativa forma parte del diseño, no es un caso límite vergonzoso. Los equipos prueban si los agentes pueden realizar acciones y se saltan las pruebas que demuestran que no pueden salir de su alcance. Prueba ambos caminos.

No permitas que el planificador elija la definición de acción del ejecutor. La persona responsable de la plataforma debe definir el catálogo, sus reglas de validación y la asignación de credenciales. El planificador selecciona entre las acciones disponibles. No puede inventar `deploy_anything` porque una tarea concreta parezca urgente.

## Los procesos separados evitan compartir autoridad por accidente

Dos roles de agente dentro de un mismo proceso siguen siendo fáciles de confundir. Las variables de entorno, las cachés de tokens, los directorios de trabajo y los registros de herramientas compartidos crean rutas accidentales alrededor del límite que pretendías establecer. Ejecuta el planificador y el ejecutor como procesos distintos, con configuraciones de inicio diferentes.

El proceso del planificador debe recibir herramientas de investigación y quizá interfaces de lectura filtradas de forma estricta. No debería ver las credenciales del ejecutor en su entorno, sus archivos de configuración ni las descripciones de sus herramientas. Un modelo no necesita acceso en texto plano a un token para hacer un uso indebido de él. Si el proceso puede invocar una herramienta que posee el token, el límite de la herramienta es el límite de capacidad relevante.

El ejecutor debe recibir la solicitud estructurada aprobada y el inventario de herramientas más pequeño posible. No debería recibir el contenido original de la incidencia, contenido web arbitrario, una herramienta de búsqueda para todo el repositorio ni la transcripción de la conversación del planificador. Esos materiales pueden contener inyección de instrucciones, comandos incorrectos o indicaciones casuales que el ejecutor no tiene ningún motivo para obedecer.

Esto te da una regla sencilla para depurar: si un ejecutor necesita más contexto para decidir qué operación realizar, el artefacto de entrega está incompleto. No lo soluciones dándole acceso amplio para descubrir información. Añade al pedido el campo, la regla de validación o la decisión humana que falta.

La separación de procesos también ayuda durante la respuesta a incidentes. Puedes revocar la sesión del ejecutor sin perder el registro de investigación del planificador. Puedes comprobar si el planificador propuso un objetivo distinto del aprobado. Si ambos roles comparten una sesión y una identidad, reconstruir lo ocurrido se convierte en una cuestión de suposiciones.

Sallyport encaja con este límite cuando un agente compatible con MCP necesita realizar acciones HTTP o SSH sin recibir las credenciales de API o SSH subyacentes. La aplicación guarda esos secretos en su bóveda cifrada y ejecuta la llamada por sí misma, de modo que el planificador no puede extraer una credencial aunque sus instrucciones se hayan corrompido.

## La aprobación debe estar donde cambian las consecuencias

Una aprobación humana debe cubrir una decisión concreta, no dar una bendición vaga para todo lo que haga después un agente. La aprobación de sesión sirve para establecer que un proceso de agente conocido puede usar un conjunto limitado de acciones de bajo riesgo durante una ejecución. Es un mal sustituto de la revisión cuando la acción puede modificar datos de producción, identidades, exposición de red o dinero.

La aprobación por llamada corresponde a las credenciales cuyo uso tiene consecuencias importantes. El clic adicional está justificado cuando la llamada es irreversible, inusual o costosa de deshacer. Úsala para una clave de eliminación en producción, una credencial que cambie controles de acceso o una operación de pago. No la uses para cada consulta de estado inofensiva. Una ventana de confirmación que aparece constantemente se convierte en ruido de fondo y las personas la aprueban sin leer.

Usa aprobaciones que muestren lo que un revisor puede juzgar: el nombre de la acción, el entorno de destino, el recurso objetivo, la entrada inmutable y cualquier reversión prevista. Un diálogo que solo diga «El agente solicita acceso» es teatro. No informa de nada sobre las consecuencias.

El alcance de la aprobación debe caducar. Una aprobación vinculada a una ejecución debe terminar cuando el proceso se cierre. Una aprobación vinculada a una solicitud de cambio debe estar asociada a su contenido y no autorizar en silencio una revisión posterior. Las autorizaciones de larga duración resultan atractivas porque eliminan fricción, pero recrean el privilegio permanente que la separación pretendía evitar.

La escala de decisión de Sallyport tiene una forma útil para este modelo: la compuerta de la bóveda deniega toda acción mientras está bloqueada, la autorización de sesión identifica un proceso de agente nuevo y determinadas claves por llamada pueden pedir confirmación en cada uso. Es intencionadamente más limitada que un motor de políticas. Los equipos todavía deben decidir qué credenciales merecen un control por llamada.

## La inyección de instrucciones llega primero a los planificadores

La inyección de instrucciones suele entrar por el trabajo normal del planificador. Un comentario del repositorio dice que hay que ejecutar un comando. Una incidencia de soporte incluye una instrucción falsa para extraer la configuración. Una página web indica al agente que ignore las instrucciones anteriores. Los agentes planificadores ven más texto no confiable del que los ejecutors deberían ver nunca.

La respuesta equivocada habitual es pasar meses intentando escribir una instrucción perfecta que diga al planificador que no se deje engañar. El comportamiento del modelo puede mejorar, pero las instrucciones de texto no sustituyen a los límites de autoridad. Da por hecho que el planificador puede repetir una instrucción incorrecta en su plan. Después haz que el ejecutor rechace cualquier solicitud fuera de su catálogo, alcance y vínculo de aprobación.

Considera un fallo conocido. Un planificador investiga una latencia y lee una nota antigua de un incidente que recomienda establecer en cero el número de réplicas de un servicio antes de drenar el tráfico. Escribe un plan que menciona el entorno equivocado porque la nota usaba un nombre de host copiado. Si ese planificador puede llamar a una herramienta de despliegue general, podría convertir una recomendación antigua en una interrupción.

Con un diseño separado, el fallo se detiene en varios puntos. La solicitud de entrega debe indicar explícitamente producción. El ejecutor solo acepta una acción de despliegue de una revisión, no una modificación del número de réplicas. El revisor humano ve el objetivo real y el efecto solicitado. El registro del ejecutor deja constancia de la denegación si la solicitud no encaja. Ninguno de esos controles exige que el planificador reconozca perfectamente el texto manipulado u obsoleto.

Mantén la salida del planificador etiquetada como entrada no confiable para el camino de ejecución. Esa frase debe afectar al tratamiento de los datos, no ser solo una advertencia en la interfaz. No interpolés prosa del planificador en comandos de shell. No permitas que rellene rutas HTTP, encabezados o parámetros de consulta sin comprobaciones de tipos y listas permitidas. Un esquema JSON ayuda, pero validarlo no te dice por sí solo si `production` es un destino autorizado.

## El acceso de lectura también puede abrir un camino al daño

Los equipos suelen dar a los planificadores un acceso de lectura amplio porque «no pueden cambiar nada». Esa frase ha causado muchos problemas evitables. El acceso de lectura puede revelar datos de clientes, nombres de host internos, historiales de despliegue, indicadores de funciones, patrones de acceso y nombres de sistemas privilegiados. También puede proporcionar exactamente la información que un atacante necesita para preparar una solicitud de acción convincente.

Clasifica las lecturas según su sensibilidad y según lo que permiten hacer. Un endpoint de estado que devuelve la salud de un servicio no es lo mismo que un endpoint que exporta una base de datos. Un inventario de servicios que muestra nombres públicos no es lo mismo que una API de gestión de credenciales que devuelve identificadores y metadatos de secretos. No pongas ambas cosas detrás de una herramienta genérica llamada `read_only`.

Dale al planificador datos derivados cuando sea posible. En lugar de acceso a todos los eventos de despliegue, ofrece una operación que devuelva la revisión actual, el estado de salud y el ID del último cambio aprobado de un servicio con nombre. En lugar de permisos amplios para consultar la base de datos, proporciona una métrica que responda a la pregunta de diagnóstico. Reduces tanto la divulgación accidental como la cantidad de material que puede transportar instrucciones hostiles.

Aquí es donde los equipos se pasan de prudentes y dejan al planificador sin utilidad. La respuesta no es dejar ciego al agente. Es decidir qué datos necesita la tarea y crear una interfaz de lectura para esos datos. Si un planificador necesita habitualmente un campo adicional, añádelo de forma deliberada después de revisar el caso de uso. No resuelvas cada carencia dándole una consola de producción.

## Los registros deben permitir reconstruir una discrepancia

Un registro de auditoría debe responder a algo más que «¿se produjo una llamada a una API?». Después de un cambio discutido, necesitas comparar el artefacto propuesto por el planificador, el artefacto que aprobó una persona, la solicitud validada por el ejecutor, la llamada externa exacta y la respuesta. Si falta cualquiera de esos elementos, queda espacio para una historia en lugar de evidencia.

Registra un ID de solicitud estable durante todo el recorrido. El planificador lo asigna o lo recibe. La aprobación se vincula a él y al hash de su contenido. El ejecutor lo escribe junto con su identidad de proceso y el resultado de la acción. La pasarela externa lo registra junto al destino de salida y el estado de la respuesta. Evita registrar tokens bearer, contraseñas, claves privadas o cargas sensibles completas solo para facilitar la correlación.

La evidencia de manipulación importa porque los registros normales de las aplicaciones suelen estar en almacenes que los administradores pueden editar. Una secuencia de eventos enlazada mediante hashes permite detectar cambios posteriores si conservas el estado esperado de la cadena. No demuestra mágicamente que cada evento sea verdadero. Sí hace más difícil ocultar una reescritura silenciosa de la historia registrada, que es lo que necesitas cuando las personas bajo revisión también tienen acceso al almacén de registros.

Sallyport proyecta sus registros de sesiones y actividad desde un registro de auditoría cifrado y encadenado mediante hashes, y `sp audit verify` comprueba la cadena sin conexión sobre el texto cifrado y sin una clave de la bóveda. Esto resulta útil en una investigación porque la verificación no requiere entregar credenciales de acción al revisor.

Haz un simulacro de reconstrucción antes de que un incidente te obligue a hacerlo. Elige un cambio aprobado y pide a un compañero que responda cinco preguntas usando los registros: qué agente lo propuso, quién aprobó la solicitud exacta, qué ejecutor la realizó, qué operación de salida se produjo y qué resultado volvió. Si alguna respuesta depende de la memoria o de una transcripción de chat, mejora los registros.

## La primera acción automatizada debe ser aburrida y reversible

Empieza la separación con una acción que tenga una persona responsable clara, un conjunto de objetivos limitado y una reversión que ya hayas practicado. Un despliegue en un entorno no productivo con una revisión inmutable es un primer caso mejor que cambiar reglas de acceso o eliminar cuentas antiguas. El trabajo aburrido te permite encontrar fallos de diseño sin apostar producción a una demostración.

Ejecuta la misma tarea mediante el flujo hasta que el esquema de solicitud deje de cambiar por motivos triviales. Observa los fallos previsibles: los planificadores omiten un objetivo, los revisores aprueban una descripción genérica, los ejecutores necesitan un contexto no declarado y los registros no pueden asociar la aprobación con la llamada. Cada fallo te indica dónde sigue filtrándose la autoridad entre los roles.

No midas el éxito por la cantidad de clics de aprobación que has eliminado. Mídelo por si el ejecutor rechaza un objetivo equivocado, una revisión no aprobada y una acción no compatible, mientras completa la acción prevista. Un sistema que facilita todas las acciones probablemente permite demasiadas.

Cuando el flujo resista, amplía una familia de acciones cada vez. Mantén al planificador curioso y al ejecutor aburrido. La automatización de producción gana confianza cuando sus negativas son tan deliberadas como sus éxitos.
