La llamada de herramientas programática permite que Claude escriba código que llama tus herramientas programáticamente dentro de un contenedor de ejecución de código, en lugar de requerir viajes de ida y vuelta a través del modelo para cada invocación de herramienta. Esto reduce la latencia para flujos de trabajo de múltiples herramientas y disminuye el consumo de tokens al permitir que Claude filtre o procese datos antes de que lleguen a la ventana de contexto del modelo.
La llamada de herramientas programática está actualmente en beta pública.
Para usar esta función, añade el encabezado beta "advanced-tool-use-2025-11-20" beta header a tus solicitudes de API.
Esta función requiere que la herramienta de ejecución de código esté habilitada.
La llamada de herramientas programática está disponible en los siguientes modelos:
| Modelo | Versión de herramienta |
|---|---|
Claude Opus 4.5 (claude-opus-4-5-20251101) | code_execution_20250825 |
Claude Sonnet 4.5 (claude-sonnet-4-5-20250929) | code_execution_20250825 |
La llamada de herramientas programática está disponible a través de la API de Claude y Microsoft Foundry.
Aquí hay un ejemplo simple donde Claude consulta programáticamente una base de datos varias veces y agrega resultados:
Cuando configuras una herramienta para que sea invocable desde la ejecución de código y Claude decide usar esa herramienta:
tool_useEste enfoque es particularmente útil para:
Las herramientas personalizadas se convierten en funciones Python asincrónicas para soportar llamadas de herramientas paralelas. Cuando Claude escribe código que llama tus herramientas, usa await (por ejemplo, result = await query_database("<sql>")) e incluye automáticamente la función de envoltura asincrónica apropiada.
La envoltura asincrónica se omite de los ejemplos de código en esta documentación por claridad.
allowed_callersEl campo allowed_callers especifica qué contextos pueden invocar una herramienta:
{
"name": "query_database",
"description": "Execute a SQL query against the database",
"input_schema": {...},
"allowed_callers": ["code_execution_20250825"]
}Valores posibles:
["direct"] - Solo Claude puede llamar esta herramienta directamente (predeterminado si se omite)["code_execution_20250825"] - Solo invocable desde dentro de la ejecución de código["direct", "code_execution_20250825"] - Invocable tanto directamente como desde la ejecución de códigoRecomendamos elegir ["direct"] o ["code_execution_20250825"] para cada herramienta en lugar de habilitar ambas, ya que esto proporciona una orientación más clara a Claude sobre cómo usar mejor la herramienta.
caller en respuestasCada bloque de uso de herramienta incluye un campo caller que indica cómo fue invocado:
Invocación directa (uso de herramienta tradicional):
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": {"sql": "\<sql\>"},
"caller": {"type": "direct"}
}Invocación programática:
{
"type": "tool_use",
"id": "toolu_xyz789",
"name": "query_database",
"input": {"sql": "\<sql\>"},
"caller": {
"type": "code_execution_20250825",
"tool_id": "srvtoolu_abc123"
}
}El tool_id hace referencia a la herramienta de ejecución de código que realizó la llamada programática.
La llamada de herramientas programática utiliza los mismos contenedores que la ejecución de código:
containerCuando una herramienta se llama programáticamente y el contenedor está esperando tu resultado de herramienta, debes responder antes de que el contenedor expire. Monitorea el campo expires_at. Si el contenedor expira, Claude puede tratar la llamada de herramienta como agotada por tiempo y reintentar.
Aquí se muestra cómo funciona un flujo completo de llamada de herramientas programática:
Envía una solicitud con ejecución de código y una herramienta que permite llamadas programáticas. Para habilitar llamadas programáticas, añade el campo allowed_callers a tu definición de herramienta.
Proporciona descripciones detalladas del formato de salida de tu herramienta en la descripción de la herramienta. Si especificas que la herramienta devuelve JSON, Claude intentará deserializar y procesar el resultado en código. Cuanto más detalle proporciones sobre el esquema de salida, mejor podrá Claude manejar la respuesta programáticamente.
Claude escribe código que llama tu herramienta. La API se pausa y devuelve:
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I'll query the purchase history and analyze the results."
},
{
"type": "server_tool_use",
"id": "srvtoolu_abc123",
"name": "code_execution",
"input": {
"code": "results = await query_database('<sql>')\ntop_customers = sorted(results, key=lambda x: x['revenue'], reverse=True)[:5]\nprint(f'Top 5 customers: {top_customers}')"
}
},
{
"type": "tool_use",
"id": "toolu_def456",
"name": "query_database",
"input": {"sql": "\<sql\>"},
"caller": {
"type": "code_execution_20250825",
"tool_id": "srvtoolu_abc123"
}
}
],
"container": {
"id": "container_xyz789",
"expires_at": "2025-01-15T14:30:00Z"
},
"stop_reason": "tool_use"
}Incluye el historial completo de conversación más tu resultado de herramienta:
La ejecución de código continúa y procesa los resultados. Si se necesitan llamadas de herramienta adicionales, repite el Paso 3 hasta que se satisfagan todas las llamadas de herramienta.
Una vez que se completa la ejecución de código, Claude proporciona la respuesta final:
{
"content": [
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "code_execution_result",
"stdout": "Top 5 customers by revenue:\n1. Customer C1: $45,000\n2. Customer C2: $38,000\n3. Customer C5: $32,000\n4. Customer C8: $28,500\n5. Customer C3: $24,000",
"stderr": "",
"return_code": 0,
"content": []
}
},
{
"type": "text",
"text": "I've analyzed the purchase history from last quarter. Your top 5 customers generated $167,500 in total revenue, with Customer C1 leading at $45,000."
}
],
"stop_reason": "end_turn"
}Claude puede escribir código que procesa múltiples elementos de manera eficiente:
# async wrapper omitted for clarity
regions = ["West", "East", "Central", "North", "South"]
results = {}
for region in regions:
data = await query_database(f"<sql for {region}>")
results[region] = sum(row["revenue"] for row in data)
# Process results programmatically
top_region = max(results.items(), key=lambda x: x[1])
print(f"Top region: {top_region[0]} with ${top_region[1]:,} in revenue")Este patrón:
Claude puede dejar de procesar tan pronto como se cumplan los criterios de éxito:
# async wrapper omitted for clarity
endpoints = ["us-east", "eu-west", "apac"]
for endpoint in endpoints:
status = await check_health(endpoint)
if status == "healthy":
print(f"Found healthy endpoint: {endpoint}")
break # Stop early, don't check remaining# async wrapper omitted for clarity
file_info = await get_file_info(path)
if file_info["size"] < 10000:
content = await read_full_file(path)
else:
content = await read_file_summary(path)
print(content)# async wrapper omitted for clarity
logs = await fetch_logs(server_id)
errors = [log for log in logs if "ERROR" in log]
print(f"Found {len(errors)} errors")
for error in errors[-10:]: # Only return last 10 errors
print(error)Cuando la ejecución de código llama una herramienta:
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": {"sql": "\<sql\>"},
"caller": {
"type": "code_execution_20250825",
"tool_id": "srvtoolu_xyz789"
}
}Tu resultado de herramienta se pasa de vuelta al código en ejecución:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "[{\"customer_id\": \"C1\", \"revenue\": 45000, \"orders\": 23}, {\"customer_id\": \"C2\", \"revenue\": 38000, \"orders\": 18}, ...]"
}
]
}Cuando se satisfacen todas las llamadas de herramienta y el código se completa:
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_xyz789",
"content": {
"type": "code_execution_result",
"stdout": "Analysis complete. Top 5 customers identified from 847 total records.",
"stderr": "",
"return_code": 0,
"content": []
}
}| Error | Descripción | Solución |
|---|---|---|
invalid_tool_input | La entrada de herramienta no coincide con el esquema | Valida el input_schema de tu herramienta |
tool_not_allowed | La herramienta no permite el tipo de llamador solicitado | Verifica que allowed_callers incluya los contextos correctos |
missing_beta_header | Encabezado beta de PTC no proporcionado | Añade ambos encabezados beta a tu solicitud |
Si tu herramienta tarda demasiado en responder, la ejecución de código recibirá un TimeoutError. Claude lo ve en stderr e intentará típicamente reintentar:
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "code_execution_result",
"stdout": "",
"stderr": "TimeoutError: Calling tool ['query_database'] timed out.",
"return_code": 0,
"content": []
}
}Para prevenir tiempos de espera:
expires_at en respuestasSi tu herramienta devuelve un error:
# Provide error information in the tool result
{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "Error: Query timeout - table lock exceeded 30 seconds"
}El código de Claude recibirá este error y puede manejarlo apropiadamente.
strict: true no son compatibles con llamadas programáticastool_choicedisable_parallel_tool_use: true no es compatible con llamadas programáticasLas siguientes herramientas actualmente no pueden ser llamadas programáticamente, pero el soporte puede añadirse en futuras versiones:
Al responder a llamadas de herramientas programáticas, hay requisitos de formato estrictos:
Respuestas solo de resultado de herramienta: Si hay llamadas de herramientas programáticas pendientes esperando resultados, tu mensaje de respuesta debe contener solo bloques tool_result. No puedes incluir ningún contenido de texto, ni siquiera después de los resultados de herramientas.
// ❌ INVÁLIDO - No puedes incluir texto al responder a llamadas de herramientas programáticas
{
"role": "user",
"content": [
{"type": "tool_result", "tool_use_id": "toolu_01", "content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"},
{"type": "text", "text": "What should I do next?"} // This will cause an error
]
}
// ✅ VÁLIDO - Solo resultados de herramientas al responder a llamadas de herramientas programáticas
{
"role": "user",
"content": [
{"type": "tool_result", "tool_use_id": "toolu_01", "content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"}
]
}Esta restricción solo se aplica al responder a llamadas de herramientas programáticas (ejecución de código). Para llamadas de herramientas regulares del lado del cliente, puedes incluir contenido de texto después de resultados de herramientas.
Las llamadas de herramientas programáticas están sujetas a los mismos límites de velocidad que las llamadas de herramientas regulares. Cada llamada de herramienta desde la ejecución de código cuenta como una invocación separada.
Al implementar herramientas personalizadas que serán llamadas programáticamente:
La llamada de herramientas programática puede reducir significativamente el consumo de tokens:
Por ejemplo, llamar 10 herramientas directamente usa ~10x los tokens de llamarlas programáticamente y devolver un resumen.
La llamada de herramientas programática utiliza los mismos precios que la ejecución de código. Consulta los precios de ejecución de código para más detalles.
Conteo de tokens para llamadas de herramientas programáticas: Los resultados de herramientas de invocaciones programáticas no cuentan hacia tu uso de tokens de entrada/salida. Solo el resultado final de ejecución de código y la respuesta de Claude cuentan.
Casos de uso buenos:
Casos de uso menos ideales:
Error "Tool not allowed"
"allowed_callers": ["code_execution_20250825"]Expiración de contenedor
expires_at en respuestasProblemas de encabezado beta
"advanced-tool-use-2025-11-20"Resultado de herramienta no analizado correctamente
caller para confirmar invocación programáticaEl entrenamiento de Claude incluye exposición extensiva a código, lo que lo hace efectivo en razonamiento y encadenamiento de llamadas de funciones. Cuando las herramientas se presentan como funciones invocables dentro de un entorno de ejecución de código, Claude puede aprovechar esta fortaleza para:
Este enfoque habilita flujos de trabajo que serían impracticables con uso de herramientas tradicional—como procesar archivos sobre 1M tokens—al permitir que Claude trabaje con datos programáticamente en lugar de cargar todo en el contexto de conversación.
La llamada de herramientas programática es un patrón generalizable que puede ser implementado fuera de la ejecución de código gestionada de Anthropic. Aquí hay una descripción general de los enfoques:
Proporciona a Claude una herramienta de ejecución de código y describe qué funciones están disponibles en ese entorno. Cuando Claude invoca la herramienta con código, tu aplicación la ejecuta localmente donde esas funciones están definidas.
Ventajas:
Desventajas:
Usar cuando: Tu aplicación puede ejecutar de forma segura código arbitrario, quieres una solución simple, y la oferta gestionada de Anthropic no se ajusta a tus necesidades.
El mismo enfoque desde la perspectiva de Claude, pero el código se ejecuta en un contenedor aislado con restricciones de seguridad (por ejemplo, sin salida de red). Si tus herramientas requieren recursos externos, necesitarás un protocolo para ejecutar llamadas de herramientas fuera del sandbox.
Ventajas:
Desventajas:
Usar cuando: La seguridad es crítica y la solución gestionada de Anthropic no se ajusta a tus requisitos.
La llamada de herramientas programática de Anthropic es una versión gestionada de ejecución aislada con un entorno Python opinado sintonizado para Claude. Anthropic maneja la gestión de contenedores, ejecución de código, e invocación de herramientas segura.
Ventajas:
Recomendamos usar la solución gestionada de Anthropic si estás usando la API de Claude.
curl https://api.anthropic.com/v1/messages \
--header "x-api-key: $ANTHROPIC_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "anthropic-beta: advanced-tool-use-2025-11-20" \
--header "content-type: application/json" \
--data '{
"model": "claude-sonnet-4-5",
"max_tokens": 4096,
"messages": [
{
"role": "user",
"content": "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue"
}
],
"tools": [
{
"type": "code_execution_20250825",
"name": "code_execution"
},
{
"name": "query_database",
"description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
"input_schema": {
"type": "object",
"properties": {
"sql": {
"type": "string",
"description": "SQL query to execute"
}
},
"required": ["sql"]
},
"allowed_callers": ["code_execution_20250825"]
}
]
}'response = client.beta.messages.create(
model="claude-sonnet-4-5",
betas=["advanced-tool-use-2025-11-20"],
max_tokens=4096,
messages=[{
"role": "user",
"content": "Query customer purchase history from the last quarter and identify our top 5 customers by revenue"
}],
tools=[
{
"type": "code_execution_20250825",
"name": "code_execution"
},
{
"name": "query_database",
"description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
"input_schema": {...},
"allowed_callers": ["code_execution_20250825"]
}
]
)response = client.beta.messages.create(
model="claude-sonnet-4-5",
betas=["advanced-tool-use-2025-11-20"],
max_tokens=4096,
container="container_xyz789", # Reuse the container
messages=[
{"role": "user", "content": "Query customer purchase history from the last quarter and identify our top 5 customers by revenue"},
{
"role": "assistant",
"content": [
{"type": "text", "text": "I'll query the purchase history and analyze the results."},
{
"type": "server_tool_use",
"id": "srvtoolu_abc123",
"name": "code_execution",
"input": {"code": "..."}
},
{
"type": "tool_use",
"id": "toolu_def456",
"name": "query_database",
"input": {"sql": "\<sql\>"},
"caller": {
"type": "code_execution_20250825",
"tool_id": "srvtoolu_abc123"
}
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_def456",
"content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}, {\"customer_id\": \"C2\", \"revenue\": 38000}, ...]"
}
]
}
],
tools=[...]
)Comprende los fundamentos del uso de herramientas con Claude.