Claude API Tool Use in Node.js / TypeScript

Function calling with Claude in Node.js. Define tools in JSON Schema, handle tool_use blocks, and return results for multi-step agent loops.

💥 50p impulse-buy: Power Prompts PDF (first 10 buyers) 30 battle-tested Claude Code prompts · 8-page PDF · paste into CLAUDE.md and never re-type a prompt again · 50p impulse-buy, no commitment

This example shows a complete agent loop: define tools, detect a tool_use stop reason, execute the function, and return results to Claude.

Basic tool definition

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const tools: Anthropic.Tool[] = [
  {
    name: "get_stock_price",
    description: "Get the current stock price for a ticker symbol.",
    input_schema: {
      type: "object",
      properties: {
        ticker: { type: "string", description: "Stock ticker e.g. AAPL, MSFT" }
      },
      required: ["ticker"]
    }
  }
];

Agent loop

async function runAgent(userMessage: string): Promise<string> {
  const messages: Anthropic.MessageParam[] = [
    { role: "user", content: userMessage }
  ];

  while (true) {
    const response = await client.messages.create({
      model: "claude-sonnet-4-6",
      max_tokens: 1024,
      tools,
      messages
    });

    if (response.stop_reason === "end_turn") {
      const textBlock = response.content.find(b => b.type === "text");
      return textBlock?.type === "text" ? textBlock.text : "";
    }

    if (response.stop_reason === "tool_use") {
      const toolResults: Anthropic.ToolResultBlockParam[] = [];

      for (const block of response.content) {
        if (block.type === "tool_use") {
          const input = block.input as { ticker: string };
          const price = await getStockPrice(input.ticker); // your implementation
          toolResults.push({
            type: "tool_result",
            tool_use_id: block.id,
            content: JSON.stringify({ ticker: input.ticker, price })
          });
        }
      }

      messages.push({ role: "assistant", content: response.content });
      messages.push({ role: "user", content: toolResults });
    }
  }
}

const answer = await runAgent("What are the current prices of Apple and Microsoft stock?");
console.log(answer);

See the Python tool use example for the equivalent in Python. For structured JSON output without tools, see the JSON output example.

Frequently asked questions

How do I type tool inputs in TypeScript?
Cast `block.input` to your expected type: `const input = block.input as { city: string }`. Alternatively, use a Zod schema to validate and parse the input at runtime.
What happens if Claude calls a tool that doesn't exist?
Claude only calls tools you defined in the `tools` array of that specific request. If you filter tools between turns, include all tools the model may need for the entire agent loop.
Should I use tool_choice: 'required' to force tool use?
Only if your application always needs a tool call (e.g. structured extraction). For general assistants, omit `tool_choice` and let Claude decide. Forcing tool use when the model doesn't need it wastes tokens and can produce worse outputs.

Free tools

Cost Calculator → API Cookbook → Diff Summarizer → Skills Browser →

More examples

Claude API Python QuickstartClaude API Node.js / TypeScript QuickstartClaude API Streaming in PythonClaude API Streaming in Node.js / TypeScriptClaude API Tool Use in PythonClaude Prompt Caching in Python