El oficio y la máquina: el ingeniero de software en la era de la IA

8 · Diseñar para humanos es diseñar para agentes19 min read

Teoría — Diseñar para humanos es diseñar para agentes

El proyecto de la Confederación dejó a Vega el mejor espejo que había tenido de su propio código: donde había plano, la Cuadrilla voló; donde había barro, se hundió — como los humanos, pero más rápido. Esta teoría convierte ese espejo en método. Es la sección más práctica del curso: el flujo de trabajo completo que Vega usó, con los comandos y patrones reales, para que salgas de aquí capaz de montarlo en tu Claude Code — o en Codex, u OpenCode — mañana por la mañana.

La legibilidad ya no es una opinión

Empecemos por la tesis que da título a la sección. Durante décadas defendimos el código limpio con un argumento social: sé amable con el compañero que vendrá después. Era verdad, y era fácil de posponer — el compañero tardaba meses en llegar y protestaba poco. El capítulo 7 muestra el giro: el compañero ya está aquí, lee a máquina, trabaja de noche y se cree todo lo que el código le dice. Un agente rinde en proporción directa a lo que el código comunica: fronteras claras que le permiten razonar localmente, nombres honestos que no le mienten (la palabra total con tres significados le hizo elegir, con toda la razón estadística, la que no era), tests rápidos que le sirven de sentidos, tamaños de fichero que caben en una ventana de contexto sin degradarla. Todo el canon — cohesión, acoplamiento bajo, nombres intencionales, módulos pequeños — se convierte en interfaz de la automatización: la arquitectura es ahora, literalmente, el API por el que las máquinas consumen tu sistema. Y eso tiene un corolario que Nadia formuló como gratitud: la legibilidad se puede observar. Donde tus agentes pierden el norte, hay deuda; sus fracasos son la auditoría de arquitectura más barata de la historia. La respuesta correcta a esa auditoría tampoco es nueva: en Vega fue estrangular (construir lo nuevo en un módulo limpio y vaciar el viejo función a función, cada una con sus tests de caracterización antes de moverla — el patrón strangler fig de toda la vida), no reescribir. Los agentes no cambian la doctrina de gestión de legacy; le quitan las excusas.

El flujo completo: explorar → planificar → ejecutar → revisar

El error de principiante con un agente es el «hazme la integración entera» — lo que Mitchell Hashimoto (creador de Terraform y Ghostty, hoy uno de los practicantes serios más documentados del desarrollo agéntico) llama intentar «dibujar el búho» en una mega-sesión. El flujo que funciona, y que la documentación de buenas prácticas de Claude Code codifica, es el que Nadia aplicó: fases separadas, cada una con su propósito.

1. Explorar. Antes de escribir nada, una sesión donde el agente lee — el pliego, el código afectado, los documentos de diseño — y produce un análisis: qué toca dónde, qué riesgos, qué no entiende. Tú corriges ese análisis (recuerda: confundía dos tipos de contador, y solo Tomás lo sabía — la teoría no delegable de la sección 3 aparece exactamente aquí). Coste: minutos. Valor: todo lo demás se apoya en esto.

2. Planificar. Del análisis corregido, un plan por escrito: tareas del tamaño de una tarde, cada una con su criterio de «hecho» verificable — no «mejorar la validación» sino «make test-all pasa incluyendo los 12 casos nuevos del formato F-3». Los agentes modernos traen modo de planificación explícito (en Claude Code, un modo que se compromete a no tocar nada mientras planifica); úsalo, y revisa el plan como revisarías el de un compañero. Es más barato discutir un plan que deshacer una implementación.

3. Ejecutar. Ahora sí: tarea a tarea, con los tests primero cuando aporte, y con gestión deliberada del contexto. La restricción de fondo la resume la propia documentación, traducción propia: «casi todas las buenas prácticas derivan de una restricción: la ventana de contexto se llena rápido, y el rendimiento se degrada a medida que se llena». De ahí los dos comandos que deberías usar como respiración: /clear (contexto a cero entre tareas que no comparten nada — la sesión-vertedero donde conviven el bug de ayer y la feature de hoy es el antipatrón número uno) y /compact (resume el historial y sigue — para sesiones largas que sí necesitan su pasado, idealmente en los valles naturales entre subtareas). Y de ahí también los worktrees paralelos: git worktree add te da copias del repositorio en directorios distintos, cada una con su rama, de modo que varios agentes trabajen a la vez sin pisarse — el equivalente exacto de los contenedores aislados de la Cuadrilla, con git de árbitro.

