# Alcances API para agentes autónomos de programación que contienen el riesgo

Un agente autónomo de programación debe recibir una credencial para una tarea definida, no una credencial que casualmente haga desaparecer los errores. Lo difícil no es encontrar una etiqueta de alcance llamada `write`, sino demostrar que el token puede completar una tarea y fallar al intentar acciones cercanas que no le corresponden.

He visto a equipos empezar con un token personal porque el agente necesitaba «ponerse en marcha». Semanas después, ese token podía leer todos los repositorios que el desarrollador había tocado, modificar la configuración de despliegue y realizar solicitudes destructivas que la tarea original nunca requería. El agente no creó ese riesgo. Lo creó un límite de permisos aplicado con demasiada ligereza.

## Una tarea es más específica que un rol

Una tarea de agente describe un resultado y un conjunto limitado de cambios de estado. Un rol describe a una persona o un servicio en términos generales. Si concedes acceso a partir del rol, casi siempre otorgas más de lo que necesita la tarea.

Tomemos una solicitud como esta: «Actualiza una dependencia en el servicio de pagos, ejecuta el conjunto de pruebas y abre una solicitud de incorporación de cambios». El agente puede necesitar leer un repositorio, crear una rama, subir commits a esa rama y crear una solicitud de incorporación de cambios. Tal vez necesite acceso de lectura a los registros de compilación si el servicio de pruebas los expone mediante una API. No necesita administrar la organización, modificar las reglas de ramas protegidas, rotar credenciales de despliegue ni fusionar su propio trabajo.

Escribe los contratos de las tareas como verbos aplicados a recursos con nombre. No escribas «escritura del repositorio». Especifica lo que el agente puede hacer:

- Leer el código fuente, las incidencias y las solicitudes de incorporación de cambios existentes en `payments-service`.
- Crear y actualizar ramas cuyos nombres comiencen por `agent/`.
- Crear una solicitud de incorporación de cambios desde esa rama hacia la rama base designada.
- Leer el estado y los registros del flujo de trabajo iniciado por esa solicitud.
- Publicar un comentario con el resultado de las pruebas.

Esto no es burocracia. La lista deja al descubierto decisiones pendientes. ¿Puede el agente cerrar una incidencia? ¿Puede editar la solicitud de incorporación de cambios de otra persona? ¿Puede volver a ejecutar un flujo de trabajo costoso? ¿Necesita descargar un paquete de un registro privado? Cada verbo obtiene un permiso o se elimina.

Un contrato de tarea también distingue entre un efecto secundario necesario y uno conveniente. Un agente puede querer actualizar la etiqueta de una incidencia después de abrir una solicitud de incorporación de cambios. Puede resultar útil, pero no hace posible la actualización de la dependencia. Déjalo fuera del primer conjunto de permisos. Añádelo después, cuando alguien haya aceptado el efecto y probado el límite.

Trata los trabajos recurrentes como tareas independientes, aunque un mismo proceso de agente los ejecute. Una comprobación nocturna de dependencias, una promoción de versión y una reversión en producción tienen consecuencias diferentes. Una sola identidad con permisos acumulados hace que las tres tareas sean más difíciles de revisar e imposibles de revocar limpiamente.

## Los nombres de los alcances no son límites de permisos

Una cadena de alcance es una entrada para la autorización, no una prueba de que una llamada API sea segura. Los proveedores usan la palabra «alcance» para mecanismos distintos: cadenas OAuth, permisos de repositorio, roles de proyecto, concesiones de instalación y tokens limitados a una lista de recursos. No son intercambiables.

OAuth 2.0 RFC 6749 define el alcance como un conjunto de cadenas separadas por espacios que limita el acceso de un token. Deja deliberadamente el significado de cada cadena en manos del servidor de autorización. Esa flexibilidad resulta útil para los proveedores, pero significa que `repo:write`, `projects.write` y `api` no te dicen casi nada hasta que revisas la documentación de los endpoints del proveedor y pruebas el token.

RFC 8707 añade indicadores de recursos. Un cliente puede solicitar un token para un recurso protegido concreto, en lugar de tratar todos los endpoints situados detrás de un servidor de autorización como un único objetivo. Esto ayuda cuando el emisor lo admite. No corrige a un proveedor que asigna un único alcance amplio a todos los proyectos o a todos los endpoints destructivos de ese recurso.

Mantén separadas estas tres capas en tus notas de diseño:

| Capa | Pregunta que responde | Fallo si se confunde |
|---|---|---|
| Alcance del token | ¿Qué etiquetas de permisos colocó el emisor en este token? | Das por hecho que una etiqueta amigable representa una acción limitada. |
| Concesión del recurso | ¿A qué repositorios, proyectos, cuentas o entornos puede llegar esta identidad? | El token puede actuar sobre un recurso vecino. |
| Regla del endpoint | ¿Qué método y ruta aceptará la API para esta solicitud? | Un permiso de escritura permite borrar o administrar. |

La recomendación deficiente más habitual es «usa solo lectura más escritura». Es popular porque cabe en una guía de configuración y suele funcionar al primer intento. Es incorrecta porque la escritura suele cubrir varios verbos sin relación entre sí. Crear una solicitud de incorporación de cambios, borrar un repositorio, cambiar un webhook y modificar el control de acceso pueden depender del mismo permiso amplio.

Cuando un proveedor solo ofrece un alcance amplio, no finjas que has resuelto el mínimo privilegio con solo nombrarlo cuidadosamente. Limita la capa de recursos. Crea un repositorio, proyecto, entorno o cuenta de servicio dedicado con acceso únicamente al objetivo. Si el agente necesita una acción en producción, asígnale una identidad independiente para esa acción y exige aprobación explícita. El modelo general del proveedor seguirá siendo general, pero la credencial podrá llegar a menos sitios.

## Crea un registro de endpoints antes de emitir un token

Un registro de endpoints convierte una solicitud imprecisa en un diseño de permisos que se puede revisar. Registra cada llamada que el agente puede realizar, por qué la necesita, qué recurso puede tocar y qué permiso exacto la habilita.

Empieza por la secuencia de acciones, no por la página de permisos del proveedor. Un agente que abre una solicitud de incorporación de cambios suele necesitar más llamadas de las esperadas: lee la revisión base, crea una referencia, crea o actualiza archivos, obtiene el estado del flujo de trabajo y envía la solicitud. Una página de permisos rara vez indica cuál de ellas es esencial para el flujo que has elegido.

Usa un registro como este. Sustituye las rutas ilustrativas por las que documente realmente tu proveedor.

```yaml
task: update dependency and open pull request
resource: org/payments-service
calls:
  - method: GET
    path: /repos/org/payments-service/contents/package-lock.json
    purpose: read current dependency lockfile
    permission: contents:read

  - method: POST
    path: /repos/org/payments-service/git/refs
    constraint: "ref starts with refs/heads/agent/"
    purpose: create working branch
    permission: contents:write

  - method: PUT
    path: /repos/org/payments-service/contents/package-lock.json
    constraint: "branch starts with agent/"
    purpose: commit updated lockfile
    permission: contents:write

  - method: POST
    path: /repos/org/payments-service/pulls
    constraint: "base is main; head starts with agent/"
    purpose: request review
    permission: pull_requests:write

forbidden_calls:
  - DELETE /repos/org/payments-service
  - PATCH /repos/org/payments-service/branches/main/protection
  - POST /repos/org/organization-hooks
  - GET /repos/org/another-service/contents/secrets.yml
```

El campo `constraint` importa porque los permisos de los endpoints a menudo se quedan cortos frente a los permisos de la tarea. Una API puede permitir crear ramas sin ofrecer una restricción nativa al prefijo `agent/`. Registra esa carencia. Tal vez necesites un servicio intermediario de acciones, un repositorio independiente o una puerta de revisión, porque un alcance no puede imponer la regla de ramas que quieres.

No confíes en una instrucción del agente para mantener intactas las restricciones. Una instrucción puede describir el prefijo previsto de la rama, pero no puede rechazar una solicitud enviada a `main`. El punto de control debe ser el proveedor de la API, la configuración del recurso objetivo o una pasarela de acciones que compruebe la solicitud antes de enviarla.

El registro debe incluir las llamadas de lectura con la misma seriedad que las de escritura. Leer un secreto de despliegue, una exportación de clientes, un aviso de seguridad o un segundo repositorio puede exponer más que un commit incorrecto. La mayoría de las revisiones de permisos concentran toda la atención en las escrituras porque son visibles. La ventana de contexto del agente también hace peligrosas las lecturas amplias.

## Separa el acceso para descubrir del acceso para modificar

El acceso de descubrimiento y el acceso de modificación normalmente deberían usar credenciales distintas, porque un agente necesita contexto amplio con más frecuencia de la que necesita autoridad amplia para cambiar el estado.

Un agente de planificación puede necesitar buscar código, revisar incidencias, examinar resultados de compilación y comparar versiones en varios repositorios. Un agente que aplica parches puede necesitar escribir solo en una rama de un repositorio. Si ambos trabajos comparten un token, el agente que aplica parches hereda la amplia superficie de lectura del planificador y el planificador hereda una capacidad de escritura que nunca necesita.

