¿Qué es el uso de herramientas?
Tus flujos de trabajo existentes dependen de muchas tecnologías diferentes: software de gestión de proyectos, bases de datos, archivos. Claude no puede simplemente revisar estas cosas por sí mismo. En cambio, depende de herramientas, que le dan a Claude acceso a datos y acciones externas.
Qué es una herramienta
En pocas palabras, una herramienta es una función que defines y expones a Claude. Describes qué hace y qué entradas recibe, y Claude decide cuándo llamarla.
Esto es lo clave que debes interiorizar: Claude no ejecuta la herramienta, tu código lo hace. El flujo se ve así:
- Claude solicita una llamada a herramienta.
- Tu código ejecuta la función.
- El resultado vuelve a Claude, y este continúa.
Cómo se definen las herramientas
Las herramientas son esquemas JSON con tres partes: un nombre, una descripción y un esquema de entrada. Se las pasas a Claude en el cuerpo de la solicitud como un arreglo tools.
La descripción es lo que Claude lee para decidir si llamar a la herramienta. Si escribes una descripción vaga, obtienes un mal uso de herramientas. Esta es la razón número uno por la que los agentes fallan o no toman las herramientas que tienen disponibles. Sé específico.
Así es como se ve la definición de una herramienta:
{
"name": "lookup_building_code",
"description": "Look up a specific building code section by its identifier. Returns the full text of that code section.",
"input_schema": {
"type": "object",
"properties": {
"section": {
"type": "string",
"description": "The building code section to look up"
}
},
"required": ["section"]
}
}Entonces, ¿qué sucede cuando usamos esto? Supongamos que le enviamos a un agente un informe de cumplimiento. En el primer turno, Claude responde con stop_reason: "tool_use", esa es nuestra señal. Así es como se ve esa respuesta:

Nuestro bucle llama a lookup_building_code con el parámetro que Claude solicitó, y luego devuelve el resultado como un resultado de herramienta: un mensaje de usuario que contiene un bloque tool_result vinculado al id de la llamada a la herramienta:

Y Claude continúa. En ese punto, podemos seguir llamando a herramientas y devolviendo resultados a Claude hasta que tenga lo que necesita.
Múltiples herramientas: dejar que Claude elija
Una herramienta es útil, pero la parte interesante es darle a Claude múltiples herramientas y observar cuál elige usar, y en qué orden.
Imagina este escenario: estás empacando para un viaje de tres días a Denver, y quieres tanto el clima de hoy como el pronóstico para los próximos días. Así que declaramos dos herramientas en lugar de una:
const tools = [
{
name: "get_weather",
description: "Get today's current weather for a city.",
input_schema: {
type: "object",
properties: {
city: { type: "string", description: "The city to check" }
},
required: ["city"]
}
},
{
name: "get_forecast",
description: "Get the weather forecast for the next few days for a city.",
input_schema: {
type: "object",
properties: {
city: { type: "string", description: "The city to check" }
},
required: ["city"]
}
}
];El bucle es idéntico a los bucles de agentes que ya hemos visto. La única pieza nueva es una función runTool que despacha según el nombre de la herramienta con una sentencia switch; este bloque de código es simplemente donde tu código realmente se ejecuta:
function runTool(name, input) {
switch (name) {
case "get_weather":
return getWeather(input.city);
case "get_forecast":
return getForecast(input.city);
}
}
while (true) {
const response = await client.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
messages,
tools,
});
if (response.stop_reason !== "tool_use") {
// Claude terminó — esta es la respuesta final
break;
}
messages.push({ role: "assistant", content: response.content });
const toolResults = response.content
.filter((block) => block.type === "tool_use")
.map((block) => ({
type: "tool_result",
tool_use_id: block.id,
content: runTool(block.name, block.input),
}));
messages.push({ role: "user", content: toolResults });
}Y ese es todo el patrón. ¿Quieres una tercera herramienta? Agrégala al arreglo, agrega un caso al switch, y listo.
Ejecuta esto, y verás a Claude llamar a get_weather y luego a get_forecast, a veces en el mismo turno, a veces uno después del otro. Luego responde: empaca capas, espera ráfagas de nieve hoy, con calentamiento a lo largo de la semana.
Ahora fíjate en cómo eligió Claude. Leyó las descripciones, relacionó tu prompt con "el clima de hoy" y "los próximos días", y eligió la herramienta correcta para cada uno. Por eso tus descripciones de herramientas realmente importan.
El ejecutor de herramientas: evita el código repetitivo
Probablemente ya hayas notado dos señales de alerta con lo que acabamos de escribir:
- Eso es mucho código para dos búsquedas simples.
- En una base de código real, no quieres escribir a mano esquemas JSON para cada función que tengas. Es como escribir tu código dos veces.
Ahí es donde entra el ejecutor de herramientas (tool runner). Se incluye en beta en los SDKs de Claude: TypeScript, Python, Ruby, C#, Go, Java y PHP. Defines cada herramienta una vez, y el ejecutor maneja internamente todo el bucle de uso de herramientas / resultado de herramienta.
En TypeScript, el asistente recomendado del ejecutor, betaZodTool(), describe cada herramienta con un esquema breve escrito en Zod, una biblioteca de TypeScript para declarar y validar la forma de los datos. El asistente necesita Zod 3.25.0 o posterior, lo cual una instalación nueva te proporciona:
npm install zodTu código se reduce a: describir la herramienta, enviar el prompt, esperar el resultado. Aquí está la misma demostración del clima con dos herramientas, conectada a través del ejecutor de herramientas:
import { betaZodTool } from "@anthropic-ai/sdk/helpers/beta/zod";
import { z } from "zod";
// Envuelve las mismas dos búsquedas que ejecutamos a mano, cada una con un esquema Zod breve
const weatherTool = betaZodTool({
name: "get_weather",
description: "Get today's current weather for a city.",
inputSchema: z.object({
city: z.string().describe("The city to check"),
}),
run: async ({ city }) => getWeather(city),
});
const forecastTool = betaZodTool({
name: "get_forecast",
description: "Get the weather forecast for the next few days for a city.",
inputSchema: z.object({
city: z.string().describe("The city to check"),
}),
run: async ({ city }) => getForecast(city),
});
const runner = client.beta.messages.toolRunner({
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [
{
role: "user",
content:
"I'm packing for a three-day trip to Denver. What's the weather today and over the next few days?",
},
],
tools: [weatherTool, forecastTool],
});
// Espera (await) al runner para obtener el mensaje final tras resolverse todo el ping-pong de herramientas
const finalMessage = await runner;El mismo escenario, con una fracción del código:
- Sin bucle while, sin switch de razón de parada, sin empujar manualmente los resultados de herramientas de vuelta a los mensajes; el ejecutor se encarga de todo eso.
- Sin esquemas JSON escritos a mano, solo un breve esquema Zod por herramienta, que también valida la entrada que Claude envía.
- Cada función
runenvuelve la misma búsqueda que ejecutamos a mano hace un momento. - Esperar al ejecutor devuelve el mensaje final del asistente una vez que todo se ha resuelto.
Ejecútalo, y obtienes la misma respuesta.
Las herramientas reales envuelven tu código existente
En la vida real, tus herramientas no serían datos de clima codificados de forma fija. Envolverían funciones reales que ya tienes en tu aplicación.
Toma un agente de revisión de cumplimiento: sus herramientas son envoltorios delgados alrededor de las funciones lookup_building_code y search_building_code que ya existen en la base de código. Con el ejecutor de herramientas, envuelves cada una de esas funciones en una breve definición de herramienta con su propio esquema Zod, y el agente cita secciones específicas del código en cada hallazgo que escribe:

Resumen
- Las herramientas le dan a Claude acceso a tus sistemas. Una herramienta es una función que defines y expones; Claude decide cuándo llamarla, y tu código la ejecuta.
- Las herramientas son esquemas JSON con un nombre, una descripción y un esquema de entrada, pasados en la solicitud como un arreglo
tools. - Escribe descripciones específicas. Las descripciones vagas son la razón número uno por la que los agentes fallan.
stop_reason: "tool_use"es tu señal para ejecutar la herramienta y devolver el resultado como un resultado de herramienta.- Para múltiples herramientas, despacha según el nombre de la herramienta. Agregar una herramienta significa agregarla al arreglo y agregar un caso.
- El ejecutor de herramientas del SDK (disponible en beta en todos los SDKs de Claude) maneja todo el bucle, y en TypeScript cada herramienta es una breve definición con un esquema Zod. O puedes ejecutar el bucle tú mismo.
- Tú ejecutas, o delegas el bucle. En el extremo más lejano de ese espectro, los agentes gestionados delegan todo el agente a Anthropic.