4. Revisar. Doble anillo, y fíjate en que la regla del reparto de la sección 5 también parte en dos la revisión. El primer anillo es determinista y ya lo tienes: los sentidos del arnés (tests, linter, tipos, escáneres) en CI — todo lo que una regla fija puede comprobar, comprobado por reglas fijas, bloqueando por igual a agentes y humanos. Pero hay una mitad de la revisión que ningún linter alcanza, porque exige juicio: ¿este cambio cumple los acuerdos de la casa? ¿Respeta la frontera que el ADR-001 declaró intocable? ¿Sigue las convenciones de diseño del equipo — dónde van las invariantes, qué módulo puede hablar con cuál? ¿La spec se cumplió en espíritu o solo en letra? Esa revisión de conformidad — contra la spec, contra el AGENTS.md, contra los ADRs — es exactamente la revisión que los equipos siempre quisieron hacer y casi nunca hacían por falta de tiempo, y es delegable: es el segundo anillo, la revisión cruzada del capítulo — el patrón writer/reviewer: un agente escribe; otro agente distinto, con contexto limpio, con las reglas de la casa cargadas y con instrucciones de desconfiar revisa el diff contra la spec y contra los acuerdos, y señala lo dudoso. Y como es un paso más del flujo, puede ejecutarse también como job de CI en cada pull request — el agente revisor en modo no interactivo, publicando sus hallazgos como comentario del PR —, con un matiz de reparto que importa: el anillo determinista bloquea (sus veredictos son fiables por construcción); el revisor agéntico, que es no determinista, informa y exige respuesta — sus hallazgos se atienden o se refutan, pero un juicio probabilístico no debería ser la única llave de un merge. Esa asimetría — el revisor no carga con el historial mental del escritor, no «sabe» por qué el código debería estar bien — es la misma razón por la que la revisión humana funciona, y en su variante más dura (revisión adversarial: «encuentra razones por las que este cambio está mal») caza una clase de errores que la relectura del autor no caza jamás. Como dijo Tomás: dos aprendices repasándose las soldaduras — no sustituye tu ojo; te lo ahorra para donde hace falta.

Y el tercer anillo eres tú, y no es opcional. Aquí el consenso de los practicantes serios es unánime y conviene citarlo textual. Simon Willison: «I won't commit any code to my repository if I couldn't explain exactly what it does to somebody else» — no committeo código que no pudiera explicarle exactamente a otra persona (traducción propia). Hashimoto, tras describir cómo una funcionalidad no trivial de Ghostty fue escrita en gran parte por un agente: «Please don't ever ship AI-written code without a thorough manual review» — por favor, no enviéis jamás código escrito por IA sin una revisión manual concienzuda (traducción propia). Leerlo todo, línea a línea, como leía Tomás. Si esto te parece que anula la ganancia de velocidad, revisa la cuenta: la velocidad del flujo agéntico viene de paralelizar la escritura y automatizar la verificación mecánica, no de saltarse la comprensión — saltársela es fabricar deuda de comprensión, la más cara de todas, porque se paga el peor día posible y con la teoría ya muerta (sección 3, siempre la sección 3).

La caja de herramientas: subagentes, skills, hooks, comandos

El flujo anterior se apoya en piezas concretas del arnés moderno. Vocabulario mínimo, herramienta por herramienta, con su criterio de uso:

  • Subagentes: agentes hijos con contexto propio y limpio que el agente principal lanza para tareas acotadas («explora el módulo de facturación y resume sus invariantes»). Su gracia es doble: paralelismo, y protección del contexto del padre — el hijo se traga las dos mil líneas y devuelve el párrafo. El patrón writer/reviewer se monta con ellos.
  • Comandos slash propios: prompts parametrizados y versionados en el repositorio (en Claude Code, ficheros markdown en .claude/commands/) que empaquetan flujos del equipo — /revisar-driver, /preparar-release. Son la respuesta a «este prompt bueno lo tengo en un stickie»: al repositorio, como todo.
  • Skills: paquetes de instrucciones y recursos (formato abierto: un directorio con un SKILL.md) que el agente carga cuando la tarea lo pide, en vez de engordar el contexto siempre — la respuesta modular al fichero hinchado de la sección 5. Una skill de «cómo se escriben migraciones aquí» solo ocupa contexto cuando hay migraciones de por medio.
  • Hooks: puntos de intercepción determinista — «antes de cada edición, ejecuta el formateador», «prohíbe tocar facturacion/ salvo rama autorizada». La diferencia crucial con pedirlo en el prompt: el hook es código, se cumple siempre, no depende de que el modelo se acuerde. Aquí manda la regla del reparto de la sección 5, en su versión completa: lo determinista ni siquiera necesita ser un hook del agente — la suite en un git hook de pre-commit, la revisión bloqueante en el push, el escáner de secretos y el auditor de dependencias en CI se ejecutan siempre, se lo digas o no al modelo, y frenan por igual al agente y al humano que edita a mano. Reserva los hooks del agente para lo específico de la sesión (formateo al vuelo, protecciones de rutas), deja las barreras universales en la infraestructura git/CI de siempre, y no gastes ni una línea de prompt en pedir lo que un mecanismo ya impone.

