Las llamadas programáticas a herramientas permiten que Claude escriba código que llama a tus herramientas de forma programática dentro de un contenedor de code execution (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 datos antes de que lleguen a la 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 llamadas programáticas a herramientas sobre herramientas de búsqueda básicas mejoró el rendimiento en un promedio del 11% mientras se usaban 24% menos 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 separados al modelo, incorporando miles de líneas de gastos al contexto en el proceso. Con las llamadas programáticas a herramientas, un solo script ejecuta las 20 consultas, filtra los resultados y devuelve solo los empleados que excedieron sus límites, reduciendo lo que Claude necesita razonar de cientos de kilobytes a solo unas pocas líneas.
Para un análisis más profundo de los costos de inferencia y contexto que abordan las llamadas programáticas a herramientas, consulta Advanced tool use.
Esta función requiere que la herramienta de ejecución de código esté habilitada.
Esta función no es elegible para Zero Data Retention (ZDR). Los datos se conservan de acuerdo con la política de retención estándar de la función.
Las llamadas programáticas a herramientas requieren code_execution_20260120 o posterior, que es compatible con los siguientes modelos:
| Modelo |
|---|
| Claude Fable 5 (claude-fable-5) |
| Claude Mythos 5 (claude-mythos-5) |
| Claude Opus 4.8 (claude-opus-4-8) |
| Claude Opus 4.7 (claude-opus-4-7) |
| Claude Opus 4.6 (claude-opus-4-6) |
| Claude Sonnet 5 (claude-sonnet-5) |
| Claude Sonnet 4.6 (claude-sonnet-4-6) |
| Claude Opus 4.5 (claude-opus-4-5-20251101) |
| Claude Sonnet 4.5 (claude-sonnet-4-5-20250929) |
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. Las llamadas programáticas a herramientas están disponibles en la API de Claude, Claude Platform on AWS y Microsoft Foundry. En Microsoft Foundry, las llamadas programáticas a herramientas requieren una implementación Hosted on Anthropic. Actualmente no están disponibles en Amazon Bedrock ni en Google Cloud.
Aquí tienes un ejemplo donde Claude consulta programáticamente una base de datos varias veces y agrega los resultados:
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
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 sea invocable desde la ejecución de código y Claude decide usar esa herramienta:
tool_useEste enfoque es particularmente útil para:
Las herramientas que permiten un caller de ejecución de código se exponen al código de Claude como funciones asíncronas de Python, por lo que Claude puede ejecutarlas en paralelo con asyncio.gather. Cada función toma un único dict de argumentos y devuelve una cadena: el texto del tool_result que envías de vuelta. El código de Claude espera estas funciones con await de nivel superior y analiza los resultados que necesita como datos estructurados, por ejemplo rows = json.loads(await query_database({"sql": "<sql>"})).
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 dentro de la ejecución de código["direct", "code_execution_20260120"] - Claude puede llamar a esta herramienta directamente o desde dentro de la ejecución de códigoTanto "code_execution_20260120" como "code_execution_20260521" se aceptan en allowed_callers y son intercambiables: una solicitud que usa cualquiera de las versiones de la herramienta de ejecución de código satisface las herramientas que listan cualquiera de los callers. Los bloques de respuesta siempre etiquetan el caller como code_execution_20260120 independientemente de qué versión declaró la solicitud.
Elige ["direct"] o ["code_execution_20260120"] para cada herramienta en lugar de habilitar ambos, ya que esto proporciona una guía más clara a Claude sobre cómo usar mejor la herramienta.
allowed_callers controla cómo se presenta la herramienta a Claude y se valida contra tool_choice, pero no es un bloqueo estricto a nivel de API sobre la invocación directa. Claude está fuertemente guiado a respetarlo, pero tu cliente debe estar preparado para manejar un tool_use directo para cualquier herramienta que defina. No confíes en allowed_callers como un límite de seguridad.
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.
Las llamadas programáticas a herramientas usan 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. Los contenedores inactivos actualmente se recuperan después de aproximadamente 5 minutos, y ningún contenedor puede reutilizarse más de 30 días después de su creación.Mientras el código de Claude está esperando un resultado de herramienta programática, la llamada pendiente expira después de aproximadamente 4 minutos y genera un TimeoutError dentro del código. Devuelve cada resultado de herramienta mucho antes de la marca de tiempo expires_at en la respuesta pausada. Consulta Expiración del contenedor durante la llamada a herramienta.
Así es como funciona un flujo completo de llamadas programáticas a herramientas:
Envía una solicitud con ejecución de código y una herramienta que permita llamadas programáticas. Para habilitar las llamadas programáticas, agrega 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 intenta 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.
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 tu resultado de 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 tiene llamadas programáticas a herramientas pendientes pero sin ID de contenedor.tools que 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ías 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-4-8",
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 se pausa nuevamente con más bloques tool_use programáticos, o 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 entre 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 se completa, 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 procesa múltiples elementos de manera 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"
}
}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 todas las llamadas a herramientas están satisfechas 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 | Dónde aparece | Descripción | Solución |
|---|---|---|---|
invalid_tool_input | error_code en el bloque de error code_execution_tool_result en 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 tu resultado de herramienta no llega dentro de aproximadamente 4 minutos, la llamada pendiente genera un TimeoutError dentro del código en ejecución de Claude. Claude ve el error en stderr y típicamente 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 prevenir 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 apropiadamente.
strict: true no son compatibles con las llamadas programáticastool_choicedisable_parallel_tool_use: true no es compatible con las llamadas programáticasLas herramientas personalizadas cuyo input_schema contiene un $ref recursivo (un ciclo de referencia, como un esquema que se refiere a sí mismo) no pueden habilitarse para llamadas programáticas. Incluir una versión de la herramienta de ejecución de código en allowed_callers para dicha herramienta hace que la solicitud falle con un 400 invalid_request_error cuyo mensaje contiene Circular $ref detected. El mismo esquema se acepta para llamadas directas a herramientas.
Para solucionar esto, haz una de las siguientes cosas:
allowed_callers (o estableciéndolo en ["direct"]). Otras herramientas en la misma solicitud aún pueden usar llamadas programáticas.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 programáticamente:
Al responder a llamadas programáticas a herramientas, existen requisitos estrictos de formato:
Respuestas solo con resultados de herramientas: Si hay llamadas programáticas a herramientas 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.
No válido - No se puede incluir texto al responder a llamadas programáticas a 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 a herramientas:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01",
"content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"
}
]
}Esta restricción solo aplica al responder a llamadas programáticas a herramientas (de ejecución de código). Para llamadas regulares a herramientas del lado del cliente, puedes incluir contenido de texto después de los resultados de 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 son rechazados.
Las llamadas programáticas a herramientas están sujetas a los mismos límites de velocidad que las llamadas regulares a herramientas. 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 serán llamadas programáticamente:
Las llamadas programáticas a herramientas reducen el consumo de tokens de tres maneras:
Por ejemplo, llamar a 10 herramientas directamente usa ~10x los tokens de llamarlas programáticamente y devolver un resumen.
En las evaluaciones internas de Anthropic sobre un modelo de Claude en producción:
tools contiene de 10 a 49 definiciones de herramientas ven ahorros típicos de tokens del 20% al 40% con las llamadas programáticas a herramientas habilitadas.Los ahorros reales varían según la forma de la carga de trabajo. Consulta Cuándo usar llamadas programáticas.
Las llamadas programáticas a herramientas usan 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 programáticas a herramientas: Los resultados de herramientas de invocaciones programáticas no cuentan para tu uso de tokens de entrada/salida. Solo cuentan el resultado final de la ejecución de código y la respuesta de Claude.
Las llamadas programáticas a herramientas intercambian 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. Si ese intercambio vale 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 ampliamente.
invalid_request_error al establecer tool_choice
tool_choice no puede nombrar una herramienta cuyo allowed_callers omite "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 aproximadamente 4 minutos, y los contenedores inactivos actualmente se recuperan después de aproximadamente 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 usar esa fortaleza:
Las llamadas programáticas a herramientas son un patrón generalizable que también puede implementarse en tu propia infraestructura. Así es como 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:
Úsalo cuando: Tu aplicación puede ejecutar código arbitrario de forma segura, quieres la implementación más pequeña 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 (sandbox) con restricciones de seguridad (por ejemplo, sin salida de red). Si tus herramientas requieren recursos externos, necesitarás un protocolo para ejecutar llamadas a herramientas fuera del sandbox.
Ventajas:
Desventajas:
Úsalo cuando: La seguridad es crítica y la solución gestionada de Anthropic no se ajusta a tus requisitos.
Las llamadas programáticas a herramientas de Anthropic son una versión gestionada de la ejecución en sandbox con un entorno Python con opiniones definidas, optimizado 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 estás usando la API de Claude, Claude Platform on AWS o Microsoft Foundry. En Microsoft Foundry, las llamadas programáticas a herramientas requieren una implementación Hosted on Anthropic.
Las llamadas programáticas a herramientas están construidas sobre la infraestructura de ejecución de código y usan 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 entradas de herramientas 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. Descubre 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?