La "programmatic tool calling" (llamada programática de herramientas) permite que Claude escriba código que llama a tus herramientas de forma programática 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 en flujos de trabajo con múltiples herramientas y disminuye el consumo de tokens al permitir que Claude filtre o procese los datos antes de que lleguen a la "context window" (ventana de contexto) del modelo. En benchmarks de búsqueda agéntica como BrowseComp y DeepSearchQA, que evalúan la investigación web de múltiples pasos y la recuperación de información compleja, agregar la llamada programática de herramientas sobre herramientas de búsqueda básicas mejoró el rendimiento en un promedio del 11% mientras usaba un 24% menos de tokens de entrada (consulta Improved web search with dynamic filtering).
Considera verificar el cumplimiento del presupuesto de 20 empleados: el enfoque tradicional requiere 20 viajes de ida y vuelta al modelo por separado, incorporando miles de partidas de gastos al contexto en el proceso. Con la llamada programática de herramientas, un solo script ejecuta las 20 consultas, filtra los resultados y devuelve únicamente los empleados que excedieron sus límites, reduciendo lo que Claude necesita razonar de cientos de kilobytes a unas pocas líneas.
La llamada programática de herramientas requiere code_execution_20260120 o posterior, que es compatible con los siguientes modelos:
| Modelo |
|---|
| Claude Fable 5 () |
| Claude Mythos 5 () |
| Claude Opus 5 () |
| Claude Opus 4.8 () |
| Claude Opus 4.7 () |
| Claude Opus 4.6 () |
| Claude Sonnet 5 () |
| Claude Sonnet 4.6 () |
| Claude Opus 4.5 () |
| Claude Sonnet 4.5 () |
Para la matriz completa de versiones de la herramienta de ejecución de código, consulta la tabla de compatibilidad de modelos de la herramienta de ejecución de código. La llamada programática de herramientas está disponible en la Claude API, Claude Platform on AWS y Microsoft Foundry. En Microsoft Foundry, la llamada programática de herramientas requiere un despliegue Hosted on Anthropic. Actualmente no está disponible en Amazon Bedrock ni en Google Cloud.
Aquí tienes un ejemplo en el que Claude consulta una base de datos de forma programática varias veces y agrega los resultados. Agregar allowed_callers: ["code_execution_20260120"] a la definición de una herramienta es lo que hace que esa herramienta pueda llamarse desde la ejecución de código (consulta El campo allowed_callers):
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-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_20260120", "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_20260120"],
},
],
)
print(response)La respuesta se detiene con stop_reason: "tool_use", un ID de container y un bloque tool_use para query_database cuyo campo caller identifica la ejecución de código que lo llamó. Devuelve el resultado como se muestra en el Paso 3 del flujo de trabajo de ejemplo para que el código pueda finalizar.
Cuando configuras una herramienta para que pueda llamarse desde la ejecución de código y Claude determina que esa herramienta es necesaria:
tool_useEste enfoque es particularmente útil para:
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_20260120"]
}Valores posibles:
["direct"] - Se guía a Claude para que llame a esta herramienta directamente (valor predeterminado si se omite)["code_execution_20260120"] - Se guía a Claude para que llame a esta herramienta solo desde la ejecución de código["direct", "code_execution_20260120"] - Claude puede llamar a esta herramienta directamente o desde la ejecución de códigoTanto "code_execution_20260120" como "code_execution_20260521" se aceptan en allowed_callers y son intercambiables: una solicitud que use cualquiera de las dos versiones de la herramienta de ejecución de código satisface a las herramientas que listan cualquiera de los dos llamadores. Los bloques de respuesta siempre etiquetan al llamador como code_execution_20260120 independientemente de la versión que haya declarado la solicitud.
caller en las respuestasCada bloque de uso de herramientas incluye un campo caller que indica cómo fue invocado:
Invocación directa (uso de herramientas 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_20260120",
"tool_id": "srvtoolu_abc123"
}
}El tool_id es el id del bloque server_tool_use de ejecución de código que realizó la llamada, por lo que puedes asociar cada tool_use programático con la ejecución de código que lo produjo.
La llamada programática de herramientas usa los mismos contenedores que la ejecución de código:
container, junto con una marca de tiempo expires_atexpires_at te indica cuánto tiempo le queda al contenedor. Actualmente, los contenedores inactivos se recuperan después de unos 5 minutos, y ningún contenedor puede reutilizarse más de 30 días después de su creación.Así funciona un flujo completo de llamada programática de herramientas:
Envía una solicitud con ejecución de código y una herramienta que permita la llamada programática. Para habilitar la llamada programática, agrega el campo allowed_callers a la definición de tu herramienta.
La forma de la solicitud es idéntica al ejemplo de Inicio rápido: incluye code_execution en tu lista de herramientas, agrega allowed_callers: ["code_execution_20260120"] a cualquier herramienta que quieras que Claude invoque desde código y envía tu mensaje de usuario. Los pasos restantes de este flujo de trabajo usan el mensaje de usuario "Query customer purchase history from the last quarter and identify our top 5 customers by revenue".
Claude escribe código que llama a 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": "import json\n\nrows = json.loads(await query_database({'sql': '<sql>'}))\ntop_customers = sorted(rows, 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_20260120",
"tool_id": "srvtoolu_abc123"
}
}
],
"container": {
"id": "container_xyz789",
"expires_at": "2026-01-20T14:30:00Z"
},
"stop_reason": "tool_use"
}Envía el historial completo de la conversación más el resultado de tu herramienta. Tres detalles importan en esta solicitud:
tool_result. Consulta Restricciones de formato de mensajes.container de la respuesta pausada. La API rechaza una continuación que tenga llamadas programáticas de herramientas pendientes pero ningún ID de contenedor.tools que en la solicitud original. La herramienta de ejecución de código debe seguir presente para que el código pausado se reanude, y las herramientas que envíes en esta solicitud son las definiciones que Claude y el código en ejecución pueden usar durante el resto del turno.response = client.messages.create(
model="claude-opus-5",
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_20260120",
"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}, ...]',
}
],
},
],
# El mismo array de herramientas que en la solicitud original
tools=[
{"type": "code_execution_20260120", "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_20260120"],
},
],
)
print(response)El código retoma donde se pausó y procesa tu resultado. Cada respuesta de continuación o bien se pausa de nuevo con más bloques tool_use programáticos, o bien completa la ejecución de código y permite que Claude continúe el turno (Paso 5). Revisa stop_reason y el caller de cada bloque tool_use para distinguir ambos casos: una respuesta que se pausa esperándote tiene stop_reason: "tool_use" y un bloque tool_use cuyo caller nombra una versión de ejecución de código, y repites el Paso 3 con un tool_result para cada llamada programática pendiente en un solo mensaje de usuario.
Una vez que la ejecución de código finaliza, 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: [{'customer_id': 'C1', 'revenue': 45000}, {'customer_id': 'C2', 'revenue': 38000}, {'customer_id': 'C5', 'revenue': 32000}, {'customer_id': 'C8', 'revenue': 28500}, {'customer_id': 'C3', 'revenue': 24000}]",
"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 procese múltiples elementos de forma eficiente:
regions = ["West", "East", "Central", "North", "South"]
results = {}
for region in regions:
rows = json.loads(await query_database({"sql": f"<sql for {region}>"}))
results[region] = sum(row["revenue"] for row in rows)
# Procesa los resultados de forma programática
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:
endpoints = ["us-east", "eu-west", "apac"]
for endpoint in endpoints:
status = await check_health({"endpoint": endpoint})
if status == "healthy":
print(f"Found healthy endpoint: {endpoint}")
break # Stop early, don't check remainingpath = "/tmp/example.txt"
file_info = json.loads(await get_file_info({"path": path}))
if file_info["size"] < 10000:
content = await read_full_file({"path": path})
else:
content = await read_file_summary({"path": path})
print(content)server_id = "srv-01"
log_text = await fetch_logs({"server_id": server_id})
errors = [line for line in log_text.splitlines() if "ERROR" in line]
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 a una herramienta:
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": {
"type": "code_execution_20260120",
"tool_id": "srvtoolu_xyz789"
}
}El resultado de tu 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 todas las llamadas a herramientas se han satisfecho y el código finaliza:
{
"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 | Dónde aparece | Descripción | Solución |
|---|---|---|---|
invalid_tool_input | error_code en el bloque de error code_execution_tool_result de la respuesta | Se pasaron parámetros no válidos a la herramienta de ejecución de código | Consulta los errores de la herramienta de ejecución de código |
invalid_request_error (en tool_choice) | Respuesta de error HTTP 400 | tool_choice nombra una herramienta cuyo allowed_callers no incluye "direct" | Agrega "direct" al allowed_callers de esa herramienta, o elimina la herramienta de tool_choice y deja que Claude la invoque desde código |
Si el resultado de tu herramienta no llega en unos 4 minutos, la llamada pendiente genera un TimeoutError dentro del código en ejecución de Claude. Claude ve el error en stderr y normalmente reintenta la llamada:
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "code_execution_result",
"stdout": "",
"stderr": "TimeoutError: Calling tool ['query_database'] timed out (no response after 270s).",
"return_code": 0,
"content": []
}
}Para evitar tiempos de espera agotados:
expires_at en las respuestasSi tu herramienta devuelve un error:
{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "Error: Query timeout - table lock exceeded 30 seconds"
}El código de Claude recibe este error y puede manejarlo adecuadamente.
strict: true no son compatibles con la llamada programáticatool_choicedisable_parallel_tool_use: true no es compatible con la llamada programáticaLas herramientas personalizadas cuyo input_schema contiene un $ref recursivo (un ciclo de referencias, como un esquema que se refiere a sí mismo) no pueden habilitarse para la llamada programática. Incluir una versión de la herramienta de ejecución de código en allowed_callers para una herramienta así hace que la solicitud falle con un 400 invalid_request_error cuyo mensaje contiene Circular $ref detected. El mismo esquema se acepta para la llamada directa de herramientas.
Para solucionar esto, haz una de las siguientes cosas:
allowed_callers (o estableciéndolo en ["direct"]). Las demás herramientas de la misma solicitud pueden seguir usando la llamada programática.description del nivel más interno, o reemplaza la propiedad recursiva con un {"type": "object"} simple cuya description explique la forma esperada.Las siguientes herramientas no pueden llamarse de forma programática:
computer_toolset_20260801 y browser_toolset_20260801), cuyo campo allowed_callers acepta únicamente "direct"Al responder a llamadas programáticas de herramientas, existen requisitos de formato estrictos:
Respuestas solo con resultados de herramientas: Si hay llamadas programáticas de herramientas pendientes esperando resultados, tu mensaje de respuesta debe contener únicamente bloques tool_result. No puedes incluir ningún contenido de texto, ni siquiera después de los resultados de las herramientas.
No válido - No se puede incluir texto al responder a llamadas programáticas de herramientas:
{
"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?" }
]
}Válido - Solo resultados de herramientas al responder a llamadas programáticas de herramientas:
{
"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 (de ejecución de código). Para las llamadas de herramientas normales del lado del cliente, puedes incluir contenido de texto después de los resultados de las herramientas.
Contenido de resultado de herramienta solo de texto: El content de cada tool_result que responde a una llamada programática debe ser una cadena o bloques text. Los tipos de bloques de contenido de imagen, documento y otros se rechazan.
Las llamadas programáticas de herramientas están sujetas a los mismos "rate limits" (límites de velocidad) que las llamadas de herramientas normales. Cada llamada a herramienta desde la ejecución de código cuenta como una invocación separada.
Al implementar herramientas definidas por el usuario que se llamarán de forma programática:
La llamada programática de herramientas reduce el consumo de tokens de tres maneras:
Por ejemplo, llamar a 10 herramientas directamente usa ~10 veces los tokens que llamarlas de forma programática y devolver un resumen.
En las evaluaciones internas de Anthropic con un modelo Claude de producción:
tools contiene entre 10 y 49 definiciones de herramientas obtienen ahorros típicos de tokens del 20% al 40% con la llamada programática de herramientas habilitada.Los ahorros reales varían según la forma de la carga de trabajo. Consulta Cuándo usar la llamada programática.
La llamada programática de herramientas usa los mismos precios que la ejecución de código. Consulta los precios de la ejecución de código para más detalles.
La llamada programática de herramientas intercambia una pequeña sobrecarga fija (inicio del contenedor, generación del script) por grandes ahorros en tokens de resultados de herramientas y viajes de ida y vuelta al modelo. Que ese intercambio valga la pena depende de la forma de la carga de trabajo.
Buen ajuste:
Mal ajuste:
Si no estás seguro, mide los tokens de entrada facturados con y sin allowed_callers en una muestra representativa de tu tráfico antes de habilitarlo de forma generalizada.
invalid_request_error al establecer tool_choice
tool_choice no puede nombrar una herramienta cuyo allowed_callers omita "direct". Agrega "direct" al allowed_callers de esa herramienta, o elimina la herramienta de tool_choice y deja que Claude la invoque desde código.Expiración del contenedor
expires_at de la respuesta pausada. El código de Claude deja de esperar un resultado después de unos 4 minutos, y actualmente los contenedores inactivos se recuperan después de unos 5 minutos.El resultado de la herramienta no se analiza correctamente
caller para confirmar la invocación programáticaClaude está entrenado con grandes cantidades de código, por lo que presentar las herramientas como funciones de Python invocables le permite aprovechar esa fortaleza:
La llamada programática de herramientas es un patrón generalizable que también puede implementarse en tu propia infraestructura. Así se comparan 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 lo ejecuta localmente donde esas funciones están definidas.
Ventajas:
Desventajas:
Úsala cuando: Tu aplicación pueda ejecutar código arbitrario de forma segura, quieras la implementación más pequeña y la oferta gestionada de Anthropic no se ajuste 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 las llamadas a herramientas fuera del sandbox.
Ventajas:
Desventajas:
Úsala cuando: La seguridad sea crítica y la solución gestionada de Anthropic no se ajuste a tus requisitos.
La llamada programática de herramientas de Anthropic es una versión gestionada de la ejecución en sandbox con un entorno Python con criterios definidos y ajustado para Claude. Anthropic se encarga de la gestión de contenedores, la ejecución de código y la comunicación segura de invocación de herramientas.
Ventajas:
Considera usar la solución gestionada de Anthropic si usas la Claude API, Claude Platform on AWS o Microsoft Foundry. En Microsoft Foundry, la llamada programática de herramientas requiere un despliegue Hosted on Anthropic.
La llamada programática de herramientas está construida sobre la infraestructura de ejecución de código y usa los mismos contenedores sandbox. Los datos del contenedor, incluidos los artefactos de ejecución y las salidas, se retienen hasta por 30 días.
Para la elegibilidad de ZDR en todas las funciones, consulta API y retención de datos.
Transmite las entradas de herramientas mediante streaming sin almacenamiento en búfer de JSON del lado del servidor para aplicaciones sensibles a la latencia.
Ejecuta código Python y bash en un contenedor aislado para analizar datos, generar archivos e iterar sobre soluciones.
Conecta Claude a herramientas y APIs externas. Consulta dónde se ejecutan las herramientas, cuándo las llama Claude y qué herramienta se ajusta a tu tarea.
Especifica esquemas de herramientas, escribe descripciones efectivas y controla cuándo Claude llama a tus herramientas.
Was this page helpful?