Saltar al contenido
sobolewski.proLa IA de hoy, cada tardeSuscribirme

Una vez al día. Date de baja con un clic. Política de privacidad

Cómo crear un agente de IA en Python: Claude Agent SDK paso a paso

Cómo crear un agente de IA que lee y corrige código por sí solo: instalamos Claude Agent SDK, escribimos el primer agente y añadimos una herramienta y MCP.

10 min de lectura

Este artículo en otros idiomas:العربيةDeutschEnglishFrançaisItaliano日本語Polski简体中文

En este artículo
  1. ¿Qué es un agente de IA desde el punto de vista del programador?
  2. Paso 1: ¿cómo instalar Claude Agent SDK?
  3. Paso 2: ¿cómo configurar la clave de API?
  4. Paso 3: ¿cómo escribir el primer agente de IA?
  5. Paso 4: ¿cómo decidir qué puede hacer el agente por su cuenta?
  6. Paso 5: ¿cómo darle al agente una herramienta propia?
  7. Paso 6: ¿cómo conectar el agente a un servidor MCP?
  8. ¿Qué hacer después del primer agente?
  9. ¿A qué hay que prestar atención?
  10. Preguntas frecuentes

¿Cómo crear un agente de IA sin escribir todo el bucle desde cero? El camino más corto que conozco es Claude Agent SDK, una biblioteca para Python y TypeScript que nos da las mismas herramientas, el mismo bucle de agente y la misma gestión de contexto sobre los que funciona Claude Code. Escribimos una docena de líneas de código y el agente lee archivos, corrige errores y ejecuta comandos por su cuenta.

En este tutorial construimos un primer agente en Python, le configuramos los permisos y le añadimos una herramienta propia y un servidor MCP. Todos los comandos y fragmentos de código salen del quickstart oficial de Agent SDK y de las páginas de documentación que enlazo por el camino.

¿Qué es un agente de IA desde el punto de vista del programador?

Según la documentación, un agente es una aplicación que realiza una tarea planificando por sí misma los siguientes pasos y llamando a herramientas: lee archivos, ejecuta comandos o edita código. La visión general, sin código, la expliqué en Qué es un agente de IA.

Para un programador, lo esencial es el bucle: el modelo piensa, llama a una herramienta, mira el resultado y decide qué hacer después. Agent SDK se encarga de ese bucle, de ejecutar las herramientas, de gestionar el contexto y de los reintentos, y nosotros solo leemos el flujo de mensajes.

La documentación distingue cuatro formas de trabajar con Claude:

  1. Agent SDK, una biblioteca que ejecuta el agente de Claude Code dentro de nuestra aplicación (en un proceso que gestionamos nosotros),
  2. Claude Code CLI, la terminal para el trabajo diario e interactivo (de eso trata mi tutorial de Claude Code),
  3. Client SDK, acceso directo a la API de Claude, donde el bucle de herramientas lo escribimos nosotros (o se lo encargamos al «tool runner», en beta),
  4. Managed Agents, un agente alojado por Anthropic y configurado a través de la API.

Este tutorial trata de la primera opción.

Paso 1: ¿cómo instalar Claude Agent SDK?

Necesitamos Python 3.10+ (o Node.js 18.14+ para TypeScript) y una cuenta en Claude Console. Primero creamos la carpeta del proyecto:

mkdir my-agent
cd my-agent

Por defecto, el agente tiene acceso a los archivos de este directorio y sus subdirectorios. La documentación recomienda el gestor de paquetes uv:

uv init
uv add claude-agent-sdk

Con pip normal (macOS y Linux) queda así:

python3 -m venv .venv
source .venv/bin/activate
pip install claude-agent-sdk

Curiosamente, normalmente no hace falta instalar Claude Code aparte: ambos SDK incluyen un binario nativo de Claude Code. La excepción son las plataformas sin paquete precompilado, como Windows ARM64 (en ese caso instalamos Claude Code a mano y el SDK lo encuentra en el PATH).

Paso 2: ¿cómo configurar la clave de API?

Creamos la clave en Claude Console y la definimos como variable de entorno en la terminal donde vamos a ejecutar el agente:

export ANTHROPIC_API_KEY=your-api-key

El SDK no carga los archivos .env automáticamente, así que si guardamos la clave en .env, tenemos que cargarla nosotros (por ejemplo, con el paquete dotenv). En lugar de una clave de Anthropic también se puede usar Amazon Bedrock, Claude Platform on AWS, Google Cloud o Microsoft Foundry, definiendo la variable correspondiente, p. ej. CLAUDE_CODE_USE_BEDROCK=1.

Una advertencia de la documentación: sin aprobación previa, Anthropic no permite que los productos creados con Agent SDK ofrezcan inicio de sesión con una cuenta de claude.ai ni que usen los límites de una suscripción. El agente funciona con una clave de API y pagamos por tokens (cómo controlarlos lo conté al hablar de los costos de la API de Claude).

Paso 3: ¿cómo escribir el primer agente de IA?

El ejemplo del quickstart es un agente que encuentra y corrige errores en el código. Primero creamos un archivo utils.py con dos errores intencionados:

def calculate_average(numbers):
    total = 0
    for num in numbers:
        total += num
    return total / len(numbers)


def get_user_name(user):
    return user["name"].upper()

calculate_average([]) fallará con una división entre cero y get_user_name(None), con un TypeError. Ahora el agente propiamente dicho, el archivo agent.py:

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ResultMessage


async def main():
    # Agentic loop: streams messages as Claude works
    async for message in query(
        prompt="Review utils.py for bugs that would cause crashes. Fix any issues you find.",
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Edit", "Glob"],  # Auto-approve these tools
            permission_mode="acceptEdits",  # Auto-approve file edits
        ),
    ):
        # Print human-readable output
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if hasattr(block, "text"):
                    print(block.text)  # Claude's reasoning
                elif hasattr(block, "name"):
                    print(f"Tool: {block.name}")  # Tool being called
        elif isinstance(message, ResultMessage):
            print(f"Done: {message.subtype}")  # Final result


asyncio.run(main())

El código tiene tres partes:

  1. query crea el bucle del agente y devuelve un iterador asíncrono, así que leemos los mensajes sobre la marcha con async for,
  2. prompt es la tarea. Claude decide por sí mismo qué herramientas usar,
  3. options es la configuración: aquí allowed_tools aprueba de antemano Read, Edit y Glob, y permission_mode="acceptEdits" acepta automáticamente los cambios en los archivos.

Lo ejecutamos:

uv run agent.py

(o python agent.py con el venv activado). El agente muestra su razonamiento y cada herramienta que llama, y al final Done: success. Después, utils.py gestiona una lista vacía y la ausencia de usuario. El agente leyó el archivo, encontró los casos límite y corrigió el código por sí solo, y nosotros no escribimos ni una sola función para manejar herramientas.

Si vemos el error Not logged in o Invalid API key, casi seguro que la variable ANTHROPIC_API_KEY no está definida en esa terminal.

Paso 4: ¿cómo decidir qué puede hacer el agente por su cuenta?

Lo que el agente es capaz de hacer depende de las herramientas. La documentación propone tres conjuntos típicos:

  1. Read, Glob, Grep: solo análisis, sin cambios en los archivos,
  2. Read, Edit, Glob: análisis y edición de código,
  3. Read, Edit, Bash, Glob, Grep: automatización completa con comandos en la terminal.

Para que el agente pueda, por ejemplo, buscar en la web o ejecutar pruebas, basta con añadir una herramienta y cambiar el prompt:

options = ClaudeAgentOptions(
    allowed_tools=["Read", "Edit", "Glob", "Bash"], permission_mode="acceptEdits"
)

Con Bash activado, el quickstart propone la tarea «Write unit tests for utils.py, run them, and fix any failures». También se le puede dar un rol al agente mediante system_prompt, por ejemplo el de un programador de Python con experiencia que respeta PEP 8.

La segunda palanca es el modo de permisos (permission_mode):

  1. "default" pasa cada llamada no aprobada a nuestra función canUseTool y, si no existe, la rechaza,
  2. "acceptEdits" acepta ediciones de archivos y comandos sencillos como mkdir o mv en el directorio de trabajo,
  3. "plan" hace que el agente primero estudie el código y prepare un plan,
  4. "dontAsk" nunca pregunta: solo funciona lo que aprobamos de antemano y el resto se rechaza (bueno para agentes sin una persona al teclado),
  5. "auto" pasa las acciones por un clasificador que revisa cada una y la bloquea o la permite,
  6. "bypassPermissions" lo ejecuta todo sin preguntar y, según la documentación, sirve solo para entornos aislados, como CI o contenedores.

La regla de oro de la documentación: "acceptEdits" en el equipo de desarrollo y "bypassPermissions" solo donde el agente no pueda dañar nada importante. Por qué importa lo explico en la guía sobre la seguridad de los agentes de IA.

Conviene fijar también límites desde el principio: max_turns limita el número de turnos y max_budget_usd detiene el bucle cuando se supera el costo estimado. Sin ellos, el agente sigue hasta que decide que ha terminado, y con tareas abiertas como «mejora este proyecto» eso puede tardar ;)

Paso 5: ¿cómo darle al agente una herramienta propia?

Las herramientas integradas son solo el principio. Una herramienta propia se define con el decorador @tool (nombre, descripción, esquema de entrada y función) y luego se empaqueta en un servidor MCP que funciona en el mismo proceso. El ejemplo de la documentación obtiene la temperatura de la API de Open-Meteo, así que primero añadimos la biblioteca httpx:

uv add httpx

La definición de la herramienta:

from typing import Annotated, Any
import httpx
from claude_agent_sdk import tool, create_sdk_mcp_server


# Define a tool: name, description, input schema, handler
@tool(
    "get_temperature",
    "Get the current temperature at a location",
    {
        "latitude": Annotated[float, "Latitude coordinate"],
        "longitude": Annotated[float, "Longitude coordinate"],
    },
)
async def get_temperature(args: dict[str, Any]) -> dict[str, Any]:
    async with httpx.AsyncClient() as client:
        response = await client.get(
            "https://api.open-meteo.com/v1/forecast",
            params={
                "latitude": args["latitude"],
                "longitude": args["longitude"],
                "current": "temperature_2m",
                "temperature_unit": "fahrenheit",
            },
        )
        data = response.json()

    # Return a content array - Claude sees this as the tool result
    return {
        "content": [
            {
                "type": "text",
                "text": f"Temperature: {data['current']['temperature_2m']}°F",
            }
        ]
    }


