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
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Pipeline | pasos que se ejecutan en orden con cada cambio | |
| Permiso | algo que un paso tiene permitido hacer | write-branch |
| Mínimo privilegio | solo los permisos que un paso necesita | |
| Puerta de aprobación | un punto donde una persona debe decir que sí | |
| Registro | lo 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
| Permiso | Paso de agente | Por qué |
|---|---|---|
| read | Sí | Tiene que leer el código |
| write-branch | Sí | Su cambio va en una rama propia |
| write-main | No | Solo una fusión aprobada por una persona escribe en main |
| secrets | No | Un secreto en un prompt se puede filtrar |
| puede cambiar | Solo docs/ | Las carpetas que su tarea necesita |
| límite de tiempo | 30 minutos o menos | Un 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
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
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
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
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
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
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
docker exec -w /home/node/project agent node ci.jsSe 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ínea | Lo que muestra |
|---|---|
| bot de docs: seguro | Mínimos permisos, tests y luego una aprobación |
| autoarreglos: inseguro | Siete problemas listados debajo |
| agente: puede subir a main | Puede saltarse a cualquier persona |
| agente: puede leer secretos | Un secreto en una instrucción se puede filtrar |
| agente: puede cambiar cualquier cosa | No hay lista de carpetas permitidas |
| agente: no guarda registro | Después nadie sabrá qué hizo |
| agente: dura demasiado | Pasa del límite de tiempo |
| fusionar: sin tests después del agente | Nada comprueba su cambio |
| fusionar: sin aprobación | Nadie 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.