Claude Agent SDK: Tool Use and Function Calling

· 5 min read

Overview

Tools are what transform a language model from a text generator into an agent that acts in the world. Without tools, an agent can only describe what it would do. With tools, it can query databases, call APIs, read files, send notifications, and make decisions based on live data. Tool use is the foundation of every useful agent system.

The Claude Agent SDK provides a structured approach to defining tools: typed input schemas, execution functions, and result handling that feeds tool outputs back into the agent's reasoning loop. The SDK manages the multi-turn conversation flow — the agent decides which tool to call, the SDK executes it, and the result becomes part of the agent's context for the next step.

Understanding tool design deeply matters because tool definitions are the primary interface between your agent and your application logic. A well-designed tool set makes agents more capable and predictable. A poorly designed one leads to agents that call wrong tools, pass bad arguments, or miss available capabilities entirely.

When to use it

Use custom tools when your agent needs to:

Avoid creating tools for tasks the model handles well natively, such as summarization, translation, or general reasoning. Adding unnecessary tools clutters the agent's decision space and increases the chance of incorrect tool selection.

The decision boundary is straightforward: if the task requires access to information or capabilities outside the model's context window, it needs a tool. If the task is purely about reasoning over provided text, it probably does not.

Getting started

Define tools with clear schemas

Good tool definitions have descriptive names, precise descriptions, and constrained input schemas. The model uses all three to decide when and how to call each tool.

import { Tool } from "@anthropic-ai/agent-sdk";
import { z } from "zod";

const searchKnowledgeBase = new Tool({
  name: "search_knowledge_base",
  description:
    "Search the internal knowledge base for articles matching a query. " +
    "Returns up to 5 relevant articles with titles, snippets, and relevance scores. " +
    "Use this when the user asks about product features, policies, or procedures.",
  inputSchema: z.object({
    query: z.string().min(3).describe("Search query, 3+ characters"),
    category: z
      .enum(["product", "billing", "technical", "policy"])
      .optional()
      .describe("Optional category filter to narrow results"),
    maxResults: z
      .number()
      .int()
      .min(1)
      .max(10)
      .default(5)
      .describe("Number of results to return"),
  }),
  async execute({ query, category, maxResults }) {
    const filters: Record<string, string> = {};
    if (category) filters.category = category;

    const results = await knowledgeBaseClient.search(query, {
      filters,
      limit: maxResults,
    });

    return {
      resultCount: results.length,
      articles: results.map((r) => ({
        title: r.title,
        snippet: r.snippet,
        relevanceScore: r.score,
        articleId: r.id,
        lastUpdated: r.updatedAt.toISOString(),
      })),
    };
  },
});

Chain tools for multi-step operations

Some tasks require multiple tool calls in sequence. Design tools as composable units that the agent can chain together.

const getOrderDetails = new Tool({
  name: "get_order_details",
  description:
    "Retrieve full details for a specific order by order ID. " +
    "Includes line items, shipping status, and payment information.",
  inputSchema: z.object({
    orderId: z.string().regex(/^ORD-[A-Z0-9]{8}$/, "Must be format ORD-XXXXXXXX"),
  }),
  async execute({ orderId }) {
    const order = await db.orders.findById(orderId);
    if (!order) {
      return { found: false, error: `No order found with ID ${orderId}` };
    }
    return {
      found: true,
      order: {
        id: order.id,
        status: order.status,
        items: order.items.map((i) => ({
          name: i.productName,
          quantity: i.quantity,
          price: i.unitPrice,
        })),
        total: order.totalAmount,
        shippingAddress: order.shippingAddress,
        trackingNumber: order.trackingNumber,
      },
    };
  },
});

const initiateRefund = new Tool({
  name: "initiate_refund",
  description:
    "Start a refund for a specific order. The agent should first retrieve " +
    "order details using get_order_details to confirm the order exists and " +
    "is eligible for refund before calling this tool.",
  inputSchema: z.object({
    orderId: z.string().regex(/^ORD-[A-Z0-9]{8}$/),
    reason: z.enum(["defective", "wrong_item", "not_received", "changed_mind"]),
    itemIds: z.array(z.string()).optional().describe("Specific items to refund, or omit for full order"),
  }),
  async execute({ orderId, reason, itemIds }) {
    const refund = await paymentService.createRefund({
      orderId,
      reason,
      itemIds: itemIds ?? "all",
    });

    return {
      refundId: refund.id,
      amount: refund.amount,
      estimatedProcessingDays: refund.estimatedDays,
      status: refund.status,
    };
  },
});

Build an agent with a focused tool set

Assign each agent only the tools it needs. A smaller, focused tool set leads to more accurate tool selection.

import { Agent } from "@anthropic-ai/agent-sdk";

const customerSupportAgent = new Agent({
  name: "customer-support",
  model: "claude-sonnet-4-20250514",
  instructions: `You are a customer support agent. Help customers with
    order inquiries, refunds, and product questions.

    Always look up order details before discussing order status.
    Always confirm order eligibility before initiating a refund.
    Use the knowledge base for product and policy questions.`,
  tools: [
    searchKnowledgeBase,
    getOrderDetails,
    initiateRefund,
  ],
});

const result = await customerSupportAgent.run(
  "I want a refund for order ORD-A1B2C3D4, the item arrived damaged",
  { maxTurns: 10 }
);

Integration with agent teams

Tool design directly affects multi-agent coordination. In a Fork-Join pattern, different agents might need overlapping tool access — a research agent and a verification agent both need search tools, but only the verification agent needs the fact-checking tool.

const researchTools = [webSearchTool, documentReaderTool, dataExtractorTool];
const verificationTools = [webSearchTool, factCheckTool, sourceValidatorTool];
const synthesisTools = [summarizerTool, citationFormatterTool];

const researchAgent = new Agent({
  name: "researcher",
  model: "claude-sonnet-4-20250514",
  instructions: "Gather information from multiple sources on the given topic.",
  tools: researchTools,
});

const verificationAgent = new Agent({
  name: "verifier",
  model: "claude-sonnet-4-20250514",
  instructions: "Cross-check research findings for accuracy and source reliability.",
  tools: verificationTools,
});

const synthesisAgent = new Agent({
  name: "synthesizer",
  model: "claude-sonnet-4-20250514",
  instructions: "Combine verified research into a cohesive summary with citations.",
  tools: synthesisTools,
});

When agents in a team share tools, ensure the tools are stateless or properly handle concurrent access. Two agents calling the same database tool simultaneously should not corrupt shared state.

Best practices and common pitfalls

  1. Write tool descriptions for the model, not for developers. The description is the model's primary signal for when to use a tool. Include when to use it, what it returns, and any prerequisites. Avoid jargon the model might not map correctly to use cases.

  2. Constrain input schemas tightly. Use enums instead of free-form strings when the set of valid values is known. Add regex patterns for structured identifiers. The tighter the schema, the fewer invalid tool calls.

  3. Return structured data, not prose. Tool outputs that return structured objects (with named fields, arrays, and clear types) are easier for agents to reason about than unstructured text blocks. Include explicit status fields (found: true/false, success: true/false).

  4. Avoid tools with overlapping responsibilities. If two tools both search for customer information but in slightly different ways, the agent will frequently pick the wrong one. Either merge them with a parameter to control behavior, or make their use cases clearly distinct in the descriptions.

  5. Test tool selection independently. Before testing full agent conversations, verify that the model selects the correct tool for representative inputs. Tool selection accuracy is the single biggest determinant of agent reliability.

Skip the setup — generate agent teams instantly →