# Ingeniería Harness: Cómo un agente de IA escribe código de producción en un monorepo legado
En Ingeniería Harness, los humanos definen límites arquitectónicos, escenarios de pruebas y revisan resultados, mientras el agente de IA genera todo el código de producción. Un experimento en un monorepo legado con 310.000 líneas de Scala/Java demostró que el enfoque funciona para tareas comunes como extraer un módulo sin alterar el comportamiento. El rol del ingeniero pasa a gestionar contexto y proceso, con el agente encargándose del trabajo mecánico pesado.
Monorepo: 25 módulos SBT, 8 años de historia, sistema de alta carga. Tarea: Extraer el procesamiento de webhooks de Canal X en un servicio independiente, siguiendo el patrón de adaptadores existentes.
Configuración del experimento y roles
Los humanos no escriben código de producción. Los roles están claramente divididos:
- Humano: Límites arquitectónicos, desglose de tareas, requisitos, pruebas, revisiones, validación final.
- Agente: Creación/cambios de código, movimiento de componentes, ejecución de pruebas basadas en escenarios, configuración de infraestructura, corrección de errores.
Tarea típica: Extracción mecánica con cableado y adaptaciones de dependencias, sin refactorización de lógica de negocio. Verificable mediante pruebas unitarias y E2E.
Preparación del contexto: La documentación como interfaz de control
La documentación se convierte en la herramienta clave: Los ADRs delinean opciones, los planes definen etapas. El agente se ciñe a los marcos dados, sin suposiciones.
Ejemplo de ADR:
# ADR-42: Extraer procesamiento de webhooks de Canal X del monolito
## Contexto
El Canal X se maneja actualmente dentro del núcleo. Otros canales ya funcionan como servicios separados detrás de un broker de mensajes.
## Opciones
1. Envoltorio ligero: Mover código existente con ajustes mínimos (paquetes, cableado).
2. Reescribir el manejador desde cero en una pila diferente.
3. Dejar como está.
## Decisión
Opción 1: Minimiza pérdida de comportamiento implícito durante la extracción; alinea la arquitectura con otros canales.
## Consecuencias
+ Patrón consistente en todos los canales
− Duplicación temporal de código; refactorización como tarea separada
Planes por etapas reducen errores: Desde el esqueleto hasta el bucle E2E completo.
Etapas y prompts: Control del agente paso a paso
Desglosar en pasos asegura supervisión. Ejemplos de prompts:
- Plano arquitectónico:
Estudia cómo funcionan los adaptadores de Canal A y B: Cómo se suscriben al broker y publican eventos entrantes.
Localiza el manejo de webhooks de Canal X en el monolito.
Escribe un ADR con tres opciones: envoltorio / reescritura / mantener en núcleo. Recomienda envoltorio y detalla consecuencias.
Coloca archivos en architecture/adr/, no toques código aún.
- Pruebas como contrato:
En la clase WebhookHandler hay ramificaciones por tipo de chat. Extráelo a una función pura routeEvent(...).
No mejores el comportamiento: copia ramificaciones tal cual. Escribe pruebas unitarias: chat privado, grupo, tipo desconocido, cuerpo vacío.
Éxito: `sbt test` del módulo pasa en verde.
- Nuevo módulo:
Crea módulo sbt channel-x-adapter según ESPEC en ADR-42.
Copia archivos listados del monolito; cambia solo paquetes, imports y deps para compilar limpio sin `dependsOn(core)`.
Regla: Sin refactorización de lógica de negocio en esta etapa.
- Bucle E2E:
Añade dir e2e/ con pytest + testcontainers: Contenedor broker, PostgreSQL, mock de API externa en puerto separado.
Escribe una prueba: POST webhook con texto "ping" → Broker recibe evento en subject esperado con text=ping.
Las pruebas guían al agente: Apunta a sbt test o pytest en verde.
Fortalezas del agente: Rutinas bajo control
El agente destaca en:
- Extracción y adaptación de código.
- Replicar patrones de ejemplos.
- Generar boilerplate.
- Construir infraestructura de pruebas.
- Lotes de ediciones similares.
Ejemplo de prueba E2E con pytest + testcontainers:
# Fixtures: Contenedor broker, adaptador, mock de API HTTP externa
def test_incoming_webhook_publishes_to_broker(e2e):
e2e.http.post("/webhook/channel-x", json={"message": {"text": "hello", "chat": {"id": 42}}})
msg = e2e.broker.await_message("inbound.channel-x", timeout_s=5)
assert msg["text"] == "hello"
assert msg["chat_id"] == 42
def test_outgoing_command_reaches_external_api(e2e):
e2e.broker.publish("outbound.channel-x", {"chat_id": "42", "text": "hi"})
calls = e2e.external_mock.wait_for_requests(method="POST", path_contains="sendMessage")
assert any(b"hi" in c.body for c in calls)
Verifica no solo compilación, sino comportamiento integrado: Broker, BD, mock de API.
Límites y fronteras
El agente no reemplaza decisiones arquitectónicas, pero acelera la mecánica. Riesgos: Regresiones ocultas (pruebas verdes esconden problemas), necesidad de límites estrictos. Adecuado para legado con patrones, no para greenfield o I+D.
Los desarrolladores pueden discrepar: Ahorros en rutinas vs. sobrecarga de contexto.
Lecciones clave
- Ingeniería Harness: Entorno controlado para agente — reglas, herramientas, retroalimentación.
- Triunfa en extracción/adaptación de código e infra de pruebas en proyectos legacy.
- Pruebas: Interfaz de control principal, no ritual.
- Fronteras: Tareas rutinarias con ejemplos, sin innovación arquitectónica.
- Industria: Anthropic (90% código IA), Meta, Amazon — transición a desarrollo nativo IA.
— Editorial Team
Aún no hay comentarios.