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
Sin puertas de aprobación; todas las llamadas a herramientas marcadas como bajas/medias/altas se ejecutan sin preguntar. workspace_only está implícitamente deshabilitado (el agente puede acceder a rutas fuera del workspace); forbidden_paths sigue bloqueando; el sandbox a nivel de SO (sandbox_enabled + sandbox_backend) sigue aplicándose.
Esto es adecuado para entornos de desarrollo local confiables, CI o SOPs que necesiten ejecutarse de extremo a extremo sin intervención humana. Si necesitas full + sin restricciones de espacio de trabajo + sin sandboxing, consulta modo YOLO.
Anulaciones por herramienta
auto_approve, always_ask y excluded_tools existen como listas planas de nombres de herramientas en el perfil de riesgo (no como tablas anidadas). excluded_tools también está disponible por canal (channels.<type>.<alias>.excluded_tools) para ocultar herramientas de 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
on_no_approver = "deny" # predeterminado; o "inherit-originator"
timeout_secs = 120 # predeterminado; acota 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.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).
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".
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.