Harness autoevolutivo: 1 regla, 3 que borré
Monté un “harness autoevolutivo” leyendo el capítulo 13 de mi propio libro y creyéndome el discurso. La idea del capítulo es sencilla: un cuarto agente llamado Evolver reescribe las reglas que siguen los otros agentes mientras yo duermo. OpenAI lo tiene en el Cookbook como “Self-Evolving Agents”, Addy Osmani lo plantea como un bucle que corre mientras uno duerme, Meta HyperAgents llega hasta modificar la propia implementación del agente.
Lo activé en el dominio de Dev.to del repositorio harness-ops. Un cron sábado 09:00 que ejecuta claude -p "/harness-evolve devto" y suelta un archivo EVO-NNNN.md cada vez que detecta algo digno de proponer.
Cinco meses después abrí el log y conté lo que había salido de ahí. 1 regla aplicada, 2 pendientes, 1 rechazada, 2 archivos de prueba, 13 ejecuciones en silencio total. Y aparte de eso, otras 3 reglas iniciales que terminé borrando yo mismo con un git commit desde el laptop, sin pasar por el evolver.
Vale la pena contarlo con las cifras honestas porque “autoevolver” suena a magia y la práctica es otra cosa.

Qué quería construir
El capítulo 13 de mi libro recoge tres referencias que marcan el techo del patrón.
- Self-Evolving Agents (OpenAI Cookbook) — ciclos de retroalimentación que permiten al agente aprender iterativamente, moviendo gradualmente la supervisión humana de “corrección fina” a “aprobación de alto nivel”.
- Self-Improving Coding Agents (Addy Osmani, Google Chrome) — la imagen de terminar el día de trabajo y despertar con la nueva feature codificada, probada y lista para revisión.
- HyperAgents (Meta Research) — el agente lee su propia implementación, genera parches y se autoactualiza.
Mi versión era más tímida. No quería que el evolver reescribiera código, sólo strategy.md: el archivo donde documento las reglas que siguen los otros 3 agentes del harness (Observer, Strategist, Marketer). El evolver sería la 4ta capa, con permiso de proponer diffs contra ese archivo, sin aplicar nada sin mi approve.
Cociné el prompt, puse el cron, firmé mentalmente el pacto fáustico (“mientras yo duermo, el harness se mejora a sí mismo”) y me fui al próximo proyecto.
Qué construí de verdad
El script que lanza al evolver cada sábado está en scripts/devto-evolver.sh y tiene 57 líneas. Lo importante es que llama a claude_run_capture "/harness-evolve devto" con WebSearch y WebFetch habilitados — eso diferencia al evolver del strategist, que trabaja offline con sólo datos del repo.
Un ciclo exitoso del evolver escribe un archivo en domains/devto/data/evolution/EVO-NNNN.md:
---
id: EVO-0003
domain: devto
title: "Reaction率 → Engagement率 (reaction+comment)"
status: pending
target_files: [domains/devto/strategy.md]
---
Yo luego ejecuto core/harness-evolve.sh approve EVO-0003 y el diff se aplica contra strategy.md. Si digo reject, se archiva. Si no hago nada en una semana, muta a expired. Suena a procedimiento serio.
El audit de 5 meses
Abro el directorio de evolución y cuento los archivos.
| Archivo | Fecha | Status | Qué era |
|---|---|---|---|
| EVO-0002 | 2026-05-19 | applied | Test del flujo approve (placeholder en TEMPLATE.md) |
| EVO-0003 | 2026-05-19 | applied | Reaction → Engagement rate |
| EVO-0004 | 2026-05-19 | rejected | Test de rechazo |
| EVO-0005 | 2026-08-19 | pending | Forzar exclude-list en el strategist |
| EVO-0006 | 2026-08-22 | pending | Metric frame_hit en los logs del strategist |
Si tacho los dos tests y la propuesta rechazada, queda 1 regla real aplicada y 2 esperando aprobación. En 5 meses. El tope teórico del schedule.evolver.cron (sábado semanal) son unas 20 ejecuciones en ese periodo. La realidad: 3 propuestas útiles de 20 oportunidades es un 15% de productividad. Nada que vaya a competir con el discurso del Cookbook.
Y aún así, el 15% está contado generoso. La verdadera cifra sale cuando leo el commit e823f39.
El agujero: 13 ejecuciones en silencio
El commit e823f39 de 2026-08-19 lleva un mensaje incómodo:
evolver: cwd を harness-ops に固定して silent fail を落とす— “fijar el cwd aharness-opspara que el silent fail se caiga ruidosamente”.
El bug era un clásico de los harness que operan por cron. /harness-evolve es un skill de proyecto que está en .claude/skills/harness-evolve/ del repo harness-ops. Claude Code sólo lo encuentra si tu cwd apunta al repo. Pero cron y mi run-phase.sh no hacían cd; el cwd quedaba en $HOME.
Lo que pasaba cada sábado 09:00 era esto: Claude arrancaba, buscaba el skill, no lo encontraba, respondía “Unknown command: /harness-evolve” en el stdout y salía con exit 0. Mi run-phase.sh lo tomaba como éxito, el log decía ”✅ phase complete” y Telegram ni se enteraba. Entre el 2026-05-23 y el 2026-08-15 esto se repitió 13 veces consecutivas. Dos de ellas (6/27 y 7/4) también murieron por exit=127 (“claude_run undefined”, bug distinto). El resto fue “Unknown command” puro.
El fix tiene dos partes. La primera es cd "$HOME/repos/harness-ops" antes de llamar a claude_run_capture. La segunda es un grep -qiE "Unknown command|Unknown slash command" después, que fuerza un exit 1 si el string aparece. La segunda parte es la verdadera lección. Un harness sin “fail loud” es un harness que miente.
Entre 2026-05-23 y 2026-08-15 no “no proponer también era evolución”. No era nada. El autoevolver estaba apagado y yo creía que estaba trabajando. Tres meses perdidos que convierten “5 meses de operación” en 1.5 meses de operación real + 3 meses de teatro + 2 semanas de post-fix.
Las 3 reglas que borré yo (no el evolver)
Esta parte es la que me pegó. En paralelo al evolver, yo seguí tocando strategy.md manualmente. Cuando reviso git log -- domains/devto/strategy.md, encuentro 3 reglas que escribí al inicio del dominio y que terminé borrando o invirtiendo con mis propias manos.
1. “Reaction rate como único quality gate” (invertida por EVO-0003 en commit aeffce8). La escribí porque en Dev.to las reactions son más visibles que los comments, pero los datos de 4 semanas mostraban artículos con 0% de reaction y comments activos. El evolver propuso extender a Engagement rate = reaction + comment, con cálculo semanal obligatorio para el strategist. Esta es la única regla que sí mató el evolver (y el commit aeffce8 lo deja marcado como evolve(devto): EVO-0003).
2. “5 posts por semana” (reducida a 2 en commit 76d7e99). La frecuencia inicial venía de una intuición: “si publico más seguido, más alcance”. El dato real fue que la mediana de PV se derrumbó cuando subí a 5/semana — los artículos competían entre sí por la misma audiencia y Dev.to no los repartía. Lo bajé a 2/semana y la mediana se recuperó. Esta la borré yo leyendo el dashboard, no el evolver.
3. “Publicar a las 12:00 y 22:00 JST” (desplazada a 07:00/20:00 en commit 77b5e43). Los dos slots originales los elegí por conveniencia (horas donde yo podía revisar en el teléfono). El observer registraba el PV acumulado por slot semana a semana, y a los 3 meses el patrón era claro: los artículos publicados a las 07:00 superaban a los de las 12:00 por un factor de ~2x. Lo moví. También la borré yo.
De las 3, el evolver sólo propuso la 1. Las 2 y 3 las propuse yo, con el dato en la mano. Y es precisamente ahí donde encuentro el techo honesto del patrón.
Lo que de verdad hace la autoevolución
El evolver propone bien cuando la regla tiene una métrica calculable en el repo (conteos de reaction/comment leídos del article-performance.jsonl del observer). Falla cuando la regla depende de observar patrones que atraviesan el sistema: la cadencia semanal, el slot de publicación, la prioridad del canonical. Esas requieren mirar varios archivos a la vez y entender el ritmo del dominio, no sólo una métrica.
Lo que sí me cambió es la forma de iterar. Tener un archivo EVO-NNNN.md con status, target_files y references me obliga a escribir el porqué del cambio antes de aplicarlo. Cuando lo hago yo mismo con un commit, suelo saltarme ese paso. El evolver, además de ser mi 4ta capa, se volvió mi plantilla de pensamiento para los cambios que escribo manualmente.
El cuarto agente que detectó al Strategist postergando es la primera propuesta real que me devolvió el evolver — EVO-0003 nació de ese patrón. El punto de entrada del harness (los archivos de contexto que uno pone al Claude Code antes de que arranque nada de esto) lo describo en los 7 archivos de Claude Code para un harness mínimo.
Si tienen que quedarse con una línea: el autoevolver no reemplaza al humano que lee los datos. Es un asistente que convierte los números del Observer en diffs legibles contra strategy.md, pero las reglas que cruzan dominios siguen siendo mi tarea. El techo del patrón, por lo menos en mi harness, está ahí.
ken imoto · kenimoto.dev
Libro relacionado Harness Engineering Harness Engineering desde cero — cinco interpretaciones (OpenAI, Anthropic, LangChain, Martin Fowler, academia) unificadas en un solo sistema para ingenieros en producción Ver la página del libro → ¿Te resultó útil este artículo?