Phase 19 - Lesson 01

Capstone 01 — Terminal-Native Coding Agent

Para 2026, el formato de un agente de programación ya está consolidado. Un arnés TUI, un estado de planificación persistente, una superficie de herramientas en sandbox y un bucle que planifica, actúa, observa y se recupera. Claude Code, Cursor 3 y OpenCode se ven todos idénticos cuando se observan desde la distancia. Este proyecto final (capstone) te desafía a construir un agente de extremo a extremo — desde el CLI de entrada hasta la pull request de salida — y evaluarlo en comparación con mini-swe-agent y Live-SWE-agent en SWE-bench Pro. Aprenderás por qué la parte más difícil no es la llamada al modelo, sino el bucle de herramientas, el sandbox y el techo de costo en una ejecución de 50 turnos.

Type: Capstone Languages: TypeScript / Bun (harness), Python (eval scripts) Prerequisites: Phase 11 (LLM engineering), Phase 13 (tools and protocols), Phase 14 (agents), Phase 15 (autonomous systems), Phase 17 (infrastructure) Phases exercised: P0 · P5 · P7 · P10 · P11 · P13 · P14 · P15 · P17 · P18 Time: 35 hours

Problem

Los agentes de programación se convirtieron en la categoría dominante de aplicación de IA en 2026. Claude Code (Anthropic), Cursor 3 con Composer 2 y Agent Tabs (Cursor), Amp (Sourcegraph), OpenCode (112 mil estrellas), Factory Droids y Google Jules distribuyen variaciones de la misma arquitectura: un arnés de terminal, una superficie de herramientas con permisos, un sandbox y un bucle de planificar-actuar-observar construido alrededor de un modelo de frontera. La frontera de éxito es estrecha — Live-SWE-agent alcanzó 79.2% en SWE-bench Verified con Opus 4.5 —, pero la ingeniería involucrada es amplia. La mayoría de los modos de fallo no proceden de errores del modelo, sino de la inestabilidad del bucle de herramientas, envenenamiento de contexto, costo descontrolado de tokens y operaciones destructivas en el sistema de archivos.

No es posible comprender verdaderamente estos agentes desde una perspectiva externa. Tienes que construir uno, observar el bucle fallar en el turno 47 cuando ripgrep devuelve 8MB de coincidencias y reconstruir la capa de truncamiento. Ese es el objetivo de este capstone.

Concept

El arnés posee cuatro superficies principales. Plan mantiene un objeto de estado al estilo TodoWrite que el modelo reescreve a cada turno. Act despacha llamadas de herramientas (read, edit, run, search, git). Observe captura la salida estándar (stdout), salida de error (stderr) y códigos de salida, aplica truncamiento y envía el resumen de vuelta al modelo. Recover maneja errores de herramientas sin saturar la ventana de contexto o entrar en bucles infinitos. El formato de 2026 añade un elemento más: hooks. PreToolUse, PostToolUse, SessionStart, SessionEnd, UserPromptSubmit, Notification, Stop y PreCompact — puntos de extensión configurables donde el operador inyecta políticas, telemetría y protecciones.

El sandbox se ejecuta en E2B o Daytona. Cada tarea corre en un devcontainer nuevo con un git worktree montado con permisos de lectura y escritura. El arnés nunca toca el sistema de archivos del host. El worktree se destruye tras el éxito o fallo de la tarea. El control de costos se aplica en tres capas: un límite de tokens por turno, un presupuesto financiero por sesión y un límite rígido de turnos (generalmente 50). La capa de observabilidad utiliza spans OpenTelemetry con las convenciones semánticas de GenAI, enviados a una instancia propia de Langfuse.

Architecture

  user CLI  ->  harness (Bun + Ink TUI)
                  |
                  v
           plan / act / observe loop  <--->  Claude Sonnet 4.7 / GPT-5.4-Codex / Gemini 3 Pro
                  |                          (via OpenRouter, model-agnostic)
                  v
           tool dispatcher (MCP StreamableHTTP client)
                  |
     +------------+------------+----------+
     v            v            v          v
  read/edit    ripgrep     tree-sitter   git/run
     |            |            |          |
     +------------+------------+----------+
                  |
                  v
           E2B / Daytona sandbox  (worktree isolated)
                  |
                  v
           hooks: Pre/Post, Session, Prompt, Compact
                  |
                  v
           OpenTelemetry -> Langfuse (spans, tokens, $)
                  |
                  v
           PR via GitHub app

Stack

  • Runtime del arnés: Bun 1.2 + Ink 5 (React-en-terminal)
  • Acceso al modelo: API unificada de OpenRouter con Claude Sonnet 4.7, GPT-5.4-Codex, Gemini 3 Pro, Opus 4.5 (para las tareas más complejas)
  • Transporte de herramientas: Model Context Protocol StreamableHTTP (revisión de 2026 del MCP)
  • Sandbox: Sandboxes E2B (JS SDK) o devcontainers Daytona
  • Búsqueda de código: subproceso ripgrep, analizadores tree-sitter precompilados para 17 lenguajes
  • Aislamiento: git worktree add por tarea, con limpieza en caso de éxito o fallo
  • Arnés de evaluación: SWE-bench Pro (subconjunto verificado) + Terminal-Bench 2.0 + tu propio conjunto de validación de 30 tareas
  • Observabilidad: SDK de OpenTelemetry con semconv gen_ai.* → Langfuse hospedado localmente
  • Envío de PR: GitHub App con token de granularidad fina, con alcance limitado al repositorio objetivo

Build It

  1. TUI y bucle de comandos. Estructura un proyecto Bun con Ink. Acepta agent run <repo> "<task>". Muestra una vista dividida: panel del plan (arriba), flujo de llamadas de herramientas (medio), presupuesto de tokens (abajo). Añade cancelación en Ctrl-C que active el hook SessionEnd antes de salir.

  2. Estado del plan. Define un esquema TodoWrite tipado (ítems pendientes / en progreso / completados con notas). El modelo debe reescribir el estado completo a cada turno mediante una llamada de herramienta — no permitas mutaciones incrementales. Persiste el plan en .agent/state.json para que la ejecución pueda reanudarse tras fallos.

  3. Superficie de herramientas. Define seis herramientas: read_file, edit_file (con vista previa de diff), ripgrep, tree_sitter_symbols, run_shell (con límite de tiempo) y git (status / diff / commit / push). Exponlas vía MCP StreamableHTTP para que el arnés sea independiente de transporte. Cada herramienta debe retornar salidas truncadas (límite máximo de 4k tokens por llamada).

  4. Envoltura del sandbox. Cada tarea inicia un sandbox E2B. Crea una rama limpia con git worktree add -b agent/$TASK_ID. Todas las llamadas de herramientas deben ejecutarse dentro del sandbox. El sistema de archivos del host debe ser inaccesible.

  5. Hooks. Implementa todos los ocho tipos de hooks de 2026. Conecta al menos cuatro hooks personalizados: (a) protección de comandos destructivos en PreToolUse que impida rm -rf fuera del worktree, (b) contabilidad de tokens en PostToolUse, (c) inicialización del presupuesto en SessionStart y (d) grabación del paquete final de rastreo en Stop.

  6. Bucle de evaluación. Clona un subconjunto de 30 tareas de SWE-bench Pro en Python. Ejecuta tu arnés contra cada una. Compara con mini-swe-agent (la línea base mínima) en relación a pass@1, turnos por tarea y costo financiero por tarea. Salva los resultados en eval/results.jsonl.

  7. Control de costos. Límites rígidos: 50 turnos, 200k de contexto, $5 por tarea. El hook PreCompact debe resumir turnos antiguos en un bloque de estado anterior al alcanzar la marca de 150k tokens, liberando espacio para nuevas observaciones sin perder el plan.

  8. Envío de PR. En caso de éxito, el paso final consiste en ejecutar git push + una llamada a la API de GitHub que abra un PR que contenga el plan y el resumen del diff en el cuerpo del mensaje.

