El 90% del código en Anthropic lo escriben agentes de Claude. No ingenieros escribiendo en una ventana de chat. Son agentes autónomos ejecutando bucles, llamando herramientas y enviando código mientras el equipo duerme.
Sigue mi Substack para recibir información fresca sobre IA:
Esta es la configuración exacta. Paso a paso. Desde la primera llamada a la API hasta un agente funcional que puedes apuntar a cualquier tarea.
Este artículo cubrirá:
1 - por qué la mayoría de los "agentes" que la gente construye no son agentes
2 - las 5 partes que todo agente funcional necesita
3 - cómo construir cada parte con Claude, con código
4 - los errores que matan a los agentes antes de que se implementen
Guarda esto. Cada bloque de código a continuación funciona.
01. La mayoría de los "agentes de IA" no son agentes
He construido y roto más agentes de los que puedo contar. Los he visto quemar tokens toda la noche y no producir nada. Los he visto reescribir el mismo archivo 30 veces. Los he visto pasar sus propias pruebas borrando la prueba.

Cada fracaso me enseñó la misma lección: el modelo no es el problema. La arquitectura a su alrededor sí lo es. Esta guía es todo lo que aprendí, comprimido en el camino más corto que puedo darte.
Esto es lo que la mayoría construye cuando dice "agente de IA":
1while True:2 user_input = input("> ")3 response = call_claude(user_input)4 print(response)
Eso es un chatbot. Espera por ti. Hace lo que dices. Olvida todo entre sesiones. Cuando cierras la pestaña, se detiene.
Un agente es un sistema que trabaja hacia un objetivo sin que te sientes frente a él. Descubre lo que hay que hacer, hace un plan, ejecuta, verifica el resultado, y si no está listo aún, lo intenta de nuevo. Tú marcas la dirección. El agente hace el trabajo.
"Claude Code pasó de cero a 400 millones de dólares en ingresos en unos meses. Comenzó como un proyecto de hackathon. Todavía usa solo la API pública." -
Boris Cherny, Jefe de Claude Code
La misma API a la que tienes acceso ahora. Los mismos modelos. La diferencia es la arquitectura alrededor del modelo.

02. Las 5 partes de un agente real
Todo agente funcional - Claude Code, Devin, Codex, o cualquier cosa que construyas tú mismo - se ensambla a partir de cinco partes. Si falta una, se rompe.

03. La capa de API
Todo comienza aquí. Llamas a Claude, Claude responde. Pero la forma en que lo llamas determina si obtienes un chatbot o un agente.

Tres cosas importan: el prompt del sistema, la salida estructurada y la temperatura.
El prompt del sistema no es un saludo. Es el manual de operación de tu agente. Aquí van todas las reglas, restricciones y comportamientos. Sin él, Claude adivina lo que quieres. Con él, Claude sigue tu especificación.
1import anthropic23client = anthropic.Anthropic()45response = client.messages.create(6 model="claude-sonnet-4-6",7 max_tokens=4096,8 system="""Eres un agente de revisión de código.910Reglas:11- Lee todo el diff antes de comentar12- Señala solo errores reales, no preferencias de estilo13- Si no hay nada malo, di "LGTM" y detente14- Nunca sugieras cambios que no hayas probado mentalmente15- Formato de salida: array JSON de {file, line, issue, fix}""",16 messages=[{"role": "user", "content": diff_content}]17)
La salida estructurada hace que la respuesta de tu agente sea legible por máquina. Si Claude devuelve texto libre, tu código tiene que analizarlo. Si Claude devuelve JSON, tu código puede usarlo directamente.
1# Forzar salida JSON diciéndole a Claude la forma exacta2system = """Devuelve SOLO JSON válido. Sin markdown. Sin explicación.3Esquema:4{5 "status": "pass" | "fail",6 "issues": [{"file": str, "line": int, "issue": str}],7 "summary": str8}"""
Temperatura. Ponla en 0 para agentes deterministas. Ponla en 0.3-0.5 para trabajo creativo. El valor por defecto (1.0) añade aleatoriedad que casi nunca quieres en un agente.
04. Herramientas
Un modelo sin herramientas puede razonar pero no puede actuar. Puede decirte qué archivo editar pero no puede editarlo. Puede describir una consulta pero no puede ejecutarla.

El uso de herramientas de Claude te permite definir funciones que el modelo puede llamar. Tú describes la función. Claude decide cuándo llamarla. Tú la ejecutas y devuelves el resultado. Claude usa el resultado para seguir razonando.
1tools = [{2 "name": "run_sql",3 "description": "Ejecuta una consulta SQL de solo lectura contra la base de datos",4 "input_schema": {5 "type": "object",6 "properties": {7 "query": {8 "type": "string",9 "description": "Consulta SQL SELECT a ejecutar"10 }11 },12 "required": ["query"]13 }14},15{16 "name": "write_file",17 "description": "Escribe contenido en un archivo en disco",18 "input_schema": {19 "type": "object",20 "properties": {21 "path": {"type": "string"},22 "content": {"type": "string"}23 },24 "required": ["path", "content"]25 }26}]
La descripción de la herramienta importa más de lo que piensas. Claude la lee para decidir cuándo y cómo usar la herramienta. Una descripción vaga significa llamadas incorrectas. Una descripción precisa significa llamadas precisas.
Empieza con 3-5 herramientas. Leer archivo, escribir archivo, ejecutar comando, buscar, y una herramienta específica del dominio para tu caso de uso. Eso cubre el 90% de las tareas de un agente.