Divide el trabajo en etapas cuando el proveedor lo permita. La etapa de descubrimiento produce un plan limitado o una propuesta de parche. Un segundo proceso recibe ese artefacto y una credencial más restringida para realizar la modificación solicitada. Una persona puede revisar la transferencia cuando el cambio afecta a una zona protegida.

Esta separación detecta un fallo práctico que las instrucciones no pueden corregir. Supón que un planificador busca referencias a un paquete en una organización y encuentra un repositorio interno antiguo con notas de despliegue. Si el mismo token puede subir cambios a cada resultado que leyó, una llamada de herramienta equivocada podría modificar después el repositorio incorrecto. El modelo puede entender perfectamente la tarea y aun así seleccionar el identificador equivocado. Restringir al escritor al repositorio previsto convierte ese error en una solicitud rechazada.

No dividas tokens solo para crear más tokens. Divídelos cuando difieran el conjunto de recursos o los verbos permitidos. Un único token de lectura puede servir para una investigación coherente. Un único token de escritura puede servir para ediciones estrechamente relacionadas dentro de un objetivo. La idea es que la respuesta de cada token a «¿qué puede hacer este proceso?» sea lo bastante breve para que un ingeniero pueda verificarla sin adivinar.

En el control de código fuente, separa la autoridad para escribir en ramas de la autoridad para fusionar siempre que el proveedor lo permita. Una rama es un cambio propuesto. Una fusión cambia la base compartida y a menudo activa despliegues, versiones o automatización posterior. El agente puede abrir una solicitud de incorporación de cambios útil sin recibir permiso para fusionarla.

## Limita el recurso antes de perfeccionar el alcance

Un alcance limitado unido a una credencial de toda la organización suele ser peor que un alcance amplio unido a un objetivo aislado y desechable. El alcance controla los verbos. Los límites de recursos controlan dónde se aplican esos verbos. Necesitas ambos, pero los límites de recursos suelen hacer que los errores sean asumibles.

Asigna a los agentes autónomos identidades de servicio en lugar de tokens personales. Los tokens personales de acceso suelen heredar las antiguas pertenencias de una persona, concesiones temporales de administración y acceso a proyectos que nadie recordó durante la configuración. Revocar uno más tarde también puede interrumpir trabajos no relacionados, lo que hace que los equipos pospongan la revocación. Así es como las excepciones temporales se convierten en acceso permanente.

Una identidad dedicada debe comenzar sin acceso y recibir únicamente las concesiones de recursos enumeradas en el registro de endpoints. Si un agente trabaja en un repositorio, concédele ese repositorio en lugar de toda la organización. Si actualiza un despliegue de pruebas, concédele el entorno de pruebas en lugar de todos los entornos. Si escribe registros para una cuenta de cliente, concédele esa cuenta en lugar de una credencial API global.

Usa objetivos que no sean de producción para probar los permisos. Probar un token realizando escrituras reales en producción te enseña si funciona, pero no demuestra que esté limitado adecuadamente. Un repositorio o proyecto de prueba te permite ejercitar la creación, actualización, fallo, revocación y auditoría sin dejar trabajo de limpieza en un sistema activo.

El aislamiento de recursos también compensa las API con modelos de alcance poco afortunados. Algunos servicios emiten un token que tiene un único alcance `api` sin granularidad por endpoint. Aun así, puedes crear un proyecto dedicado que contenga solo los recursos sobre los que el agente puede actuar, denegarle la administración de la organización y usar una identidad distinta para cada entorno. Es menos elegante que una API de granularidad fina, pero mucho mejor que entregar un token universal a un proceso que construye solicitudes dinámicamente.

No des acceso a producción a un agente solo porque el código que modifica llegue finalmente a producción. El sistema de versiones debe encargarse de esa transición mediante una ruta aprobada y autorizada por separado. Si la tarea incluye realmente una operación en producción, escribe un contrato independiente para ella. Debe indicar el entorno objetivo, el método permitido, los parámetros admisibles, el comportamiento de reversión y la persona que la aprueba.

## Prueba el éxito y la denegación como un mismo contrato

Un conjunto de permisos está incompleto hasta que demuestras dos cosas: el agente puede terminar el trabajo asignado y las acciones cercanas que no se le asignaron fallan. Probar solo el camino exitoso demuestra comodidad. No dice nada sobre la contención.

