Tool use (también llamado function calling) permite que Claude solicite la ejecución de funciones definidas por ti cuando necesita información que no tiene o cuando debe tomar una acción externa. Es la base para construir agentes de IA que interactúan con sistemas reales.
El ciclo de tool use
El flujo tiene varios pasos:
- Envías el mensaje del usuario junto con las definiciones de herramientas disponibles
- Claude responde con
stop_reason: "tool_use"y una lista de herramientas que quiere invocar - Tú ejecutas las herramientas y recopilas los resultados
- Envías los resultados de vuelta a Claude
- Claude responde con el mensaje final
Definición de herramientas
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic();
const tools: Anthropic.Tool[] = [
{
name: 'obtener_clima',
description: 'Obtiene el clima actual para una ciudad específica',
input_schema: {
type: 'object',
properties: {
ciudad: {
type: 'string',
description: 'Nombre de la ciudad, ej: "Madrid"'
},
unidades: {
type: 'string',
enum: ['celsius', 'fahrenheit'],
description: 'Unidades de temperatura'
}
},
required: ['ciudad']
}
},
{
name: 'buscar_vuelos',
description: 'Busca vuelos disponibles entre dos ciudades',
input_schema: {
type: 'object',
properties: {
origen: { type: 'string' },
destino: { type: 'string' },
fecha: { type: 'string', description: 'Formato YYYY-MM-DD' }
},
required: ['origen', 'destino', 'fecha']
}
}
];
El ciclo completo implementado
async function runWithTools(userMessage: string) {
const messages: Anthropic.MessageParam[] = [
{ role: 'user', content: userMessage }
];
while (true) {
const response = await client.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 4096,
tools,
messages
});
// Si no hay tool use, tenemos la respuesta final
if (response.stop_reason === 'end_turn') {
const textBlock = response.content.find(b => b.type === 'text');
return textBlock?.text ?? '';
}
// Procesar tool use
if (response.stop_reason === 'tool_use') {
// Añadir la respuesta del asistente al historial
messages.push({ role: 'assistant', content: response.content });
// Ejecutar cada herramienta solicitada
const toolResults: Anthropic.ToolResultBlockParam[] = [];
for (const block of response.content) {
if (block.type === 'tool_use') {
const result = await executeToolCall(block.name, block.input);
toolResults.push({
type: 'tool_result',
tool_use_id: block.id,
content: JSON.stringify(result)
});
}
}
// Añadir resultados al historial
messages.push({ role: 'user', content: toolResults });
}
}
}
// Simulación de ejecución de herramientas
async function executeToolCall(name: string, input: unknown) {
switch (name) {
case 'obtener_clima':
return { temperatura: 22, condicion: 'soleado', ciudad: (input as any).ciudad };
case 'buscar_vuelos':
return { vuelos: [{ hora: '10:30', precio: 150, aerolinea: 'Iberia' }] };
default:
throw new Error(`Herramienta desconocida: ${name}`);
}
}
// Uso
const resultado = await runWithTools(
'¿Qué clima hace en Madrid hoy y hay vuelos desde Barcelona para mañana?'
);
console.log(resultado);
Tool choice: controlar cuándo se usan las herramientas
// Forzar que Claude use una herramienta específica
const response = await client.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
tools,
tool_choice: { type: 'tool', name: 'obtener_clima' },
messages: [{ role: 'user', content: '¿Cómo está el tiempo?' }]
});
Errores comunes
No manejar el ciclo completo: Si hay múltiples herramientas o el modelo quiere varias iteraciones, necesitas el bucle while.
Tool results sin el tool_use_id: Cada resultado debe referenciar el ID de la herramienta que lo solicitó.
No limitar las iteraciones: Añade un contador máximo al bucle para evitar loops infinitos.
Fuentes: Documentación oficial de Tool Use de Anthropic, guía de mejores prácticas para agentes.