Para que nada de esto quede en abstracto, los dos artefactos concretos en Claude Code. Un subagente se define como un fichero markdown versionado en .claude/agents/ — este es un revisor adversarial mínimo y real:

---
name: revisor
description: Revisa diffs contra la spec y las reglas de la casa,
  con mandato adversarial. Usar tras cada tarea, antes de abrir PR.
tools: Read, Grep, Glob, Bash
---
Eres un revisor desconfiado. Recibes un diff y la spec de la tarea.
Lee primero AGENTS.md y los ADRs de docs/adr/. Tu trabajo es
encontrar razones por las que el cambio está MAL, en dos frentes:
(a) corrección — casos límite sin cubrir, contratos rotos,
desviaciones de la spec, tests que no prueban lo que dicen;
(b) conformidad — incumplimientos de las reglas de la casa y de
los ADRs vigentes: fronteras de módulos que no deben cruzarse,
convenciones de diseño, zonas declaradas intocables.
No pierdas tiempo en lo que el linter ya comprueba. Informa cada
hallazgo con fichero, línea, severidad y la regla o ADR que
incumple. No arregles nada: señala.

Con eso, el patrón writer/reviewer es literalmente pedible («implementa la tarea F-08 y pásale el diff al subagente revisor antes de darla por hecha»), y el revisor arranca con contexto limpio cada vez — que es lo que le da valor. Y los hooks del agente viven en la configuración del proyecto (en .claude/settings.json), donde declaras comandos que se ejecutan en eventos del ciclo (antes o después de usar herramientas, por ejemplo «tras cada edición de *.py, ejecuta el formateador») — consulta la referencia de tu versión para la sintaxis exacta, y recuerda el criterio: ahí lo específico de sesión; lo universal, en git/CI. Para el paralelismo, el comando es el de git de siempre: git worktree add ../azud-f08 -b feature/f08 te da la copia aislada donde lanzar el segundo agente sin que pise al primero.

La misma lógica existe en el resto del ecosistema con otros nombres (Codex y OpenCode tienen sus equivalentes de contexto, comandos y políticas; AGENTS.md es la capa común); el mapa conceptual — contexto versionado, flujos empaquetados, política como código — es portable aunque la sintaxis no lo sea.

Multiagente en serio, y el «loop engineering»

Cuando el trabajo crece, los patrones de orquestación de la sección 4 (aquellos cinco de Building Effective Agents) se vuelven arquitectura de equipos de agentes: orquestador-trabajadores (un agente trocea y reparte a N paralelos — el proyecto de la Confederación), generador-evaluador (writer/reviewer institucionalizado; las notas de Anthropic sobre arneses de larga duración lo señalan como palanca fuerte: «separar al agente que hace el trabajo del agente que lo juzga», traducción propia), y su combinación planificador + generador + evaluador.

