Claude Agent SDK Tutorial 2026: Por Qué tu Primer "Agente" No Necesita un Framework Externo
Tutorial práctico de Claude Agent SDK: construye agentes autónomos con la API nativa de Claude en 40 líneas de Python. Sin LangChain, sin dependencias externas.
El 95% de los Tutoriales de "Claude Agent SDK" te Venden Abstracción que No Necesitas
La mayoría de la gente cree que construir un agente autónomo con Claude requiere un framework externo.
LangChain. CrewAI. AutoGPT. Algún SDK pomposo con "Agent" en el nombre.
*El problema no es que funcionen. Es que te venden una solución a un problema que Claude ya resolvió. *
He construido agentes en producción para gestoriascercademi.com y findemergencyplumber.com. He pasado por LangChain, por loops caseros, por frameworks que prometían "orquestación mágica".
Voy a ser directo: tu agente más potente ya está en la API de Anthropic, y ocupa 40 líneas de Python con cero dependencias.
Este es el Claude Agent SDK tutorial que nadie te ha dado. No porque no exista. Porque la mayoría de la industria gana dinero vendiéndote la abstracción.
---
❌ La Mentira: Necesitas un Framework para Hacer Agentes
Mira cualquier tutorial de "agentes con IA" en YouTube o Medium. El patrón es siempre el mismo:
1. Instala LangChain
2. Importa `AgentExecutor`, `Tool`, `LLMSingleActionAgent`
3. Escribe 80 líneas de configuración
4. Reza para que no pete
*El resultado: una caja negra que no puedes depurar. *
¿Sabes lo que pasa dentro de `AgentExecutor` cuando Claude hace una tool call? Capas sobre capas de prompt templates, parsers, callback handlers, y "memory modules" que inyectan texto sin que sepas exactamente qué está viendo el modelo.
El dato que nadie te cuenta: un framework como LangChain añade entre un 30% y un 50% más de tokens por request solo en wrappers y prompt injection. No es productividad. Es impuesto.
---
✅ La Verdad: La API Nativa de Claude YA es un Agent SDK
Claude nativo soporta tool use sin ningún SDK externo. Definiciones en JSON. Claude responde con bloques `tool_use`. Tú ejecutas y devuelves.
Eso es todo.
No necesitas "Agent Executor". No necesitas "Tool Abstraction Layer". No necesitas "Callback Manager".
Lo que sí necesitas:
1. Un bucle de mensajes
2. Definiciones de herramientas en JSON
3. Gestión del historial de conversación
Eso es literalmente El Patrón de 3 Capas para Agentes Nativos. Y en código, son 40 líneas.
---
El Código: 40 Líneas, Cero Dependencias
Aquí está el agente más básico que puedes construir. Sin LangChain. Sin SDK. Sin magia.
```python
import anthropic
import json
client = anthropic.Anthropic(api_key="sk-...")
tools = [
{
"name": "get_weather",
"description": "Obtiene el tiempo actual para una ciudad",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "Ciudad y país, ej: Madrid, España"
}
},
"required": ["location"]
}
}
]
def execute_tool(name, input_data):
if name == "get_weather":
return {"temperature": 22, "condition": "soleado", "city": input_data["location"]}
return {"error": f"Tool {name} no encontrada"}
def agent_loop(user_input, history=None):
if history is None:
history = []
history.append({"role": "user", "content": user_input})
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system="Eres un asistente útil que responde usando herramientas cuando es necesario.",
messages=history,
tools=tools
)
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
history.append({"role": "assistant", "content": [block]})
history.append({
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result)
}]
})
return agent_loop("Continúa basándote en el resultado de la herramienta.", history)
history.append({"role": "assistant", "content": response.content})
return response.content[0].text
print(agent_loop("¿Qué tiempo hace en Madrid?"))
```
*Eso es todo. Un agente funcional. *
20 líneas efectivas. Sin dependencias externas (solo `anthropic`). Sin abstracción. Sin cajas negras.
Cada tool call es visible. Cada mensaje está en el historial. Puedes depurar cada paso.
---
El Patrón de 3 Capas para Agentes Nativos
Vamos a formalizar lo que acabas de ver. Este es el framework que uso en producción para cada agente que despliego.
1. Define herramientas como JSON plano
Nada de clases Tool con métodos abstractos. Nada de Pydantic validators. Claude entiende JSON.
```python
tools = [
{
"name": "search_web",
"description": "Busca información actualizada en internet",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string"}
},
"required": ["query"]
}
},
{
"name": "calculate",
"description": "Realiza cálculos matemáticos",
"input_schema": {
"type": "object",
"properties": {
"expression": {"type": "string", "description": "Expresión matemática como '2 + 2'"}
},
"required": ["expression"]
}
}
]
```
La clave: nombres descriptivos y descripciones claras. Claude usa la descripción para decidir qué herramienta llamar. Sé específico.
2. Bucle mínimo: envía, parsea, ejecuta, repite
No necesitas un orquestador. El bucle es:
Envía mensajes + herramientas
Claude devuelve texto, `tool_use` blocks, o ambos
Si hay `tool_use`: ejecuta, añade `tool_result` al historial, repite
Si no hay `tool_use`: devuelve la respuesta
*Eso es toda la "orquestación" que necesitas. *
3. Sistema de prompts para el qué, no para el cómo
El error más común: meter "piensa paso a paso", "razona antes de actuar", "eres un agente autónomo" en el system prompt.
Claude ya fue entrenado para razonar y usar herramientas. Sobrepromptear para "comportamiento de agente" solo hace que gaste tokens siendo verboso.
```python
❌ Mal: microgestionas el comportamiento del modelo
system="Eres un agente. Piensa paso a paso. Antes de cada tool call, razona.
Luego ejecuta la herramienta. Luego evalúa el resultado."
✅ Bien: describes lo que debe lograr, no cómo pensar
system="Responde preguntas de los usuarios usando las herramientas disponibles.
Cuando tengas suficiente información, responde directamente."
```
---
Structured Outputs: El Poder que Nadie Usa
Una de las prestaciones más infravaloradas de la API de Claude es la salida estructurada nativa. No necesitas Pydantic. No necesitas Zod. No necesitas parsers.
```python
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system="Devuelve siempre JSON válido.",
messages=[{"role": "user", "content": "Dame los datos de contacto de la empresa"}],
tools=[{
"name": "output_contact",
"description": "Tool de salida para devolver datos de contacto estructurados",
"input_schema": {
"type": "object",
"properties": {
"company_name": {"type": "string"},
"email": {"type": "string"},
"phone": {"type": "string"},
"address": {"type": "string"}
},
"required": ["company_name", "email"]
}
}],
tool_choice={"type": "tool", "name": "output_contact"}
)
for block in response.content:
if block.type == "tool_use":
data = block.input
print(f"Empresa: {data['company_name']}")
print(f"Email: {data['email']}")
```
Un patrón que uso constantemente en gestoriascercademi.com para extraer datos de registro mercantil. Sin librerías. Sin parsing frágil. Claude devuelve JSON directamente.
---
Gestión de Contexto: Lo Único que Realmente Importa
El 80% de los fallos en producción con agentes no son por tool calls. Son por gestión del contexto.
El problema real: el historial crece. El prompt se come la ventana de contexto. Claude empieza a ignorar instrucciones tempranas.
La solución: truncamiento estratégico, no memoria con vector store.
```python
def truncate_history(history, max_exchanges=10, system_prompt=None):
"""Mantiene el system prompt + los últimos N intercambios."""
if len(history) <= max_exchanges * 2:
return history
recent = history[-(max_exchanges * 2):]
if system_prompt:
return [{"role": "system", "content": system_prompt}] + recent
return recent
```
No necesitas memoria externa para el 90% de los casos de uso. Necesitas decidir qué es relevante mantener y qué puedes resumir.
Cuando el historial se hace muy largo (más de 50 intercambios), añado un paso de resumen:
```python
def summarize_history(history):
summary_prompt = "Resume la conversación hasta ahora en 3 frases,
manteniendo solo la información esencial para continuar."
summary = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=256,
messages=[{"role": "user", "content": summary_prompt +
"\n\n" + format_history(history)}]
)
return [{"role": "system", "content": f"Historial resumido: {summary.content[0].text}"}]
```
---
Multi-Tool en Paralelo: Donde el SDK Brilla más que los Frameworks
Una petición compleja como "planifica un viaje a Londres para fin de semana" puede requerir:
1. Buscar vuelos
2. Consultar el tiempo
3. Convertir moneda
4. Buscar hoteles
Con los frameworks tradicionales, esto implicaba sub-agentes, planificación secuencial, o "agentes orquestadores".
Con Claude nativo, el modelo puede llamar múltiples herramientas en un solo turno.
```python
Claude puede devolver varios tool_use blocks en una sola respuesta
Tú solo tienes que iterarlos:
for block in response.content:
if block.type == "tool_use":
if block.name == "search_flights":
results["flights"] = search_flights(block.input)
elif block.name == "get_weather":
results["weather"] = get_weather(block.input)
elif block.name == "convert_currency":
results["currency"] = convert_currency(block.input)
elif block.name == "search_hotels":
results["hotels"] = search_hotels(block.input)
```
Cada resultado se añade al historial como `tool_result`. Claude recibe toda la información de golpe y construye la respuesta final.
¿Frameworks para esto? Solo añaden bucles sobre bucles.
---
Observabilidad: La Ventaja que los Frameworks te Quitan
En producción, cuando un agente hace una tool call equivocada, necesitas saber por qué.
Con un framework, el prompt ha sido reescrito. Se han inyectado instrucciones. Hay callbacks que modifican el mensaje. Depurar es un infierno.
Con la API nativa, tienes el historial completo. Sabes exactamente qué vio Claude:
El system prompt original
Cada mensaje del usuario
Cada tool result devuelto
La respuesta exacta del modelo
Loggea todo desde el día uno:
```python
def agent_loop(user_input, history=None, log=True):
... código del agente ...
if log:
with open(f"agent_log_{timestamp}.json", "w") as f:
json.dump({
"request": messages,
"response": response.to_dict(),
"tools_executed": tool_calls_log
}, f, indent=2)
```
Cuando algo falla, abres el log. Ves exactamente qué pasó. Arreglas. Sin adivinar.
---
La Comparación que lo Dice Todo
Vamos a ponerlo en números. El mismo agente — dos tool calls, devuelve JSON estructurado — construido de dos formas.
Con LangChain (~80+ líneas):
Importas 4 módulos
Defines clases Tool con métodos
Configuras AgentExecutor con promps templates
Añades output parsers
Añades memory wrappers
= ~80 líneas, 3 segundos de init, tokens extra por cada llamada
Con Claude nativo (~25 líneas):
Importas anthropic
Defines herramientas en JSON
Bucle de 15 líneas
= ~25 líneas, init instantáneo, tokens justos
*No es que LangChain sea malo. Es que el SDK ya te da lo que necesitas. *
---
¿Y los Casos Complejos? Sub-Agents, Human-in-the-Loop, Rate Limits
Los defensores de los frameworks dirán: "¿Y los sub-agentes? ¿Y el human-in-the-loop? ¿Y el rate limiting?"
Sub-agentes: Son tool calls recursivas. Una herramienta que llama a otro agente es simplemente una función que ejecuta el mismo bucle.
Human-in-the-loop: Pausas el bucle, esperas input del usuario, continúas. No necesitas un framework para eso.
Rate limits y retries: Son concerns de infraestructura, no de agente. Un wrapper de cliente reutilizable los maneja:
```python
class ClaudeClient:
def __init__(self, api_key, max_retries=3):
self.client = anthropic.Anthropic(api_key=api_key)
self.max_retries = max_retries
def create_message(self, **kwargs):
for attempt in range(self.max_retries):
try:
return self.client.messages.create(**kwargs)
except anthropic.RateLimitError:
if attempt == self.max_retries - 1:
raise
time.sleep(2 ** attempt)
```
Una vez. Reutilizable. Sin framework.
---
El Futuro Ya Está Aquí: Menos Abstracción, Más Control
El ecosistema está girando hacia lo simple.
Anthropic recomienda empezar con la API raw. Vercel AI SDK apuesta por wrappers mínimos. Las migraciones más sonadas de 2025-2026 son equipos saliendo de LangChain hacia stacks propios de 3 ficheros.
El "Claude Agent SDK" real no se vende en npm o PyPI. Está en los endpoints de Anthropic, esperando a que escribas el bucle.
40 líneas. Cero dependencias externas. 100% control.
*Eso es un agente. Lo demás son impuestos. *
---
Resumen y Próximos Pasos
Lo que has aprendido hoy:
La API nativa de Claude con tool use es más potente que cualquier framework de agentes externo
El Patrón de 3 Capas para Agentes Nativos — define herramientas en JSON, bucle mínimo, system prompt para el qué no para el cómo
Structured outputs nativos sin librerías de parsing
Gestión de contexto con truncamiento estratégico, no memoria externa
Observabilidad desde el día uno con logging plano
El siguiente paso: abre tu terminal. Escribe las 40 líneas. Ejecuta. Cuando funcione, despliega. Cuando falles, miras el log. Arreglas. Repites.
No necesitas un SDK. Necesitas confiar en que el modelo ya sabe lo que tiene que hacer.
Lee el artículo completo en brianmenagomez.com
Más sobre mis servicios en brianmenagomez.com
Herramientas: Conversor IAE CNAE · Gestorias cerca de ti · Calculadora IRPF