05. El bucle
Esta es la parte que convierte un script en un agente. Sin un bucle, tu código llama a Claude una vez y se detiene. Con un bucle, tu código llama a Claude, verifica el resultado, y llama de nuevo hasta que el trabajo esté hecho.

Tres componentes:
- Verificador. Algo que comprueba si la salida es buena. Un conjunto de pruebas, un verificador de tipos, un linter, una segunda llamada a Claude con criterios estrictos. Sin esto, el agente se da la razón a sí mismo en bucle.
- Estado. Un registro de lo que sucedió. Lo que funcionó, lo que falló, qué intentar a continuación. Sin estado, el agente comete el mismo error en cada pasada.
- Condición de parada. El objetivo se cumple, o un límite duro dice "después de N intentos, detente e informa". Sin esto, el bucle se ejecuta para siempre y agota tu cuenta.
1import json2from pathlib import Path34def run_agent(task: str, max_attempts: int = 5):5 state = {"task": task, "attempts": [], "done": False}67 for i in range(max_attempts):8 # Construir contexto a partir del estado9 context = build_prompt(state)1011 # Llamar a Claude con herramientas12 result = call_claude(context, tools)1314 # Ejecutar cualquier llamada a herramienta15 output = execute_tools(result)1617 # Verificar el resultado18 check = verify(output)1920 # Actualizar estado21 state["attempts"].append({22 "attempt": i + 1,23 "action": result.summary,24 "passed": check.passed,25 "reason": check.reason26 })2728 if check.passed:29 state["done"] = True30 break3132 # Guardar estado para la próxima ejecución33 Path("state.json").write_text(json.dumps(state, indent=2))34 return state
Este es el esqueleto completo. Cada agente de producción es una variación de este patrón. Los detalles cambian. La forma no.
06. Memoria
Sin memoria, cada sesión comienza desde cero. El agente redescubre la estructura de tu proyecto. Vuelve a aprender tus convenciones. Vuelve a cometer los errores que cometió ayer.

Los agentes de Claude usan tres capas de memoria:
CLAUDE.md es un archivo markdown en la raíz de tu proyecto. Claude Code lo lee automáticamente al inicio de cada sesión. Tus reglas, tu stack, tus convenciones. Escríbelo una vez, léelo siempre.
1# CLAUDE.md23## Proyecto4API de gestión de tareas. Python 3.12, FastAPI, PostgreSQL.56## Reglas7- Todas las respuestas: esquema {data, error, meta}8- Pruebas requeridas para cada nuevo endpoint9- Mensajes de commit: tipo(ámbito): descripción10- Nunca uses print() para registrar. Usa structlog.1112## Problemas conocidos13- El middleware de autenticación espera x-auth-token, no Authorization14- El conjunto de pruebas tarda 45s completo. Usa --filter para iterar.
Habilidades (Skills) capturan flujos de trabajo completos. No solo prompts, sino la forma completa: formato de entrada, pasos, formato de salida, reglas de validación. La primera ejecución toma 20 minutos. La reproducción toma 30 segundos.
Archivo de aprendizajes es un registro continuo de errores. El agente escribe en él después de cada sesión. La próxima sesión lo lee. Los errores se repiten hasta que se escriben. Luego se detienen.
1# learnings.md23- La API de pagos espera la clave de idempotencia en el encabezado, no en el cuerpo4- PostgreSQL NOTIFY necesita LISTEN explícito en el pool de conexiones5- El limitador de tasa cuenta por clave, no por IP. Las pruebas necesitan claves únicas.
07. La puerta de verificación
La puerta es la parte más difícil de construir y la más fácil de omitir. La mayoría la omite. Por eso la mayoría de los agentes se rompen en producción.

