Qué es un archivo de contexto
Un archivo de contexto es un archivo corto del repositorio que un agente de código lee antes de cada tarea. Dice cómo ejecutar los tests, qué convenciones sigue el equipo y qué no se toca.
Sin él, el agente aprende tu proyecto de nuevo en cada tarea y adivina el resto. Un buen archivo de contexto es corto, verdadero y seguro, y un script puede comprobar las tres cosas.
Al final de esta lección
Nota
Puedo escribir un archivo de contexto corto que diga a un agente de código cómo trabajar en un repositorio.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Archivo de contexto | notas fijas que un agente lee antes de cada tarea | AGENTS.md |
| Convención | una regla que el equipo siempre sigue | |
| Comando | una línea que escribes para ejecutar algo | npm run test |
| Ruta protegida | un archivo o carpeta que el agente no debe cambiar | |
| Límite de líneas | el máximo de líneas que puede tener el archivo |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
El contexto dice lo que el código calla
El código muestra lo que hace el programa. No muestra cómo trabaja el equipo. Un archivo de contexto tiene cuatro tipos de línea: los comandos para probar y ejecutar, las convenciones, las rutas protegidas y dónde está cada cosa.
opencode, el agente de este laboratorio, lee un archivo llamado AGENTS.md en la raíz del proyecto. Otros agentes leen archivos con otros nombres.
Ejemplo resuelto: qué líneas se quedan
| Línea | ¿Se queda? | Por qué |
|---|---|---|
| Ejecuta los tests con npm run test | Sí | Un comando que el agente necesita siempre |
| Los precios van en céntimos enteros | Sí | Una convención que el código no dice |
| No tocar: data/prices.json | Sí | Una ruta protegida |
| La tienda abrió en 2019 | No | Historia que el agente no necesita |
| total suma la cesta | No | El código ya lo dice |
| API_KEY=abc123 | No | Un secreto nunca va en el repositorio |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Corto, cierto y seguro
El agente lee cada línea en cada tarea, así que cada línea cuesta tiempo y espacio. Pon un límite de líneas, por ejemplo 40, y respétalo.
Una línea que ya no es cierta es peor que ninguna. Un comando que no existe manda al agente por mal camino. Una ruta que se ha movido no protege nada.
Un error frecuente
Advertencia
Mucha gente cree que un archivo de contexto más largo da mejor trabajo. Una regla en la línea 300 se pasa por alto fácilmente, tanto para un agente como para una persona. Mantén el archivo corto y comprueba que cada comando y cada ruta siguen existiendo.
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 repositorio y el revisor, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const fs = require(\"fs\");' 'const { ask } = require(\"./model\");' 'const NL = String.fromCharCode(10);' 'fs.mkdirSync(\"ctx-demo/data\", { recursive: true });' 'fs.mkdirSync(\"ctx-demo/src\", { recursive: true });' 'const pkg = { name: \"shop\", scripts: { test: \"node --test\", lint: \"node lint.js\" } };' 'fs.writeFileSync(\"ctx-demo/package.json\", JSON.stringify(pkg, null, 2));' 'fs.writeFileSync(\"ctx-demo/data/prices.json\", JSON.stringify({ manzana: 35, zumo: 85 }));' 'fs.writeFileSync(\"ctx-demo/src/shop.js\", \"module.exports = {};\" + NL);' > context.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 repositorio y el revisor, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const draft = [\"# Notas para agentes de código\", \"Ejecuta los tests con npm run test\",' ' \"Revisa el estilo con npm run lint\", \"Construye la web con npm run build\",' ' \"Los precios van en céntimos enteros, nunca con decimales.\", \"No tocar: data/prices.json\",' ' \"No tocar: secrets/keys.txt\", \"API_KEY=abc123 para el servidor de pruebas\"];' 'fs.writeFileSync(\"ctx-demo/AGENTS.md\", draft.join(NL) + NL);' >> context.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 repositorio y el revisor, parte 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const LIMIT = 40;' 'const lines = fs.readFileSync(\"ctx-demo/AGENTS.md\", \"utf8\").trim().split(NL);' 'const scripts = JSON.parse(fs.readFileSync(\"ctx-demo/package.json\", \"utf8\")).scripts;' 'const found = [];' 'if (lines.length > LIMIT) found.push(\"demasiado largo: \" + lines.length + \" líneas\");' >> context.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 repositorio y el revisor, parte 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'lines.forEach(function (line, at) {' ' const words = line.split(\" \");' ' const i = words.indexOf(\"run\");' ' const where = \"línea \" + (at + 1) + \": \";' ' if (i > 0 && words[i - 1] === \"npm\" && scripts[words[i + 1]] === undefined) found.push(where + \"no existe el script \" + words[i + 1]);' ' const path = line.slice(10);' ' if (line.indexOf(\"No tocar: \") === 0 && fs.existsSync(\"ctx-demo/\" + path) === false) found.push(where + \"no existe la ruta \" + path);' ' if (line.indexOf(\"KEY=\") >= 0 || line.toLowerCase().indexOf(\"contraseña\") >= 0) found.push(where + \"parece un secreto\");' '});' >> context.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 repositorio y el revisor, parte 5
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' console.log(\"AGENTS.md: \" + lines.length + \" líneas, límite \" + LIMIT);' ' found.forEach(function (one) { console.log(one); });' ' const q = \"En una frase corta: ¿por qué un archivo de contexto para un agente de código debe ser corto?\";' ' const sample = \"El agente lee cada línea en cada tarea, así que un archivo largo entierra las reglas importantes.\";' ' const reply = await ask([{ role: \"user\", content: q }], sample, 60);' ' console.log(\"el modelo dijo: \" + reply.text);' '}' 'main();' >> context.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 contexto
docker exec -w /home/node/project agent node context.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 |
|---|---|
| AGENTS.md: 8 líneas, límite 40 | El borrador es bastante corto |
| línea 4: no existe el script build | package.json no tiene un script build |
| línea 7: no existe la ruta secrets/keys.txt | La ruta protegida no existe |
| línea 8: parece un secreto | Una clave inventada, que debe salir |
| 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.