Usa una identidad de prueba limpia para cada cambio de permisos. Las credenciales existentes suelen tener concesiones almacenadas, roles heredados o una segunda vía de autenticación que hace que una prueba parezca exitosa por el motivo equivocado. Registra el sujeto del token, los recursos previstos, los alcances emitidos y la caducidad antes de la ejecución.

Una secuencia práctica de pruebas es esta:

1. Crea un recurso de prueba desechable y una credencial con las concesiones propuestas.
2. Ejecuta el agente o una plantilla determinista de solicitudes mediante todas las llamadas permitidas del registro.
3. Comprueba el estado esperado, como una rama, una solicitud de incorporación de cambios, un comentario o un registro actualizado.
4. Envía cada llamada prohibida con la misma credencial y espera una denegación.
5. Elimina la credencial o revoca la sesión, vuelve a ejecutar una llamada antes permitida y espera una denegación.

Usa solicitudes directas además de una ejecución del agente. Las solicitudes directas eliminan la incertidumbre de la selección de herramientas y muestran si el propio proveedor aplica el límite. Esta plantilla de shell ilustra la estructura de la prueba. Supone una API que devuelve JSON y utiliza `403` para una identidad autenticada que carece del permiso.

```sh
base="https://api.example.internal"
auth="Authorization: Bearer $AGENT_TOKEN"

curl -sS -o allowed.json -w "%{http_code}\n" \
  -H "$auth" \
  -X POST "$base/repos/acme/payments-service/pulls" \
  -H "Content-Type: application/json" \
  -d '{"head":"agent/dependency-bump","base":"main","title":"Update parser"}'
# Expected output: 201

curl -sS -o denied.json -w "%{http_code}\n" \
  -H "$auth" \
  -X DELETE "$base/repos/acme/payments-service"
# Expected output: 403

cat denied.json
# Expected shape: {"message":"Resource not accessible by integration"}
```

No afirmes solo el código de estado. Inspecciona el estado resultante de las operaciones permitidas. Algunas API aceptan una solicitud y la procesan de forma asíncrona, o devuelven éxito mientras ignoran un campo del que dependía el agente. En las denegaciones, distingue `401` de `403`. Un `401` puede significar que la credencial de prueba está mal formada o ha caducado. Un `403` después de una autenticación correcta demuestra mejor que la autorización bloqueó la llamada. Los proveedores tienen comportamientos distintos, así que documenta su semántica en la plantilla.

Conserva una prueba negativa para cada límite de permisos peligroso. Si un agente puede crear un despliegue, prueba que no puede promocionarlo. Si puede comentar una incidencia, prueba que no puede editar sus etiquetas o asignados. Si puede escribir el valor de un secreto de pruebas, comprueba que no pueda volver a leerlo si la API permite escribir sin leer. Estas pruebas impiden que una modificación posterior del alcance amplíe el acceso silenciosamente.

## Un 403 fallido debe cambiar la tarea o la concesión

Una respuesta `403 Forbidden` aporta información sobre el contrato. Debe provocar una decisión, no una solicitud automática del permiso más amplio del proveedor.

He visto este patrón de fallo muchas veces. Un agente crea una rama y confirma una corrección, pero recibe una denegación al intentar abrir una solicitud de incorporación de cambios. Alguien descubre que el permiso para solicitudes de incorporación de cambios también permite descartar revisiones o editar conversaciones de forma más amplia. Lo concede porque el agente tiene que terminar. Unos días después, el mismo agente empieza a «limpiar» solicitudes antiguas y modifica trabajo que no formaba parte de su encargo.

La primera denegación contenía una cuestión de diseño: ¿abrir una solicitud de incorporación de cambios requiere esa capacidad más amplia y puede el equipo aceptar sus efectos secundarios? Hay varias respuestas honestas:

- Concede el permiso después de probar toda su superficie de endpoints y registrar el riesgo aceptado.
- Cambia la tarea para que el agente prepare una rama y una persona abra la solicitud de incorporación de cambios.
- Usa otra identidad del proveedor o un recurso donde la concesión amplia solo alcance al repositorio previsto.
- Coloca un servicio de acciones limitado delante de la API del proveedor, que acepte únicamente una solicitud de creación de solicitud de incorporación de cambios con restricciones fijas de recurso y rama.

La respuesta equivocada es añadir todos los alcances que convierten las respuestas rojas en verdes. Eso transforma los errores de autorización en incidentes retrasados.

Los cuerpos de las solicitudes también merecen atención. Muchos modelos de permisos API autorizan un endpoint, pero no distinguen entre valores seguros y perjudiciales. `POST /deployments` puede aceptar `staging` y `production` con el mismo permiso. `PATCH /projects/{id}` puede permitir una actualización inofensiva de la descripción y un cambio dañino de visibilidad. Si el proveedor no puede separar esas operaciones, el límite debe situarse por encima del endpoint. Exige aprobación humana, usa un objetivo dedicado o expón una operación diseñada para ese fin en lugar de acceso a la API sin restricciones.

