Las llamadas programáticas a herramientas permiten que Claude escriba código que invoca 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 "latency" (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 "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 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).
La diferencia se acumula rápidamente en flujos de trabajo reales. 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 únicamente los empleados que excedieron sus límites, reduciendo lo que Claude necesita analizar 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, 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 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 ver 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. Actualmente no están disponibles en Amazon Bedrock ni en Vertex AI.
Aquí tienes un ejemplo en el que Claude consulta programáticamente una base de datos varias veces y agrega los 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 asíncronas de Python para admitir llamadas paralelas a herramientas. Cuando Claude escribe código que llama a tus herramientas, usa await (por ejemplo, result = await query_database("<sql>")) e incluye automáticamente la función envolvente asíncrona apropiada.
La función envolvente asíncrona se omite de los ejemplos de código en esta documentación para mayor 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_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ódigoElige ["direct"] o ["code_execution_20260120"] para cada herramienta en lugar de habilitar ambos, ya que esto proporciona una orientación 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 para 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 hace referencia a la herramienta de ejecución de código que realizó la llamada programática.
Las llamadas programáticas a herramientas usan los mismos contenedores que la ejecución de código:
containerCuando una herramienta se llama programáticamente y el contenedor está esperando el resultado de tu herramienta, debes responder antes de que el contenedor expire. Monitorea el campo expires_at. Si el contenedor expira, Claude puede tratar la llamada a la herramienta como agotada por tiempo de espera y reintentarla.
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 la definición de tu 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": "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_20260120",
"tool_id": "srvtoolu_abc123"
}
}
],
"container": {
"id": "container_xyz789",
"expires_at": "2026-01-20T14:30:00Z"
},
"stop_reason": "tool_use"
}Incluye el historial completo de la conversación más el resultado de tu herramienta:
La ejecución de código continúa y procesa los resultados. Si se necesitan llamadas adicionales a herramientas, repite el Paso 3 hasta que todas las llamadas a herramientas estén satisfechas.
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 procese múltiples elementos de manera eficiente:
async def _claude_code():
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)
# 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 detener el procesamiento tan pronto como se cumplan los criterios de éxito:
async def _claude_code():
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 def _claude_code():
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 def _claude_code():
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 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 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 | Descripción | Solución |
|---|---|---|
invalid_tool_input | La entrada de la herramienta no coincide con el esquema | Valida el input_schema de tu herramienta |
invalid_request_error (en tool_choice) | 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 herramienta tarda demasiado en responder, la ejecución de código recibe un TimeoutError. Claude ve esto en stderr y normalmente reintenta:
{
"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 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 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 únicamente bloques tool_result. No puedes incluir ningún contenido de texto, ni siquiera después de los resultados de las herramientas.
Invá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 (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 las herramientas.
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 se llamarán programáticamente:
Las llamadas programáticas a herramientas pueden reducir significativamente el consumo de tokens:
Por ejemplo, llamar a 10 herramientas directamente usa aproximadamente 10 veces más tokens que llamarlas programáticamente y devolver un resumen.
En las evaluaciones internas de Anthropic con 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 obtener 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 de scripts) 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.
Buena opción:
Mala opción:
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 configurar 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 en las respuestasEl resultado de la herramienta no se analiza correctamente
caller para confirmar la invocación programáticaEl entrenamiento de Claude incluye una amplia exposición al código, lo que lo hace efectivo para razonar y encadenar llamadas a 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 permite flujos de trabajo que serían impracticables con el uso de herramientas tradicional (como procesar archivos de más de 1M de tokens) al permitir que Claude trabaje con datos programáticamente en lugar de cargar todo en el contexto de la conversación.
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 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 (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 preconfigurado y 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.
Las llamadas programáticas a herramientas se basan en 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 conocer la elegibilidad de ZDR en todas las funciones, consulta API y retención de datos.
Aprende sobre la capacidad subyacente de ejecución de código que impulsa las llamadas programáticas a herramientas.
Comprende los fundamentos del uso de herramientas con Claude.
Guía paso a paso para definir herramientas.
Was this page helpful?
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)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}, ...]',
}
],
},
],
tools=[...],
)
print(response)