¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Agentes de código en un pipeline de CI

Después de esta lección: Puedo diseñar un paso de pipeline para un agente de código con la aprobación de una persona antes de la fusión.

Lección de 65 min7 comandosLaboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

Qué es un paso de agente en CI

La integración continua (CI) ejecuta comprobaciones con cada cambio que se sube a un repositorio. Un equipo puede añadir un agente de código como un paso más, por ejemplo para corregir erratas en la documentación.

Importa porque nadie vigila un paso del pipeline mientras se ejecuta. Por eso sus límites, sus tests y la aprobación de una persona se escriben antes de que se ejecute por primera vez.

Al final de esta lección

Nota

Puedo diseñar un paso de pipeline para un agente de código con la aprobación de una persona antes de la fusión.

Palabras clave

PalabraQué significaEjemplo
Pipelinepasos que se ejecutan en orden con cada cambio
Permisoalgo que un paso tiene permitido hacerwrite-branch
Mínimo privilegiosolo los permisos que un paso necesita
Puerta de aprobaciónun punto donde una persona debe decir que sí
Registrolo que queda escrito de lo que hizo el paso

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Un paso de agente recibe los mínimos permisos

Un paso puede tener permiso para leer el código, escribir en una rama, escribir en la rama principal o leer los secretos del equipo. Un paso de agente necesita leer y escribir en una rama. Nunca necesita la rama principal ni los secretos.

También lista las carpetas que puede cambiar y un límite de tiempo. Un asterisco significa «cualquier cosa», que no es ningún límite.

Ejemplo resuelto: permisos de un paso de agente

PermisoPaso de agentePor qué
readSíTiene que leer el código
write-branchSíSu cambio va en una rama propia
write-mainNoSolo una fusión aprobada por una persona escribe en main
secretsNoUn secreto en un prompt se puede filtrar
puede cambiarSolo docs/Las carpetas que su tarea necesita
límite de tiempo30 minutos o menosUn agente atascado se detiene

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Tests, una persona y luego la fusión

Después del paso de agente, los tests se ejecutan otra vez en su rama. Luego una persona lee el cambio y lo aprueba, y solo entonces se hace la fusión.

El paso guarda un registro: la tarea que recibió, cada comando que ejecutó y cada archivo que cambió. Si algo sale mal un mes después, el registro cuenta lo que pasó.

Un error frecuente

Advertencia

Mucha gente cree que un agente en CI es seguro porque solo abre una rama. Un paso que puede leer secretos o subir a main todavía puede hacer daño. Dale los mínimos permisos y pon tests y una persona antes de cada fusión.

Escribe el ayudante del modelo, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Los tokens de una respuesta, o null si no trae ninguno.' 'function count(data, name) {' '  return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el ayudante del modelo, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' '  try {' '    const res = await fetch(base + \"/v1/chat/completions\", {' '      method: \"POST\",' '      headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' '      body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"estado \" + res.status);' '    const d = await res.json();' '    return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' '  } catch (error) {' '    console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' '    return { text: sample, inTokens: null, outTokens: null, recorded: true };' '  }' '}' 'module.exports = { ask };' >> model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el revisor de pipelines, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const pipelines = {' '  \"bot de docs\": [' '    { name: \"checkout\", kind: \"setup\", permissions: [\"read\"] },' '    { name: \"agente\", kind: \"agent\", permissions: [\"read\", \"write-branch\"], may_change: [\"docs/\"],' '      keeps_log: true, max_minutes: 20 },' '    { name: \"tests\", kind: \"test\", permissions: [\"read\"] },' '    { name: \"fusionar\", kind: \"merge\", permissions: [\"write-main\"], needs_approval: true },' '  ],' '  \"autoarreglos\": [' '    { name: \"agente\", kind: \"agent\", permissions: [\"read\", \"write-main\", \"secrets\"], may_change: [\"*\"],' '      keeps_log: false, max_minutes: 90 },' '    { name: \"fusionar\", kind: \"merge\", permissions: [\"write-main\"], needs_approval: false },' '  ],' '};' > ci.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el revisor de pipelines, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function stepProblems(s) {' '  const out = [];' '  if (s.permissions.indexOf(\"write-main\") >= 0) out.push(\"puede subir a main\");' '  if (s.permissions.indexOf(\"secrets\") >= 0) out.push(\"puede leer secretos\");' '  if (s.may_change.length === 0 || s.may_change.indexOf(\"*\") >= 0) out.push(\"puede cambiar cualquier cosa\");' '  if (s.keeps_log === false) out.push(\"no guarda registro\");' '  if (s.max_minutes > 30) out.push(\"dura demasiado\");' '  return out.map(function (p) { return s.name + \": \" + p; });' '}' >> ci.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el revisor de pipelines, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function problems(steps) {' '  let out = [];' '  let agent = false;' '  let tested = false;' '  steps.forEach(function (s) {' '    if (s.kind === \"agent\") { out = out.concat(stepProblems(s)); agent = true; tested = false; }' '    if (s.kind === \"test\") tested = true;' '    if (s.kind === \"merge\" && agent && tested === false) out.push(s.name + \": sin tests después del agente\");' '    if (s.kind === \"merge\" && agent && s.needs_approval === false) out.push(s.name + \": sin aprobación\");' '  });' '  return out;' '}' >> ci.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el revisor de pipelines, parte 4

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  Object.keys(pipelines).forEach(function (name) {' '    const found = problems(pipelines[name]);' '    console.log(name + \": \" + (found.length === 0 ? \"seguro\" : \"inseguro\"));' '    found.forEach(function (p) { console.log(\"  \" + p); });' '  });' '  const q = \"En una frase corta: ¿por qué una persona debe aprobar antes de fusionar un cambio de un agente?\";' '  const sample = \"Una persona ve lo que significa el cambio, algo que ni los tests ni el agente pueden juzgar.\";' '  const reply = await ask([{ role: \"user\", content: q }], sample, 60);' '  console.log(\"el modelo dijo: \" + reply.text);' '}' 'main();' >> ci.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejecuta el revisor de pipelines

Comando
docker exec -w /home/node/project agent node ci.js

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Lo que imprime el Run

LíneaLo que muestra
bot de docs: seguroMínimos permisos, tests y luego una aprobación
autoarreglos: inseguroSiete problemas listados debajo
agente: puede subir a mainPuede saltarse a cualquier persona
agente: puede leer secretosUn secreto en una instrucción se puede filtrar
agente: puede cambiar cualquier cosaNo hay lista de carpetas permitidas
agente: no guarda registroDespués nadie sabrá qué hizo
agente: dura demasiadoPasa del límite de tiempo
fusionar: sin tests después del agenteNada comprueba su cambio
fusionar: sin aprobaciónNadie dice que sí antes de la fusión
el modelo dijo: ...Una frase del laboratorio. Una línea de Muestra grabada si ningún modelo responde

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Sobre este laboratorio y su código: Laboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.