Claude Agent SDK: cómo construir agentes de producción con "Claude Code como librería" (tutorial en Python) — Cesar Ayala
← Todos los artículos

Claude Agent SDK: cómo construir agentes de producción con "Claude Code como librería" (tutorial en Python)

El Claude Agent SDK es "Claude Code como librería": en lugar de escribir a mano el bucle `while stop_reason == "tool_use"` contra la Messages API cruda, una sola llamada a `query()` te da el motor de Claude Code — herramientas integradas, el agent loop y la gestión de contexto — ejecutando las herramientas de forma autónoma en Python o TypeScript. Instala `claude-agent-sdk`, define `ANTHROPIC_API_KEY`, pasa `allowed_tools` y consume el stream.

Qué es el Claude Agent SDK (y su relación con Claude Code)

El Claude Agent SDK es “Claude Code como biblioteca”: en lugar de escribir a mano el bucle while stop_reason == "tool_use" contra la Messages API cruda, una sola llamada a query() te da el mismo motor que mueve a Claude Code — las herramientas integradas, el agent loop y la gestión de contexto — ejecutando las herramientas de forma autónoma en Python o TypeScript. Instalas claude-agent-sdk, defines ANTHROPIC_API_KEY, pasas allowed_tools y consumes el stream de mensajes. Eso es todo lo que necesitas para tu primer agente de producción.

La idea clave es que Claude Code y el Agent SDK comparten motor. El SDK es exactamente eso mismo pero invocable desde tu código: el mismo agent loop, las mismas herramientas (Read, Write, Bash, Grep), la misma capacidad de cargar .claude/ con skills y CLAUDE.md. La diferencia es la interfaz. La CLI es para trabajo interactivo; el SDK es para meterlo dentro de una app, un pipeline de CI/CD o un servicio en producción.

La distinción clave frente a la API cruda

Aquí está la línea que separa este post de los demás. Cuando construyes un agente contra la Messages API cruda — la Anthropic Client SDK — tú escribes el bucle de tool-use. Recibes una respuesta con stop_reason == "tool_use", ejecutas la herramienta a mano, empaquetas el resultado en un mensaje tool_result y vuelves a llamar a la API. Repites hasta que Claude deje de pedir herramientas. Ese patrón exacto es lo que mostré en el post de construir un agente autónomo con Sonnet 5.

Con el Agent SDK, Claude ejecuta las herramientas de forma autónoma y tú solo consumes el stream. No hay bucle que mantener, no hay tool_result que serializar, no hay parsing de stop_reason. El SDK gestiona todo el ciclo por dentro.

Messages API cruda

  • Tú escribes el bucle while stop_reason tool-use
  • Tú ejecutas cada herramienta a mano
  • Tú serializas el tool_result y reenvías
  • Control total, más código repetitivo

Claude Agent SDK

  • query() corre el agent loop por ti
  • Claude ejecuta las tools de forma autónoma
  • Solo consumes el stream de mensajes
  • Herramientas y gestión de contexto incluidas

Piénsalo así: la Client SDK te da el modelo y te deja armar el agente. El Agent SDK te da el agente ya armado y te deja programarlo.

Instalación y autenticación

El SDK vive en dos lenguajes. En Python necesitas Python 3.10+.

pip install claude-agent-sdk

En TypeScript, el paquete trae empaquetado un binario nativo de Claude Code, así que no instalas Claude Code por separado:

npm install @anthropic-ai/claude-agent-sdk

Para autenticarte, define la variable ANTHROPIC_API_KEY con tu clave de la Console:

export ANTHROPIC_API_KEY="sk-ant-..."

Si corres sobre un proveedor cloud, puedes apuntar el SDK con flags de entorno: CLAUDE_CODE_USE_BEDROCK=1, CLAUDE_CODE_USE_VERTEX=1 o CLAUDE_CODE_USE_FOUNDRY=1. Una nota importante: Anthropic no permite que productos de terceros ofrezcan login de claude.ai, así que en tu app siempre usas autenticación por API key, no login de usuario.

Tu primer agente: query() y el stream de mensajes

El corazón del SDK es la función asíncrona query(). Importas query y ClaudeAgentOptions, pasas un prompt y la lista de herramientas permitidas, y recorres el stream con async for:

import anyio
from claude_agent_sdk import query, ClaudeAgentOptions

async def main():
    async for message in query(
        prompt="Lee pyproject.toml y dime qué dependencias declara.",
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Grep", "Bash"],
        ),
    ):
        print(message)

anyio.run(main)

No escribiste ningún bucle de tool-use. Claude decide leer el archivo, ejecuta Read por su cuenta, quizá lanza un Grep, y tú solo ves pasar los mensajes. El equivalente en TypeScript es simétrico:

import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Lee pyproject.toml y dime qué dependencias declara.",
  options: { allowedTools: ["Read", "Grep", "Bash"] },
})) {
  console.log(message);
}

El stream trae varios tipos de mensaje: uno de inicialización (con el session_id, que usarás más adelante), los mensajes del asistente, los resultados de herramientas y un mensaje final. Consumir el stream es todo tu trabajo.

  1. Envías el promptquery() abre la sesión y devuelve el init con session_id
  2. Claude decideEl modelo elige una herramienta de allowed_tools
  3. El SDK la ejecutaRead, Bash, Grep corren sin código tuyo
  4. Consumes el streamRecorres los mensajes con async for hasta el resultado final

Las herramientas integradas