Y la pregunta que casi nadie se hace en voz alta: ¿cuándo compensa multiplicar agentes? Los motivos subyacentes son tres, y conviene tenerlos explícitos porque la tentación de sobre-orquestar es tan real como la de sobre-abstraer. Uno, independencia: hay piezas genuinamente paralelizables — módulos sin dependencias entre sí, investigaciones de varias fuentes, N ficheros que migrar con la misma receta. Si las piezas se pisan, el paralelismo es una fábrica de conflictos. Dos, protección del contexto: una tarea de mucha lectura (destripar un módulo de dos mil líneas, leer un pliego de cuarenta páginas) se delega a un subagente que se traga las dos mil líneas y devuelve el párrafo — el contexto del agente principal, que es tu recurso escaso (sección 4), queda intacto. Tres, independencia de juicio: el revisor vale precisamente porque no comparte el contexto del escritor — la separación de agentes es aquí el mecanismo que fabrica la mirada limpia. Y el contra-criterio, igual de importante: delegar tiene sobrecoste — cada subagente arranca amnésico y hay que redactarle un encargo autocontenido (paths, restricciones, formato de respuesta), esperar, y leer su informe. Para trabajo pequeño, secuencial o que necesita el contexto completo de la conversación, un solo agente bien llevado gana siempre. La señal de que te has pasado de frenada: pasas más tiempo redactando encargos y consolidando informes que revisando resultados. Como con los microservicios — el paralelo es exacto —, la topología multiagente se adopta cuando el problema la pide, no porque exista. Y para los proyectos que exceden cualquier sesión — días de trabajo autónomo — está cuajando lo que la prensa técnica llama loop engineering (término en circulación, sin acuñador claro): diseñar el bucle exterior que envuelve muchas sesiones de agente. Sus técnicas, documentadas por Anthropic en sus guías de agentes de larga duración, resuelven todas el mismo problema — cada sesión nueva despierta amnésica, «como ingenieros trabajando por turnos» (traducción propia) sin memoria del turno anterior: un agente inicializador prepara el terreno la primera vez (estructura, convenciones, lista de features en un fichero estructurado con estado por feature) y los turnos siguientes son un agente programador que lee la lista, elige la siguiente pendiente, la implementa y actualiza el estado; git como memoria y como checkpoints (commits frecuentes = puntos de restauración; el historial = lo que de verdad pasó); y notas estructuradas que el agente se escribe a sí mismo para su sucesor. Fíjate en lo que es esto con las gafas del curso puestas: ingeniería de la transferencia de teoría entre mentes efímeras. El fichero de features, las notas, los ADRs — todo es el equipo escribiendo la teoría en un formato que sobrevive a la muerte de cada contexto individual. Naur no imaginó lectores de silicio, pero describió exactamente este problema.

ADRs: la memoria de las decisiones

Lo que nos lleva al artefacto estrella del capítulo. Un ADR (Architecture Decision Record, registro de decisión de arquitectura) es un documento corto y numerado — contexto, decisión, alternativas descartadas, consecuencias — que captura por qué se decidió algo. El formato lo propuso Michael Nygard en 2011, con una motivación que desarma la vieja guerra entre ágil y documentación: «Agile methods are not opposed to documentation, only to valueless documentation» — los métodos ágiles no se oponen a la documentación, solo a la documentación sin valor (traducción propia). Un ADR no documenta el sistema (eso envejece mal); documenta una decisión en su momento, que es un hecho histórico y no caduca. La colección de ADRs de un proyecto es la parte de la teoría de Naur que mejor se deja escribir: el porqué. Y la observación de Élia les da su segunda vida: «es la primera vez en la historia de este oficio que la documentación tiene un lector infatigable que hace caso de lo que pone». Un ADR de 2024 que un humano nuevo no leería jamás está, para un agente, a un enlace del AGENTS.md de distancia — y el ADR-001 de Vega («no refactorizar informes; estrangular») fue lo que mantuvo a la Cuadrilla fuera del barro las semanas siguientes. Escribir ADRs siempre fue rentable; ahora además es ejecutable, en el sentido de que hay un lector que ajusta su comportamiento al leerlo. (En el mundo web existe un intento análogo de contexto para máquinas, llms.txt — un fichero propuesto en 2024 que resume tu sitio para LLMs; sé honesto con su estado: adopción real en documentación técnica, pero también la crítica de John Mueller, de Google, comparándolo con la meta keywords tag — «que yo sepa, ningún servicio de IA ha dicho que lo use» (traducción propia). Dentro de tu repositorio, AGENTS.md y ADRs tienen lectores garantizados; llms.txt, de momento, es una apuesta.)

Team agreements como código

Cierre operativo, y requisito explícito de este curso: los acuerdos de equipo. Todo equipo tiene tres pactos — cómo queremos el código, cómo lo revisamos, qué políticas de seguridad rigen — y la era agéntica los somete a una prueba sencilla: un acuerdo que no está en un fichero no existe para tus agentes (ni, seamos sinceros, para el compañero que entró el lunes). La traducción a ficheros, pieza a pieza:

repo/
├── AGENTS.md               ← el pacto de contexto: convenciones, comandos,
│                              vallas (sección 5); CLAUDE.md = @AGENTS.md
├── .editorconfig, eslint/ruff/prettier configs
│                           ← el pacto de estilo, ejecutable: lo que el
│                              linter impone no se discute en PRs
├── .claude/
│   ├── commands/           ← flujos del equipo como comandos slash
│   ├── skills/             ← saber-hacer modular, cargado bajo demanda
│   └── settings.json       ← permisos del agente: allow/ask/deny
│                              (la política "mergear jamás", como código)
├── .github/
│   ├── CODEOWNERS          ← quién revisa qué — también los PRs de agentes
│   ├── branch protection   ← checks obligatorios; nadie mergea en rojo,
│   │                          tenga pulso o no lo tenga
│   └── workflows/          ← los sentidos, en CI: tests, lint, evals
└── docs/adr/               ← el porqué de cada decisión, numerado

