- La estructura central de un asistente de programación con IA no es magia compleja, sino unas 200 líneas de código Python sencillo
- El sistema se basa en un bucle de conversación con un LLM: cuando el LLM solicita una llamada de herramienta, el código local la ejecuta y le devuelve el resultado
- Las herramientas básicas necesarias son tres: lectura de archivos (
read), listado de archivos (list) y edición de archivos (edit), con lo que se puede explorar el proyecto y modificar código
- El LLM decide por sí mismo qué herramienta llamar y cuándo hacerlo con base en la firma y la descripción (
docstring) de cada herramienta
- Esta estructura es la misma que está en el núcleo de productos comerciales como Claude Code, y hasta con una estructura simple se puede implementar un agente de programación potente
Concepto básico de un agente de programación
- Un agente de programación es un sistema basado en conversación con un LLM que recibe instrucciones del usuario y realiza operaciones reales sobre archivos mediante llamadas de herramientas
- El usuario introduce una petición como “crear un archivo nuevo que incluya una función hello world”
- El LLM responde con las llamadas de herramienta necesarias en formato JSON
- El programa ejecuta esa herramienta y devuelve el resultado al LLM
- El LLM no accede directamente al sistema de archivos, sino que solo hace solicitudes; el trabajo real lo maneja el código local
Las tres herramientas necesarias
read_file: lee y devuelve todo el contenido del archivo indicado
list_files: devuelve la lista de archivos y carpetas dentro de un directorio
edit_file: reemplaza una cadena existente por una nueva, o crea un archivo nuevo si old_str está vacío
- Si no encuentra la cadena a reemplazar, devuelve “old_str not found”
- Solo con estas tres herramientas ya es posible crear, modificar y explorar archivos
Registro de herramientas e integración con el LLM
- Todas las herramientas se registran en
TOOL_REGISTRY con su nombre y función para que el LLM pueda llamarlas
- Se extraen la
docstring y la firma de cada herramienta para pasárselas al LLM
- El prompt del sistema le deja claro al LLM la “lista de herramientas disponibles” y el “formato de llamada”
- Las llamadas de herramienta se limitan al formato
'tool: TOOL_NAME({JSON_ARGS})'
- Los resultados de la ejecución se envían al LLM en forma de
tool_result(...)
Parseo de llamadas de herramienta y manejo de respuestas del LLM
- En la respuesta del LLM se buscan las líneas que empiezan con
tool: para extraer el nombre de la herramienta y sus argumentos (JSON)
- Después de ejecutar cada herramienta, el resultado se serializa como JSON y se agrega al historial de conversación
- La función
execute_llm_call llama a la API del LLM y devuelve el texto de la respuesta
run_coding_agent_loop recibe la entrada del usuario y mantiene el bucle de conversación con el LLM
- El bucle interno se repite hasta que el LLM deja de solicitar llamadas de herramienta
Ejemplos de ejecución y posibilidades de expansión
- Ejemplos de conversación:
- “crea el archivo
hello.py e implementa hello world” → se crea un archivo nuevo con una llamada a edit_file
- “agrega a
hello.py una función que multiplique dos números” → se llama primero a read_file y luego a edit_file
- Es posible implementar un asistente de programación completo en apenas unas 200 líneas de código
- Los productos comerciales agregan sobre esto manejo de errores, respuestas en streaming, gestión de contexto, herramientas adicionales y flujos de aprobación
- La estructura central sigue siendo la misma: un bucle simple en el que el LLM decide y el código ejecuta
Práctica y expansión
- El código fuente completo tiene unas 200 líneas y puede ampliarse cambiando a otro proveedor de LLM o agregando más herramientas
- Incluso con una estructura simple, se puede implementar directamente un prototipo potente de agente de programación con IA
1 comentarios
Comentarios en Hacker News
Lo que yo agregaría es planning
La clave del uso efectivo de herramientas es darse cuenta de que operan sobre una lista dinámica de TODO
El modo Plan sirve para bootstrapear cómo se siembra esa lista y cuándo se ejecuta cada elemento
La interacción del usuario funciona como una forma de reordenar esa lista
El mes pasado estuve probando qué tan bien Claude Code resolvía problemas de CTF, y si desactivabas la herramienta TodoList y el planning, el rendimiento caía entre 1 y 2 niveles
Para eso, ver el video relacionado: Breaking Bots: Cheating at Blue Team CTFs with AI Speed Runs
Lo interesante es que mucha gente solo se enfoca en “usar o no usar el modo plan”, pero la lista TODO siempre está activa
Además, me da risa ver textos que reducen la “gestión inteligente del contexto” a simples elementos de TODO
Mucha gente intenta implementarlo por su cuenta y termina perdiendo un año por resultados de evaluación que se rompen en producción
Esto podría agregarse simplemente como tokens de razonamiento, pero en la práctica implementarlo como una herramienta explícita de almacenamiento de clave única es mucho más predecible y efectivo
Parece que este enfoque simple también podría funcionar para otras ideas de herramientas que almacenan estructuras del lenguaje
Mientras probaba Codex, organizaba la especificación durante unos 10 minutos, la dividía en una lista de cambios, hacía que se guardara en un archivo y luego le indicaba revisar y corregir el plan después de cada cambio
Así, el LLM puede concentrarse en trabajo corto y orientado a objetivos sin necesidad de entradas de prompt constantes
En la práctica, produce un efecto similar al de tener subagentes
A veces también indico como último TODO “vuelve a revisar todo el trabajo y verifica la calidad con el linter, etc.”
Cuando se comprime el contexto, también se usa como una representación concisa de la sesión
El núcleo de un agente de programación en realidad es una simple estructura de bucle y llamadas a herramientas
Pero si vas a escribir un texto como “The Emperor Has No Clothes: How to Code Claude Code in 200 Lines of Code”, deberías revisar sí o sí How to Build an Agent de Thorsten Ball
Ese texto fue el primero en plantear la idea de que “la esencia de un agente es simple”
Claro, en la práctica hacen falta TODOs y varios tipos de scaffolding, y Claude Code en sí también tiene configuraciones complejas, plugins y muchas funciones de UI
Aun así, con el bucle mínimo basta para bootstrapear la expansión de sus propias funciones
Si quieres ver el funcionamiento interno, con claude-trace puedes rastrear la interacción entre el LLM y las llamadas a herramientas
Además del simple bucle, hay muchos elementos complejos como uuid threading, manejo de colas de mensajes, snapshots de cambios de archivos y sidechains de subagentes
Así que “200 líneas” tiene sentido a nivel conceptual, pero a nivel de producción real es mucho más complejo
Codex todavía no tiene funciones de queueing, pero sigue siendo potente
Yo hice una app para macOS llamada Contextify que monitorea en tiempo real las transcripciones CLI de Claude Code y Codex, y permite consultar el historial de conversaciones con la función Total Recall
Los modelos Claude están entrenados con su propio schema de herramienta str replace
Reescribir archivos completos es ineficiente, así que la clave está en las modificaciones parciales
En realidad hay más elementos
Por ejemplo, hay casos en los que el agente provoca early stopping y da por terminada la tarea
Ni siquiera se resuelve con los modelos de razonamiento más recientes
Claude Code lo resuelve inyectando TODOs en cada prompt para recordarle el trabajo pendiente
En el repositorio público de HolmesGPT hay varios benchmarks experimentales
Al principio me impactó el concepto de que “basta con decirle al LLM la lista de herramientas y el formato de invocación”
Pensaba: si el LLM solo genera texto, ¿cómo va a invocar herramientas? Pero cuando entendí que eso era todo, se sintió mágico
Durante las vacaciones hice con Opus un agente de programación basado en un DSL de Prolog (pasó de las 200 líneas)
Sorprendentemente, empezó a funcionar bien casi de inmediato
Parece que los modelos de última generación han llegado a una etapa en la que ha disminuido la importancia del harness del agente
Para ese experimento, ver este post
Hace un año este artículo era bastante preciso, pero ahora los harnesses han avanzado mucho y el modelo de bucle simple ya no explica bien el funcionamiento real de Claude Code
Incluso un agente simple, si usa el mismo modelo, no queda tan lejos en rendimiento
Es parecido a un tutorial de “crear tu propia DB” que muestra el B-tree básico
Subagent, MCP y Skills están en un punto intermedio, y la optimización de contexto solo importa de verdad en ejecuciones largas
codex-cli, puedes hacer un mejor análisis del modeloYo construyo directamente agent loops empresariales y proceso más de mil millones de tokens al mes
El bucle simple sí es la base, pero en entornos reales un montón de detalles hace que la complejidad se dispare
Por ejemplo, cómo manejar el bucle si el usuario envía mensajes en medio, cómo sincronizar entradas por webhook de algo como Slack,
aprobaciones, guardrails, procesamiento asíncrono de tareas, etc.
Estoy pensando en organizar esta experiencia en un blog
Como lecturas útiles están You Should Write An Agent y How To Build An Agent
Nuestro equipo de SWE-bench publicó un agente open source de 100 líneas
Es mini-swe-agent, y es popular tanto en academia como en industria
Es un buen punto de partida para aprender sobre el mundo de los agentes
En 2023 hubo un artículo titulado “reimplementar LangChain en 100 líneas”
Vi ese artículo, lo implementé de verdad y lo usé en varios proyectos