import Anthropic from '@anthropic-ai/sdk'; const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY || '', }); // Define tools const tools: Anthropic.Tool[] = [ { name: 'get_weather', description: 'Get the current weather in a given location', input_schema: { type: 'object', properties: { location: { type: 'string', description: 'The city and state, e.g. San Francisco, CA', }, unit: { type: 'string', enum: ['celsius', 'fahrenheit'], description: 'The unit of temperature, either "celsius" or "fahrenheit"', }, }, required: ['location'], }, }, { name: 'get_time', description: 'Get the current time in a given timezone', input_schema: { type: 'object', properties: { timezone: { type: 'string', description: 'The IANA timezone name, e.g. America/Los_Angeles', }, }, required: ['timezone'], }, }, ]; // Mock tool implementations function executeWeatherTool(location: string, unit?: string): string { // In production, call actual weather API const temp = unit === 'celsius' ? 22 : 72; return `The weather in ${location} is sunny and ${temp}°${unit === 'celsius' ? 'C' : 'F'}`; } function executeTimeTool(timezone: string): string { // In production, get actual time for timezone const time = new Date().toLocaleTimeString('en-US', { timeZone: timezone }); return `The current time in ${timezone} is ${time}`; } // Example 1: Basic tool use detection async function basicToolUse() { const message = await anthropic.messages.create({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, tools, messages: [ { role: 'user', content: 'What is the weather like in San Francisco?', }, ], }); console.log('Stop reason:', message.stop_reason); if (message.stop_reason === 'tool_use') { console.log('\nClaude wants to use tools:'); for (const block of message.content) { if (block.type === 'tool_use') { console.log(`- Tool: ${block.name}`); console.log(` ID: ${block.id}`); console.log(` Input:`, block.input); } } } return message; } // Example 2: Tool execution loop async function toolExecutionLoop(userMessage: string) { const messages: Anthropic.MessageParam[] = [ { role: 'user', content: userMessage }, ]; while (true) { const response = await anthropic.messages.create({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, tools, messages, }); console.log('\nStop reason:', response.stop_reason); // Add assistant response to messages messages.push({ role: 'assistant', content: response.content, }); // Check if Claude wants to use tools if (response.stop_reason === 'tool_use') { const toolResults: Anthropic.ToolResultBlockParam[] = []; // Execute each tool for (const block of response.content) { if (block.type === 'tool_use') { console.log(`\nExecuting tool: ${block.name}`); console.log('Input:', block.input); let result: string; // Execute the appropriate tool if (block.name === 'get_weather') { result = executeWeatherTool( block.input.location as string, block.input.unit as string | undefined ); } else if (block.name === 'get_time') { result = executeTimeTool(block.input.timezone as string); } else { result = `Unknown tool: ${block.name}`; } console.log('Result:', result); toolResults.push({ type: 'tool_result', tool_use_id: block.id, content: result, }); } } // Add tool results to messages messages.push({ role: 'user', content: toolResults, }); } else { // Final response - no more tools needed const textBlock = response.content.find(block => block.type === 'text'); if (textBlock && textBlock.type === 'text') { console.log('\nFinal response:', textBlock.text); return textBlock.text; } break; } } } // Example 3: Multiple tools in one turn async function multipleToolsInOneTurn() { const messages: Anthropic.MessageParam[] = [ { role: 'user', content: 'What is the weather in New York and what time is it in Tokyo?', }, ]; const response = await anthropic.messages.create({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, tools, messages, }); console.log('Claude requested', response.content.filter(b => b.type === 'tool_use').length, 'tools'); if (response.stop_reason === 'tool_use') { const toolResults: Anthropic.ToolResultBlockParam[] = []; for (const block of response.content) { if (block.type === 'tool_use') { console.log(`\n- ${block.name}:`, block.input); let result: string; if (block.name === 'get_weather') { result = executeWeatherTool(block.input.location as string); } else if (block.name === 'get_time') { result = executeTimeTool(block.input.timezone as string); } else { result = 'Unknown tool'; } toolResults.push({ type: 'tool_result', tool_use_id: block.id, content: result, }); } } // Continue conversation with tool results messages.push({ role: 'assistant', content: response.content }); messages.push({ role: 'user', content: toolResults }); const finalResponse = await anthropic.messages.create({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, tools, messages, }); const textBlock = finalResponse.content.find(b => b.type === 'text'); if (textBlock && textBlock.type === 'text') { console.log('\nFinal answer:', textBlock.text); } } } // Example 4: Error handling in tool execution async function toolExecutionWithErrorHandling(userMessage: string) { const messages: Anthropic.MessageParam[] = [ { role: 'user', content: userMessage }, ]; try { const response = await anthropic.messages.create({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, tools, messages, }); messages.push({ role: 'assistant', content: response.content }); if (response.stop_reason === 'tool_use') { const toolResults: Anthropic.ToolResultBlockParam[] = []; for (const block of response.content) { if (block.type === 'tool_use') { try { let result: string; if (block.name === 'get_weather') { result = executeWeatherTool(block.input.location as string); } else if (block.name === 'get_time') { result = executeTimeTool(block.input.timezone as string); } else { throw new Error(`Unknown tool: ${block.name}`); } toolResults.push({ type: 'tool_result', tool_use_id: block.id, content: result, }); } catch (error) { // Return error to Claude toolResults.push({ type: 'tool_result', tool_use_id: block.id, content: `Error executing tool: ${error.message}`, is_error: true, }); } } } messages.push({ role: 'user', content: toolResults }); // Get final response const finalResponse = await anthropic.messages.create({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, tools, messages, }); const textBlock = finalResponse.content.find(b => b.type === 'text'); if (textBlock && textBlock.type === 'text') { console.log('Final response:', textBlock.text); } } } catch (error) { console.error('API error:', error); throw error; } } // Run examples if (require.main === module) { console.log('=== Basic Tool Use ===\n'); basicToolUse() .then(() => { console.log('\n\n=== Tool Execution Loop ===\n'); return toolExecutionLoop('What is the weather in London and what time is it there?'); }) .then(() => { console.log('\n\n=== Multiple Tools ===\n'); return multipleToolsInOneTurn(); }) .then(() => { console.log('\n\n=== Error Handling ===\n'); return toolExecutionWithErrorHandling('What is the weather in Mars?'); }) .catch(console.error); } export { basicToolUse, toolExecutionLoop, multipleToolsInOneTurn, toolExecutionWithErrorHandling };