Y no te dejes engañar por los ejemplos de fontanería: los acuerdos pueden contemplar cualquier decisión compartida, incluidas las de más altura. Si tu equipo trabaja con DDD, el acuerdo de cómo se hace DDD aquí — dónde viven los agregados, cómo se protegen las invariantes, qué módulos pueden hablar con cuáles, qué vocabulario del dominio es canónico — es exactamente el tipo de contenido que pertenece a este sistema de ficheros: las reglas estructurales en AGENTS.md o en una skill («cómo se modela un agregado en esta casa»), las decisiones con su porqué en ADRs, y las fronteras verificables como checks. Un agente con ese contexto no solo escribe código que compila: escribe código que pertenece a tu arquitectura — y el revisor lo comprueba contra los mismos ficheros. Y una nota para equipos con varios productos: los acuerdos transversales (el estilo de la organización, la política de seguridad, el manual de DDD común) no tienen por qué duplicarse repo a repo — pueden vivir en un repositorio propio y llegar a cada producto como skill compartida, submódulo o referencia desde su AGENTS.md, con lo que el acuerdo se corrige en un sitio y rige en todos. Si solo tienes un producto, ignora esta nota sin remordimiento: la regla general es la de siempre — no fabriques la capa común antes del segundo consumidor.

Léelo como lo que es: la constitución del equipo, ejecutable. Nada de esa estructura es nuevo — CODEOWNERS, branch protection y linters existían antes de los agentes. Lo nuevo es que ahora hay un miembro del equipo que la lee entera, siempre, y la cumple exactamente en la medida en que esté escrita. Los equipos con acuerdos implícitos descubren con los agentes cuánto de su funcionamiento era tradición oral; los equipos con acuerdos escritos descubren que ya estaban listos.

Para llevar

  • La legibilidad es la interfaz de la automatización: los agentes rinden donde la arquitectura comunica y se hunden donde hay barro — más rápido que tú y con más seguridad en sí mismos. Sus fracasos son una auditoría gratuita; la respuesta al barro sigue siendo estrangular, no reescribir.
  • El flujo que funciona: explorar → planificar (tareas de una tarde, «hecho» verificable) → ejecutar (contexto limpio: /clear, /compact; worktrees para paralelizar) → revisar (sentidos en CI + writer/reviewer + tu lectura línea a línea).
  • No committees lo que no puedas explicar (Willison); no envíes sin revisión manual concienzuda (Hashimoto). La velocidad viene de paralelizar y verificar, no de dejar de comprender.
  • Política dura en hooks y permisos (se cumple siempre), no en prosa (se cumple a veces). Prompts buenos del equipo → comandos slash versionados; saber-hacer modular → skills.
  • Proyectos largos: loop engineering — inicializador + programador por turnos, lista de features con estado, git como checkpoints, notas estructuradas. Es ingeniería de transferencia de teoría entre contextos efímeros.
  • ADRs (Nygard): contexto, decisión, alternativas, consecuencias. El porqué escrito, ahora con un lector infatigable que hace caso.
  • Team agreements como código: AGENTS.md + linters + permisos + CODEOWNERS + checks + ADRs. Lo que no está en un fichero no existe.

Para profundizar

  • Documentación de buenas prácticas de Claude Code (code.claude.com/docs/en/best-practices) — el flujo completo, los antipatrones de contexto, subagentes, hooks y skills; casi todo el método de esta sección, de primera mano.
  • Anthropic, Effective harnesses for long-running agents y Harness design for long-running application development (anthropic.com/engineering, 2025-2026) — loop engineering: inicializador+programador, listas de features, generador-evaluador.
  • M. Nygard, Documenting Architecture Decisions (cognitect.com, 2011) y adr.github.io — el formato ADR original y sus variantes.
  • M. Hashimoto, Vibing a Non-Trivial Ghostty Feature (mitchellh.com, 2025) y My AI Adoption Journey (2026) — el testimonio práctico más honesto que existe del flujo agéntico serio, incluida su fase «Engineer the Harness».
  • S. Willison, simonwillison.net — el archivo entero, pero empieza por sus reglas de qué committea y qué no.
  • Ejercicio integrador: monta el flujo completo en un proyecto pequeño real — AGENTS.md, un comando slash, permisos, y una tarea ejecutada con explorar→planificar→ejecutar→revisar con writer/reviewer. Una tarde. Es el ejercicio más importante del curso.