Una puerta de verificación es algo que comprueba el trabajo del agente sin que el agente se califique a sí mismo. El modelo que escribió el código es demasiado generoso al calificar su propia tarea. Necesitas una segunda verificación.
Tres patrones que funcionan:
1. Pruebas automatizadas. El agente escribe código. El conjunto de pruebas se ejecuta. Si las pruebas fallan, el agente obtiene la salida de error y lo intenta de nuevo. Así es como funciona Claude Code internamente.
1def verify(output):2 # Ejecutar el conjunto de pruebas3 result = subprocess.run(4 ["pytest", "tests/", "-x", "--tb=short"],5 capture_output=True, text=True6 )7 return {8 "passed": result.returncode == 0,9 "reason": result.stdout if result.returncode != 0 else "todas las pruebas pasan"10 }
2. Verificador de tipos / linter. Ejecuta mypy, ruff o tsc --noEmit después de cada cambio. Detecta categorías enteras de errores sin escribir una sola prueba.
3. Segundo modelo como revisor. Usa una llamada separada a Claude con un prompt de sistema estricto que solo busque problemas. El escritor es rápido y barato. El revisor es lento y estricto. Esa separación es la mayor parte de la calidad.
1# Prompt del revisor - separado del constructor2reviewer_system = """Eres un revisor de código estricto.3Tu ÚNICO trabajo es encontrar problemas.45Verifica:6- ¿El código coincide con la especificación?7- ¿Hay casos límite no detectados?8- ¿Todas las pruebas realmente prueban lo correcto?910Si todo está correcto, responde: {"passed": true}11Si algo está mal, responde: {"passed": false, "issues": [...]}1213NO sugieras mejoras. Solo señala errores reales."""
El escritor es rápido y barato. El revisor es lento y estricto. Esa separación es la mayor parte de la calidad.
08. Poniéndolo todo junto
Aquí hay un agente completo que toma una URL de issue de GitHub, lee el issue, escribe el código, ejecuta las pruebas y abre un PR. Cinco partes trabajando juntas.
1import anthropic, subprocess, json2from pathlib import Path34client = anthropic.Anthropic()5CLAUDE_MD = Path("CLAUDE.md").read_text()6LEARNINGS = Path("learnings.md").read_text()78SYSTEM = f"""Eres un agente de codificación.9Lee el issue. Escribe la corrección. Ejecuta las pruebas.1011Contexto del proyecto:12{CLAUDE_MD}1314Problemas conocidos:15{LEARNINGS}1617Reglas:18- Lee todo el código base antes de cambiar nada19- Escribe pruebas para cada cambio20- Si las pruebas fallan, corrige el código, no las pruebas21- Detente cuando todas las pruebas pasen"""2223TOOLS = [24 read_file_tool,25 write_file_tool,26 run_command_tool,27 search_codebase_tool,28]2930def run(issue_text, max_attempts=5):31 messages = [{"role": "user", "content": issue_text}]3233 for attempt in range(max_attempts):34 # Llamar a Claude35 response = client.messages.create(36 model="claude-sonnet-4-6",37 max_tokens=8192,38 system=SYSTEM,39 tools=TOOLS,40 messages=messages41 )4243 # Ejecutar llamadas a herramientas44 messages = handle_tool_use(response, messages)4546 # Verificar: ejecutar pruebas47 test_result = subprocess.run(48 ["pytest", "-x", "--tb=short"],49 capture_output=True, text=True50 )5152 if test_result.returncode == 0:53 print(f"Hecho en {attempt + 1} intentos")54 return True5556 # Alimentar el fallo de vuelta al bucle57 messages.append({58 "role": "user",59 "content": f"Las pruebas fallaron:\n{test_result.stdout}\nCorrige y reintenta."60 })6162 return False
Eso es un agente funcional. Capa de API con prompt del sistema y CLAUDE.md. Herramientas para operaciones de archivos. Un bucle con reintento. Memoria de learnings.md. Una puerta de verificación vía pytest.
Menos de 50 líneas. La misma arquitectura que Claude Code usa internamente.
**
09. Los 5 errores que rompen todo agente
- Sin puerta de verificación. El agente califica su propia tarea. Escribe código, dice "se ve bien", y sigue adelante. La salida parece correcta y se rompe en producción.
- Sin condición de parada. El bucle se ejecuta hasta que tu factura de API sea de $200. Sin un límite duro, el agente reintenta para siempre, reescribiendo el mismo archivo 40 veces. Siempre establece max_attempts. Siempre.
- Sin archivo de estado. El mismo error en el intento #1 y en el intento #50. El agente no sabe lo que ya intentó. Propone la misma corrección rota tres veces seguidas porque nada registra el fallo.
- Demasiadas herramientas. Le das a Claude 20 herramientas y elige la incorrecta. Un modelo con 5 herramientas claras toma mejores decisiones que uno con 20 herramientas superpuestas. Empieza pequeño. Añade herramientas solo cuando el agente se encuentre con un obstáculo.
- Prompt del sistema vago. "Sé un buen asistente de codificación" te da una salida genérica. "Todas las respuestas deben ser JSON válido, se requieren pruebas para cada cambio, nunca modifiques archivos fuera de /src" te da un agente que se comporta.
Conclusión:
Un agente funcional no es un mejor prompt. Es un sistema: API + herramientas + bucle + memoria + puerta de verificación. Cinco partes. Si falta una, se rompe.
La mayoría de la gente leerá esto, lo guardará, y seguirá usando a Claude como chatbot. Pegarán una pregunta a la vez y copiarán la respuesta en su código base manualmente.
Los que construyan el bucle enviarán trabajo mientras duermen. El mismo modelo. La misma API. El mismo precio. Arquitectura diferente.
Los bloques de código anteriores funcionan todos. Cópialos. Ejecútalos. Modifícalos para tu caso de uso.
Construye un agente esta semana. Apúntalo a una tarea que hagas todos los días. Déjalo ejecutar.