El SDK trae un conjunto de herramientas integradas listas para usar, sin que escribas una sola línea de código de ejecución. Son las mismas de Claude Code:

Read / Write / Editleer y modificar archivos
Bashejecutar comandos de shell
Glob / Grepbuscar archivos y contenido
WebSearch / WebFetchbuscar y traer contenido de la web
Monitor / AskUserQuestionvigilar procesos y preguntar al usuario

Tú controlas cuáles habilitas con allowed_tools. Si no pones Bash en la lista, el agente no puede ejecutar shell — punto. Este es tu primer mecanismo de seguridad: el modelo solo puede tocar lo que tú le autorizaste. Un agente de solo lectura que analiza un repo se queda con ["Read", "Glob", "Grep"]; uno que corrige código necesita además ["Write", "Edit", "Bash"].

Conecta TUS herramientas vía mcp_servers

Las herramientas integradas cubren el sistema de archivos, la shell y la web. Pero tu agente de producción necesita hablar con tu base de datos, tu API de facturación o tu CRM. Ahí entra MCP: pasas la opción mcp_servers para conectar servidores externos que exponen tus propias herramientas.

from claude_agent_sdk import query, ClaudeAgentOptions

options = ClaudeAgentOptions(
    allowed_tools=["Read", "Grep", "mcp__facturacion__crear_cfdi"],
    mcp_servers={
        "facturacion": {
            "command": "python",
            "args": ["-m", "mi_servidor_cfdi"],
        },
    },
)

El agente descubre las herramientas del servidor y las usa junto a las integradas. Para entender por qué MCP es la forma correcta de darle datos a un agente, revisa conectar un agente de IA a tus datos con MCP. Y antes de exponer nada en producción, lee cómo asegurar servidores MCP, porque un servidor mal configurado es una puerta abierta.

Funciones de poder: hooks, subagentes, permisos y sesiones

Aquí el SDK deja de ser un juguete y se vuelve infraestructura. Cuatro capacidades reflejan lo que ya hace Claude Code:

Hooks. Interceptas el ciclo de vida con callbacks. Un PreToolUse puede bloquear una herramienta antes de que corra; un PostToolUse puede registrar o validar el resultado. Los conectas con HookMatcher:

from claude_agent_sdk import ClaudeAgentOptions, HookMatcher

async def bloquea_rm(input_data, tool_use_id, context):
    cmd = input_data.get("tool_input", {}).get("command", "")
    if "rm -rf" in cmd:
        return {"permissionDecision": "deny", "reason": "comando peligroso"}
    return {}

options = ClaudeAgentOptions(
    allowed_tools=["Bash"],
    hooks={"PreToolUse": [HookMatcher(matcher="Bash", hooks=[bloquea_rm])]},
)

Subagentes. Defines agentes especializados con AgentDefinition y el agente principal los invoca a través de la herramienta Agent — para eso agregas "Agent" a allowed_tools. Cada subagente tiene su propio prompt y su propio conjunto de herramientas, lo cual mantiene el contexto limpio.

from claude_agent_sdk import ClaudeAgentOptions, AgentDefinition

options = ClaudeAgentOptions(
    allowed_tools=["Read", "Grep", "Agent"],
    agents={
        "revisor": AgentDefinition(
            description="Revisa código en busca de bugs",
            prompt="Eres un revisor de código riguroso.",
            tools=["Read", "Grep"],
        ),
    },
)

Permisos. Además de allowed_tools, controlas el modo con permission_mode. Por ejemplo, permission_mode="acceptEdits" deja que el agente aplique ediciones de archivo sin pedir confirmación en cada una — útil en automatización desatendida donde ya limitaste el radio de impacto de un error.

Sesiones. El agente es stateless entre llamadas, pero puedes continuar una conversación. Capturas el session_id del mensaje de inicialización y lo pasas como resume en la siguiente query():

options = ClaudeAgentOptions(
    allowed_tools=["Read", "Edit"],
    resume=session_id,  # tomado del mensaje init anterior
)

Esto te permite construir agentes que retoman trabajo tras un reinicio, o flujos de varias etapas que preservan lo aprendido.

Cuándo usar el SDK, la CLI o Managed Agents

Las tres opciones comparten motor, pero resuelven problemas distintos.

Claude Code CLI — dev interactivo, tareas puntualesterminal
Agent SDK — apps, CI/CD, producción en tu infratu proceso
Managed Agents — agente hospedado por AnthropicREST

La Claude Code CLI y el Agent SDK tienen las mismas capacidades; cambia la interfaz. La CLI es para desarrollo interactivo y tareas de una sola vez. El Agent SDK es para cuando el agente vive dentro de tu aplicación: lo llamas desde tu código, corres el agent loop en tu propio proceso e infraestructura, y tienes control total sobre hooks, permisos y logging.

Managed Agents es la otra dirección: una API REST hospedada donde Anthropic corre el agent loop y el sandbox por ti. No manejas infraestructura, pero tampoco la controlas. Muchos equipos usan ambos — el SDK donde necesitan control fino, Managed Agents donde quieren cero operaciones.

Una última nota de branding: cuando publiques tu producto construido sobre el SDK, no puedes llamarlo “Claude Code”. Usa “Claude Agent” o “Powered by Claude”.

Si quieres profundizar en el ecosistema, revisa qué es un agente de IA para los fundamentos, y el hub de agentes de IA para el mapa completo.

Fuentes oficiales: