M
MeshWorld.
Claude Anthropic API Agent Skills Tool Use Node.js Tutorial Agentic AI 4 min read

Agent Skills with the Claude API: tool_use From Scratch

Vishnu
By Vishnu
| Updated: Mar 12, 2026

I spent two hours reading the Anthropic docs to understand tool_use. The docs are technically correct, but they assume you already know the secret handshake. This guide assumes you don’t. I’ll show you the whole flow with code you can actually run. At its core, tool use is just a game of tag between your code and the AI. You tell Claude what tools you have. Claude asks to use one. You run the code and hand the result back. It’s that simple.

What is Claude actually doing when it “uses a tool”?

Claude doesn’t actually “run” your code. It just writes a structured request asking you to run it.

The Scenario: You’re building a support bot for an e-commerce site. A customer asks “Where is my order?” Claude doesn’t have access to your database. It stops and says “I need to use the track_order tool with ID 12345.” You run the database search, give Claude the status, and then Claude tells the customer “Your package is in Chicago.”

Think of Claude as a manager who knows what needs to happen but doesn’t have the keys to the server room. You are the one with the keys.

How do I get my environment ready?

Install the SDK first. You’ll need an API key from the Anthropic console to make anything work.

npm install @anthropic-ai/sdk

How do I tell Claude what my tool can do?

You define a tool with a name and a description. The description is the most important part because it’s what Claude reads to decide when to call the tool.

const tools = [{
  name: "get_weather",
  description: "Get current weather for a city. Use this when the user asks about rain or temperature.",
  input_schema: {
    type: "object",
    properties: {
      city: { type: "string", description: "City name" }
    },
    required: ["city"]
  }
}];

How do I start a conversation with tools enabled?

You pass the tools array into your message request. Claude will analyze the user’s message against your tool list.

const response = await client.messages.create({
  model: "claude-sonnet-4-6",
  max_tokens: 1024,
  tools: tools,
  messages: [{ role: "user", content: "What's the weather in Mumbai?" }]
});

Where does my actual code go?

If Claude wants a tool, it returns a stop_reason of "tool_use". Now you run your regular JavaScript function.

async function get_weather({ city }) {
  const res = await fetch(`https://api.example.com/weather?city=${city}`);
  return await res.json();
}

How do I give the answer back to the AI?

This is where people get stuck. You have to send the entire history back to Claude, including its original request for the tool.

const finalResponse = await client.messages.create({
  model: "claude-sonnet-4-6",
  messages: [
    { role: "user", content: "What's the weather in Mumbai?" },
    { role: "assistant", content: response.content }, // Claude's request
    {
      role: "user",
      content: [{
        type: "tool_result",
        tool_use_id: toolUseBlock.id,
        content: JSON.stringify(toolResult)
      }]
    }
  ]
});

What does a complete Claude agent look like?

A real agent runs in a loop. It keeps handling tool calls until Claude finally gives a plain text answer.

The Scenario: You ask your agent to “Find a flight to Tokyo and book the cheapest one.” The agent first calls a search_flights tool. It sees the results. It then calls a book_flight tool. Finally, it tells you “I’ve booked flight NH201 for $850.” The loop handles both tool calls automatically.

Can Claude pick between different tools?

Yes. You can provide a dozen tools. Claude will only pick the one that fits the context. If you ask for the weather, it won’t touch your delete_database tool. It’s surprisingly good at picking the right hammer for the nail.

What are the biggest ways people break their Claude agents?

The most common error is “forgetting” the middle of the conversation.

The Scenario: You’re testing your new agent. You send the tool result back, but you forget to include Claude’s original “I want to use a tool” message in the history. Claude gets “amnesia.” it asks you why you’re sending random JSON data about a weather report it never asked for.

  • Message order: History must be User -> Assistant -> User (result).
  • ID matching: The tool_use_id must be exact.
  • Stringify: Always JSON.stringify your results.

What should I build next?