# Wrap the tool in an in-process MCP server
weather_server = create_sdk_mcp_server(
    name="weather",
    version="1.0.0",
    tools=[get_temperature],
)

En el mismo archivo pasamos el servidor al agente. El nombre completo de la herramienta tiene el formato mcp__{servidor}__{herramienta} y es el que ponemos en allowed_tools para que funcione sin pedir permiso:

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage


async def main():
    options = ClaudeAgentOptions(
        mcp_servers={"weather": weather_server},
        allowed_tools=["mcp__weather__get_temperature"],
    )

    async for message in query(
        prompt="What's the temperature in San Francisco?",
        options=options,
    ):
        # ResultMessage is the final message after all tool calls complete
        if isinstance(message, ResultMessage) and message.subtype == "success":
            print(message.result)


asyncio.run(main())

El agente llama a nuestra herramienta y responde a partir del resultado. En lugar del tiempo podemos conectar cualquier cosa: nuestra base de datos, una API interna o un script.

Paso 6: ¿cómo conectar el agente a un servidor MCP?

Los servidores MCP ya hechos (del protocolo en sí hablé en Qué es MCP) se añaden en la opción mcp_servers. El ejemplo de la documentación conecta el agente por HTTP con el servidor remoto de documentación de Claude Code:

options = ClaudeAgentOptions(
    mcp_servers={
        "claude-code-docs": {
            "type": "http",
            "url": "https://code.claude.com/docs/mcp",
        }
    },
    allowed_tools=["mcp__claude-code-docs__*"],
)

El asterisco en allowed_tools aprueba todas las herramientas de ese servidor. Con el prompt «Use the docs MCP server to explain what hooks are in Claude Code», el agente busca en la documentación y devuelve una respuesta.

¿Qué hacer después del primer agente?

Agent SDK tiene también el resto de funciones de Claude Code:

  1. hooks: código propio que se ejecuta antes o después de llamar a una herramienta,
  2. subagentes para subtareas separadas,
  3. sesiones: el identificador de ResultMessage.session_id permite retomar una conversación con todo el contexto o bifurcarla,
  4. skills, comandos y memoria cargados desde el directorio .claude/, igual que en Claude Code.

Hay aplicaciones de ejemplo listas para usar (entre ellas, un asistente de correo y un agente de investigación) en el repositorio claude-agent-sdk-demos.

¿A qué hay que prestar atención?

Primero, a los costos. El contexto crece en cada turno, y un archivo grande o un comando muy verboso pueden consumir miles de tokens de golpe. Las partes fijas (el prompt de sistema, las definiciones de herramientas) se guardan en caché automáticamente, pero aun así conviene fijar max_budget_usd desde el primer día (el tope puede superarse en el costo de una respuesta, así que dejemos margen).

Segundo, a los permisos. Un agente con Bash y bypassPermissions en un portátil normal es buscarse problemas, así que dejemos la automatización completa para los contenedores.

Tercero, a la marca. Según la documentación, un producto creado con el SDK puede llamarse, por ejemplo, «Claude Agent» o « Powered by Claude», pero no «Claude Code», y no puede hacerse pasar por un producto de Anthropic.

Preguntas frecuentes

¿Cómo crear un agente de IA sin escribir el bucle desde cero?

Lo más sencillo es usar una biblioteca que ya tenga ese bucle, como Claude Agent SDK. Instalamos claude-agent-sdk, definimos ANTHROPIC_API_KEY y llamamos a query() con un prompt y una lista de herramientas permitidas. El resto, es decir, llamar a las herramientas y gestionar el contexto, lo hace el SDK.

¿Claude Agent SDK es gratis?

La biblioteca en sí no cuesta nada, pero el agente usa la API de Claude, así que pagamos por los tokens consumidos. Sin la aprobación de Anthropic no se puede conectar a una suscripción de claude.ai.

¿En qué se diferencia Agent SDK de la API de Claude?

Con el Client SDK normal (API de Claude), el bucle de herramientas lo escribimos nosotros o usamos el tool runner en beta. Agent SDK trae las herramientas integradas de Claude Code (lectura y edición de archivos, comandos, búsqueda web), permisos, sesiones y hooks.

¿Se puede escribir el agente en TypeScript?

Sí. El paquete es @anthropic-ai/claude-agent-sdk, requiere Node.js 18.14+ y, en los ejemplos de la documentación, las opciones se llaman igual que en Python, solo que en camelCase (allowedTools, permissionMode).

  • IA
  • agentes de IA
  • Claude
  • programación
  • tutorial

La IA de hoy, cada tarde

Cada tarde, las noticias de IA más importantes del día y los nuevos artículos del blog. Breve y con fuentes.

Una vez al día. Date de baja con un clic. Política de privacidad