Agentic Pipelines
TL;DR
En la introducción repasé de manera diagonal cómo orquestar steps secuenciales, paralelos y todos los tipos de condiciones de arranque de Bitbucket Pipelines, donde incluimos nuestras líneas de script. Pues ahora existe una figura nueva, todavía en beta, denominada Agentic Pipelines, que nos permite incrustar un agente de IA dentro de un step para que ejecute tareas descritas en lenguaje natural. Entre sus capacidades se encuentran analizar código, abrir pull requests, fixear steps fallidos o generar documentación. Podemos elegir el proveedor del agente entre Rovo Dev (el que gestiona Atlassian), Claude Code (Anthropic) o Codex (OpenAI). En esta entrada me voy a centrar solo en Claude Code, pero es extensible para cualquiera de los mencionados anteriormente.
Al ser una característica en beta, la sintaxis y las capacidades pueden cambiar. Antes de nada hay que habilitarla en Workspace settings > Atlassian Integrations > Atlassian Intelligence activando Agentic Pipelines.
Qué es un agente dentro de un step
En lugar de escribir lineas en nuestra sección de script de nuestro step, le describimos al agente qué queremos que pase y es él quien decide cómo hacerlo. El agente se ejecutará en el contexto de un step normal y corriente, así que hereda todo lo que ya conocemos del artículo anterior, como la imagen de Docker, el checkout del repositorio, las caches o las variables de entorno. La única diferencia es que, donde antes teníamos una lista de comandos en script, ahora le pasamos un prompt.
Al agente lo declaramos dentro de la entidad definitions > agents y luego lo referenciamos desde el script del step con la clave agent. Voy a empezar por la estructura mínima que necesita Claude:
definitions:
agents:
mi-agente:
provider: claude
prompt: 'Explica qué hace este repositorio y resume su arquitectura.'
pipelines:
custom:
documenta:
- step:
name: Agente documentador
auth:
system:
scopes:
- read:repository:bitbucket
script:
- agent: mi-agenteLlegados a este punto, vamos a analizar qué responsabilidad tiene cada línea del código anterior:
- Con
providerelegimos el motor del agente. Si no decimos nada, por defecto esrovodev, así que para trabajar con Claude tenemos que fijarlo explícitamente. - En
promptva la tarea en lenguaje natural. Puesta inline como aquí está limitada a 2k caracteres, pero lo recomendable es sacarlo a un fichero aparte (por ejemplo a un comando de Claude). - La entidad
auth.system.scopeses exclusiva de este nuevo flujo agéntico. Cuando el step arranca, Bitbucket emite un token OAuth efímero con únicamente los permisos que declaremos aquí. El agente lo usa para conectarse con todo el ecosistema de Bitbucket. - Y por último, dentro del
script, en lugar de comandos, llamamos al agente por su nombre conagent: mi-agente.
El proveedor Claude
La autenticación contra Anthropic es bring-your-own-key. Le pasamos nuestra propia credencial de Claude como variable de Pipelines asegurada (secured), ya sea a nivel de workspace o de repositorio, y el proveedor la consume. Ojo, que a diferencia de Rovo Dev (que gestiona Atlassian), aquí el consumo de tokens del modelo va asociado a nuestra cuenta de Anthropic.
Cómo declarar el prompt
De manera rápida podemos usar el prompt inline (2k caracteres), pero para algo serio se nos queda corto. Con Claude tenemos tres maneras de dárselo:
- La primera, inline, es la que ya hemos visto (
prompt: "haz X"). - La segunda es externalizarlo a un fichero. Con el prefijo
!apuntamos a un.mdversionado en el repo,prompt: "!.claude/prompts/mi-tarea.md", y así el prompt vive en el control de versiones y lo podemos reutilizar y revisar como cualquier otro código. - Y la tercera, invocar un comando propio con
prompt: "/mi-comando $VARIABLE", que se resuelve contra.claude/commands/mi-comando.md. Es la vía natural si ya tenemos comandos de Claude Code en el repo, porque el mismo/mi-comandoque lanzamos en local desde la terminal lo lanza aquí el pipeline.
Además, si nos hace falta afinar el comportamiento del modelo sin tocar ningún fichero externo, tenemos la figura config.overrides dentro de la propia definición del agente:
definitions:
agents:
mi-agente:
provider: claude
prompt: '/documenta-modulo $BITBUCKET_BRANCH'
config:
path: .claude/settings.json
overrides:
model: opus
permissions:
deny: ['Bash(curl *)', 'Bash(git push *)']permissions acota al agente por un lado distinto al de auth.system.scopes. Los scopes dicen qué puede tocar de Bitbucket y permissions qué puede ejecutar dentro del step. Aunque le configuremos solo lectura, hay que recordar que el agente sigue teniendo una terminal.
Casos de uso
Una vez hemos repasado cómo programar nuestro primer pipeline agéntico, vamos con tres agentes interesantes para tener en un proyecto real. Las instrucciones de cada uno viven versionadas dentro de .claude/commands/ y el prompt del YAML se limita a decirle al agente que lo siga al pie de la letra.
Auditoría de seguridad semanal
La idea es pasar una revisión periódica sobre la rama estable. Una vez por semana el agente recorre el código buscando secretos hardcodeados, dependencias con CVE conocidas o endpoints sin autenticar. Abre una PR contra esa rama con el informe y demás aspectos contenidos en nuestro command. Es la tarea que más razonamiento pide de las tres, así que va con opus.
Al declararlo como custom no se dispara en cada push, y desde Repository settings > Pipelines > Schedules le asociamos el cron apuntando a la rama que queramos auditar. Como el objetivo es que abra PR, necesita escritura tanto de repositorio (para crear la rama con los cambios) como de pull request.
definitions:
agents:
security-audit:
provider: claude
config:
overrides:
model: opus
prompt: |
Follow the instructions in .claude/commands/ci-security-report.md exactly, in order.
pipelines:
custom:
weekly-security-audit:
- step:
name: Auditoría de seguridad semanal
auth:
system:
scopes:
- read:repository:bitbucket
- write:repository:bitbucket
- read:pullrequest:bitbucket
- write:pullrequest:bitbucket
script:
- agent: security-auditRellenar título y descripción de la PR
Un clásico... la PR se llama "update frontend" y la descripción está vacía. Este agente la reescribe a partir de los commits y del diff. Es un trabajo mecánico de resumen que no necesita mucho, así que tira de haiku, que es el más rápido y barato de los tres.
definitions:
agents:
pr-writer:
provider: claude
config:
overrides:
model: haiku
prompt: |
Follow the instructions in .claude/commands/ci-pr-metadata.md exactly, in order.
pipelines:
custom:
pr-metadata:
- step:
name: Rellena título y descripción de la PR
auth:
system:
scopes:
- read:repository:bitbucket
- read:pullrequest:bitbucket
- write:pullrequest:bitbucket
script:
- agent: pr-writerArreglar un step que ha fallado
El más "goloso" de los tres. Se lanza cuando un step falla, lee los logs del pipeline (de ahí el scope read:pipeline, que es el único sitio donde aparece), reproduce el error y propone la solución. Aquí sí le damos escritura sobre el repo, porque el objetivo es que abra una PR con el fix, y usamos sonnet como término medio entre coste y razonamiento.
definitions:
agents:
claude-fixer:
provider: claude
config:
overrides:
model: sonnet
prompt: |
Follow the instructions in .claude/commands/ci-fix-failed-step.md exactly, in order.
pipelines:
custom:
fix-failed-step:
- step:
name: Arregla el step que ha fallado
auth:
system:
scopes:
- read:repository:bitbucket
- write:repository:bitbucket
- read:pipeline:bitbucket
- read:pullrequest:bitbucket
- write:pullrequest:bitbucket
script:
- agent: claude-fixerLo más interesante de los tres ejemplos es que cada uno lleva su propio model. No hace falta pagar el modelo grande para que te escriban un título de PR, ni conformarse con el pequeño cuando toca revisar seguridad. Podemos personalizar nuestro agente depende del caso de uso, como haríamos en local.