Registra la llamada denegada en el registro junto con el motivo por el que la añadiste o la rechazaste. Seis meses después, ese registro explicará por qué el agente puede crear una rama pero no cambiar el nombre de un repositorio. Sin él, alguien considerará arbitrario el límite y lo ampliará durante una corrección apresurada.

## Las puertas de aprobación controlan las llamadas de mayor consecuencia

Los permisos limitados del proveedor reducen lo que un agente puede intentar. Las puertas de aprobación ayudan con las acciones permitidas que aún merecen una decisión humana, como una operación de pago externo, un comando SSH en un host importante o una escritura contra un servicio de producción.

No uses la aprobación como excusa para dar al agente credenciales amplias. Una confirmación de un clic puede detener una solicitud claramente incorrecta, pero las personas aprueban rápidamente tarjetas repetitivas, sobre todo cuando un agente necesita varias llamadas rutinarias para terminar un trabajo. El límite de permisos debe rechazar categorías completas de acciones antes de que aparezca una tarjeta de aprobación.

Usa la aprobación cuando el contexto humano cambie la decisión. Un despliegue puede estar técnicamente autorizado, pero resultar inadecuado durante un incidente. Una solicitud para borrar una rama puede estar permitida, pero ser incorrecta si otro ingeniero la está usando. El aviso de aprobación puede mostrar el objetivo real y la acción solicitada justo cuando la persona puede juzgarlos.

Sallyport guarda las credenciales API y SSH en su bóveda cifrada de macOS y ejecuta la acción solicitada sin exponer el secreto al agente. La autorización de sesión y los controles de aprobación por credencial pueden poner a una persona delante de las llamadas que lo merecen, pero el diseño de los alcances del proveedor sigue determinando hasta dónde puede llegar una credencial aprobada.

Conserva registros de auditoría que respondan a dos preguntas distintas: qué proceso de agente recibió permiso para actuar y qué llamadas API individuales realizó. Son registros diferentes. La aprobación de un proceso demuestra que una persona permitió que esa ejecución usara una credencial; no explica si la ejecución creó una solicitud de incorporación de cambios, cambió una variable de entorno o intentó borrar algo sin éxito. Revisa ambos registros después de un cambio de permisos y después de un incidente.

## Las revisiones de alcances necesitan un desencadenante, no una promesa de calendario

Las revisiones de permisos funcionan cuando las activa un evento de ingeniería. Un recordatorio trimestral impreciso suele encontrar tokens antiguos cuando nadie recuerda para qué servían. Vincula la revisión a cambios de tareas, nuevos endpoints, ampliaciones de recursos, cambios de permisos del proveedor y modificaciones del flujo de trabajo del agente.

Mantén el registro de endpoints junto al código que invoca al agente. Cuando una solicitud de incorporación de cambios modifique las instrucciones de herramientas del agente o añada una llamada API, exige actualizar el registro y sus pruebas positivas y negativas. Así, la decisión sobre los permisos queda junto al comportamiento que los necesita.

Revisa la revocación antes de necesitarla. Elimina una credencial de prueba y confirma que una solicitud antes permitida falla. Desactiva la identidad de servicio y confirma que un agente en ejecución no puede continuar mediante una sesión almacenada en caché. Comprueba si el proveedor ha emitido tokens de actualización o credenciales duplicadas que mantienen vivo el mismo acceso. Los equipos suelen descubrir estas rutas durante un incidente, cuando la respuesta resulta menos útil.

Presta atención a la acumulación de permisos en los cambios pequeños. Una solicitud para leer registros de flujos de trabajo puede convertirse en permiso para volver a ejecutar trabajos. Una solicitud para actualizar una incidencia puede convertirse en administración de incidencias de toda la organización. Una solicitud para acceder a un entorno puede convertirse en un respaldo de producción «por si acaso». Cada llamada nueva debe superar la misma pregunta: ¿puede el agente terminar su tarea declarada sin ella?

Si la respuesta es no, añade la concesión más pequeña que habilite la llamada y agrega una prueba de denegación alrededor de su vecino perjudicial más cercano. Si la respuesta es sí, déjala fuera. Esa disciplina hace que los fallos del agente sean más visibles a corto plazo. También impide que una instrucción mal formada, un modelo confundido o un proceso comprometido herede una autoridad que nadie pretendía conceder.
