Niveles de autonomía
La autonomía es una configuración por agente que reside en un perfil de riesgo con nombre: [risk_profiles.<alias>].level. Cada agente hace referencia a un perfil de riesgo mediante agents.<alias>.risk_profile = "<profile-alias>". Tres configuraciones; supervised es la predeterminada.
readonly / supervised / full son los únicos valores aceptados; read_only (con guion bajo) se rechaza al cargar la configuración. Consulta el Ejemplo mínimo funcional canónico para ver cómo el perfil encaja en una configuración completa.
Los tres niveles
readonly
El agente puede observar pero no cambiar nada. Las herramientas permitidas son aquellas que no tienen efectos secundarios:
file_read,file_listmemory_searchhttp(solo GET; POST bloqueados)web_searchtime
Útil para: un agente de preguntas y respuestas público, un despliegue solo de análisis, o como una forma de verificar una nueva configuración de herramienta antes de permitirle escribir algo.
supervised (predeterminado)
Las herramientas de bajo riesgo se ejecutan automáticamente. Las herramientas de riesgo medio activan un mensaje de aprobación del operador. Las herramientas de alto riesgo están bloqueadas.
Clasificación de riesgos:
| Riesgo | Ejemplos | Comportamiento |
|---|---|---|
| Bajo | file_read, http GET, memory_search, web_search, time | Ejecuta |
| Medio | file_write dentro del espacio de trabajo, shell con comandos permitidos, http POST a dominios permitidos | Pregunta al operador |
| Alto | shell con comandos desconocidos o denegados, file_write fuera del espacio de trabajo, patrones destructivos | Bloques |
Canal de aprobación: la solicitud de aprobación se entrega a través del canal que haya iniciado la conversación. Telegram usa botones de teclado en línea; Slack Socket Mode usa botones de Block Kit; Discord, Signal, Matrix y WhatsApp insertan un token corto en la solicitud y esperan una respuesta <token> approve|deny|always. En la CLI, es una solicitud en línea. En ACP, el agente emite una solicitud JSON-RPC session/request_permission del agente al cliente (no una notificación session/update); el cliente responde con {"outcome": {"outcome": "selected", "optionId": "allow-once|allow-always|reject-once"}} o {"outcome": {"outcome": "cancelled"}} para aprobar, aprobar siempre o denegar. Consulta ACP → session/request_permission.
Tiempo de espera: las solicitudes de aprobación sin respuesta expiran después del approval_timeout_secs del canal (120 por defecto para la mayoría de los canales; consulta el bloque de configuración de cada canal). Los tiempos de espera agotados se tratan como denegaciones.
full
Las llamadas a herramientas no cubiertas marcadas como low/medium/high se ejecutan sin preguntar. always_ask sigue solicitando aprobación incluso en modo Full: un nombre exacto o "*" muestra una solicitud de aprobación en la CLI, envía una petición por un canal secundario o se bloquea por defecto en una superficie no interactiva sin aprobador. workspace_only queda implícitamente desactivado (el agente puede acceder a rutas fuera del espacio de trabajo); forbidden_paths sigue bloqueando; el sandbox a nivel de SO (sandbox_enabled + sandbox_backend) sigue aplicándose.
Esto es apropiado para desarrollo local de confianza, CI o SOPs que necesitan ejecutarse de principio a fin sin una persona en el bucle. Mantén las herramientas sensibles en always_ask si necesitas full para todo lo demás, pero aun así quieres una solicitud de confirmación (o una denegación en modo fail-closed) para esas herramientas. Si necesitas full + sin restricciones de workspace + sin sandboxing, consulta modo YOLO.
Anulaciones por herramienta
auto_approve, always_ask y excluded_tools se almacenan como listas planas de nombres de herramientas en el perfil de riesgo (no como tablas anidadas). always_ask tiene prioridad sobre Autonomía total, auto_approve y una concesión “Always” a nivel de sesión: una herramienta incluida en la lista (o "*") sigue solicitando confirmación. excluded_tools también está disponible por canal (channels.<type>.<alias>.excluded_tools) para ocultar herramientas en superficies específicas sin cambiar el perfil.
Enrutamiento de aprobación entre canales
De forma predeterminada, un mensaje de aprobación se entrega por el canal que inició la conversación. Para enviar las aprobaciones de herramientas de un perfil a un canal aprobador distinto en su lugar (por ejemplo, un agente impulsado desde un canal público cuyas acciones de riesgo deben ser aprobadas por un canal de operaciones separado, o por un principal diferente), establezca approval_route en el perfil de riesgo:
[risk_profiles.frontline.approval_route]
approver_channel = "matrix.ops" # una clave del registro de canales, NO el originador
approver_recipient = "!ops:example.org" # ID de sala de Matrix; destino específico de la ruta
on_no_approver = "deny" # valor por defecto; o "inherit-originator"
timeout_secs = 120 # valor por defecto; limita la ventana de respuesta del aprobador
approver_channeles la clave del registro de canales que recibe la solicitud de aprobación. Las claves están calificadas por plataforma,<channel>.<alias>(por ejemplomatrix.opsotelegram.default); un nombre de plataforma sin más (p. ej.matrix) solo se resuelve cuando es el único canal de esa plataforma. Un alias por sí solo no es una clave de registro y fallará en cerrado. Cuando la ruta está configurada, la barrera de aprobación pregunta solo a ese canal, no al canal de origen.approver_recipientes el destino en ese canal, no el destinatario del originador. Es específico de cada canal: use un ID de sala de Matrix como!ops:example.org, un ID de chat de Telegram como-1001234567890, un ID de canal de Slack comoC0123456789o un ID de canal de Discord como123456789012345678. El destino configurado se usa para el salto del aprobador; el destinatario de origen nunca se reutiliza para ese salto.on_no_approverdecide qué sucede cuando el aprobador no responde de forma concluyente, no se le puede localizar, no es un canal registrado o se agota el tiempo:deny(el valor predeterminado) falla de forma cerrada y deniega la llamada a la herramienta.inherit-originatorrecurre al prompt del canal de origen (el comportamiento actual).
- A
approver_recipientausente o vacío hace que el aprobador no esté disponible. Sigue aon_no_approver: el valor predeterminadodenyfalla en modo cerrado, mientras queinherit-originatorpermite explícitamente el respaldo al canal de origen. timeout_secs(predeterminado 120) limita cuánto tiempo espera la compuerta al aprobador antes de aplicaron_no_approver, de modo que un canal de aprobador bloqueado no pueda detener un turno.
Cuando approval_route está ausente (el valor predeterminado), las aprobaciones se comportan exactamente como se describe arriba: se entregan a través del mismo canal que inició la conversación. El valor predeterminado de fallo cerrado significa que un aprobador mal configurado o inaccesible deniega en lugar de autoaprobar silenciosamente.
Alcance.
approval_routese respeta en ambas rutas de turno: la ruta interactiva, impulsada por canal (un turno que lleva un identificador de canal activo, p. ej. un chat de agente en streaming) y la ruta no interactiva que se ejecuta sin un canal de origen (despacho de chat/webhook de gateway y mensajes entre pares agente a agente). En la ruta no interactiva, el aprobador debe ser un canal activo y registrado en el daemon en ejecución (se resuelve a través del registro de canales del daemon); si ese registro no está disponible (por ejemplo, una ejecución única de CLI sin canales iniciados) o el aprobador nombrado no está activo, la puerta de control recurre al valor predeterminado no interactivo del perfil, que falla en cerrado (deniega) con el valor predeterminadoon_no_approver = "deny".
Los delegados agénticos independientes pueden usar la ruta explícita del perfil de riesgo de destino en la ejecución en primer plano, en segundo plano y en paralelo. Tanto el canal como el destinatario deben estar configurados. El hijo obtiene un gestor de aprobaciones nuevo, por lo que las concesiones de la sesión del llamador y el canal de cliente de origen no se heredan. Un aprobador no disponible falla en modo restrictivo (fail-closed) incluso con inherit-originator, porque el hijo no tiene canal de origen. Consulte Aprobaciones de delegados independientes para la configuración y la duración de las concesiones. Los delegados agénticos acotados conservan sus reglas de aprobación sin operador existentes.
Lista de permisos de comandos
Para la herramienta shell específicamente: si allowed_commands no está vacío, es estricto: cualquier comando no listado se bloquea. El validador de políticas de shell se encarga de la detección de patrones destructivos además de la lista de permitidos.
Reglas de ruta
workspace_only = true restringe las lecturas y escrituras a <workspace>/**, además de cualquier allowed_roots configurado para el modo de acceso solicitado. Las entradas de espacio de trabajo absoluto, raíz permitida y forbidden_paths usan prefijos de componentes de ruta. Cuando coincide más de una entrada, prevalece el prefijo más específico; una entrada prohibida gana en caso de empate a la misma profundidad. Por tanto, un subárbol prohibido puede bloquear parte del espacio de trabajo o de una raíz permitida, mientras que un permiso de operador restringido puede seguir utilizándose bajo una raíz prohibida predeterminada amplia, como /home o /tmp.
Las comprobaciones de archivos resueltos comparan todas las entradas coincidentes después de resolver los alias del sistema de archivos, por lo que especificar un subárbol prohibido mediante un enlace simbólico no elude la denegación. Estas son reglas de prefijo absoluto: no proporcionan coincidencia con patrones glob ni la semántica de patrones de exclusión relativos al espacio de trabajo.
Sandbox
Los campos de sandboxing a nivel de SO residen en el mismo perfil de riesgo. Consulte Sandboxing para la selección de backend por SO.
Paso de entorno
La herramienta de shell se ejecuta en un entorno mínimo de forma predeterminada; exponga variables de entorno específicas mediante el perfil de riesgo. Los secretos (patrones API_KEY, _TOKEN, _SECRET, _PASSWORD) nunca se pasan automáticamente; enumérelos explícitamente u obténgalos del almacén de secretos dentro del comando.
Autonomía más estricta por canal
La autonomía es por agente, no por canal. Para ejecutar un canal de cara al público con un nivel más estricto que tu agente principal, define un segundo agente vinculado a un perfil de riesgo más estricto y dirige ese canal hacia él. El excluded_tools por canal (channels.<type>.<alias>.excluded_tools) es la opción más económica cuando solo necesitas ocultar herramientas individuales, sin necesidad de un segundo agente.
Observabilidad
Las solicitudes de aprobación, concesiones, denegaciones y tiempos de espera emiten eventos estructurados a través del crate infra:
INFO autonomy:aprobación_solicitada herramienta=file_write ruta=/tmp/foo.txt canal=discord usuario=alice
INFO autonomy:aprobación_concedida herramienta=file_write ruta=/tmp/foo.txt canal=discord usuario=alice
WARN autonomy:tiempo_de_espera_excedido herramienta=shell comando="git push" canal=telegram usuario=bob
WARN autonomy:bloqueado herramienta=shell comando="rm -rf /tmp" motivo="patrón prohibido"
Las llamadas bloqueadas, las denegaciones y los timeouts merecen auditoría, pero no son recibos de herramienta. Emiten eventos de observabilidad; los recibos de herramienta se adjuntan a resultados exitosos de herramientas cuando los recibos están habilitados.
¿Por qué no simplemente un “modo seguro” binario?
Porque el punto intermedio útil es amplio. Un usuario que quiere que los agentes ejecuten scripts automáticamente pero que no hagan push a master necesita algo entre “todo está permitido” y “nada está permitido”. La autonomía de tres niveles + las anulaciones por herramienta + las listas de comandos permitidos ofrecen ese control sin fragmentar la configuración.