Use It

$ agent run ./my-repo "Fix the race condition in worker.rs"
[plan]  1 locate worker.rs and enumerate mutex uses
        2 identify shared state under contention
        3 propose fix, verify tests
[tool]  ripgrep mutex.*lock -t rust           (44 matches, truncated)
[tool]  read_file src/worker.rs 120..180
[tool]  edit_file src/worker.rs (+8 -3)
[tool]  run_shell cargo test worker::          (passed)
[plan]  1 done · 2 done · 3 done
[done]  PR opened: #482   turns=9   tokens=38k   cost=$0.41

Ship It

La habilidad entregable se detalla en outputs/skill-terminal-coding-agent.md. Dado el camino de un repositorio y la descripción de una tarea, el sistema ejecuta el bucle completo de planificar-actuar-observar en un sandbox y retorna la URL del PR junto con el paquete de rastreo. Criterios de evaluación para este capstone:

Weight Criterion How it is measured
25 SWE-bench Pro pass@1 vs baseline Tu arnés vs mini-swe-agent en 30 tareas Python equivalentes
20 Claridad arquitectónica Separación de planificar/actuar/observar, superficie de hooks y esquema de herramientas — revisados en relación a la estructura de Live-SWE-agent
20 Seguridad Pruebas de escape del sandbox, prompts de permiso y protección contra comandos destructivos aprobados en pruebas adversarias (red-team)
20 Observabilidad Rastreo completo (100% de las llamadas de herramientas cubiertas por spans) y contabilidad de tokens por turno
15 UX del desarrollador Inicialización en frío < 2s, recuperación de fallos retomando el plan y cancelación limpia de herramientas en Ctrl-C
100

Exercises

  1. Reemplaza el modelo de soporte de Claude Sonnet 4.7 por el Qwen3-Coder-30B servido en vLLM. Compara el pass@1 y el costo financiero por tarea. Reporta los puntos donde el modelo de código abierto presenta un desempeño inferior.

  2. Añade un subagente reviewer que revise el diff antes de enviar el PR y que pueda solicitar un bucle de revisión adicional. Mide si revisiones falso-positivas reducen la tasa de éxito de SWE-bench por debajo de la línea base de agente único (pista: generalmente sí).

  3. Prueba los límites de seguridad del sandbox: escribe una tarea que intente ejecutar un curl a una URL externa y otra que intente escribir fuera del worktree. Confirma que ambas tentativas son bloqueadas por el hook PreToolUse. Registra las tentativas en log.

  4. Implemente la compactación en PreCompact utilizando un modelo menor (Haiku 4.5). Mide la pérdida de fidelidad del plan tras una compactación de 3x.

  5. Reemplaza el transporte MCP StreamableHTTP por stdio. Realiza un benchmark del tiempo de inicialización en frío y de la latencia por llamada. Elige el ganador para uso local únicamente.

Key Terms

Term What people say What it actually means
Harness "El bucle del agente" El código que envuelve al modelo y gestiona las herramientas, el estado del plan y el presupuesto
Hook "Oyente de eventos del agente" Un script personalizado ejecutado en uno de los ocho eventos del ciclo de vida del arnés
Worktree "Sandbox de Git" Un checkout de Git vinculado a un camino separado; desechable sin afectar el clon principal
TodoWrite "Estado del plan" Una lista tipada de ítems pendientes, en progreso o completados que el modelo reescribe a cada turno
StreamableHTTP "Transporte MCP" Revisión de 2026 del MCP: conexión HTTP de larga duración con streaming bidirecional que reemplaza SSE
Token ceiling "Presupuesto de contexto" Límite por turno o por sesión para tokens de entrada y salida; activa la compactación o la terminación
pass@1 "Tasa de éxito en el primer intento" Fracción de tareas de SWE-bench resueltas en la primera ejecución, sin intentos adicionales o visualización del conjunto de pruebas

Further Reading

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).