← Blog

How to Build an AI Agent With Claude Tools

2026-10-28 · 5 min read · SubToAPI Team

Building an AI agent with Claude tools means giving the model a set of functions it can call — search a database, hit an internal API, run a calculation — and letting it decide when and how to use them to complete a task. Claude doesn't execute code itself; it tells your application which tool to run and with what arguments, you run it, and you feed the result back. That request/response cycle, repeated until the task is done, is the entire mechanism behind "AI agents."

If you've used Claude for single-turn Q&A, the shift to agents is mostly architectural: instead of one call, you build a loop that keeps the model, the tools, and the conversation state in sync. Below is a practical walkthrough of that loop, from defining tools to handling multi-step tool calls correctly.

What Makes an AI Agent Different From a Chatbot

A chatbot takes input and returns text. An agent takes input, decides it needs more information or needs to take an action, requests that action through a tool call, receives the result, and continues reasoning — sometimes across several tool calls — before producing a final answer. The "agent" behavior isn't a special API mode; it's just tool use plus a loop in your code that keeps calling the model until it stops asking for tools.

This pattern works for a wide range of use cases: a support agent that looks up order status, a research assistant that queries a search API, a scheduling agent that checks a calendar and books events. The tools are yours — Claude only decides which to invoke and with what inputs.

Step 1: Define Your Tools

Each tool needs a name, a description Claude will use to decide when it's relevant, and a JSON Schema for its inputs. Keep descriptions specific — vague tool descriptions cause the model to either ignore a useful tool or call the wrong one.

{
  "name": "get_order_status",
  "description": "Look up the current status of a customer order by order ID",
  "input_schema": {
    "type": "object",
    "properties": {
      "order_id": { "type": "string", "description": "The order ID, e.g. ORD-12345" }
    },
    "required": ["order_id"]
  }
}

Start with as few tools as the task needs. Agents with ten overlapping tools are harder for the model to route correctly than agents with three well-defined ones.

Step 2: Send the Request With Tool Definitions

Pass your tools array alongside the conversation. The model will either answer directly or return a tool_use content block.

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "tools": [ /* your tool definitions */ ],
    "messages": [
      { "role": "user", "content": "What is the status of order ORD-12345?" }
    ]
  }'

Step 3: Handle Tool Use Responses

When Claude wants to use a tool, the response's stop_reason is tool_use, and the content array includes a block with the tool name and input:

{
  "type": "tool_use",
  "id": "toolu_01A...",
  "name": "get_order_status",
  "input": { "order_id": "ORD-12345" }
}

Your application code parses this, runs the actual function, and prepares the result to send back.

if (response.stop_reason === "tool_use") {
  const toolCall = response.content.find(c => c.type === "tool_use");
  const result = await getOrderStatus(toolCall.input.order_id);

  conversation.push({ role: "assistant", content: response.content });
  conversation.push({
    role: "user",
    content: [{
      type: "tool_result",
      tool_use_id: toolCall.id,
      content: JSON.stringify(result)
    }]
  });
}

Step 4: Loop Until the Agent Finishes

Send the updated conversation back to Claude. It may call another tool, call the same tool again with different arguments, or produce a final text answer. Your loop should keep going until stop_reason is anything other than tool_use, with a sensible max-iterations cap so a malfunctioning agent doesn't call tools indefinitely.

let iterations = 0;
while (iterations < 8) {
  const response = await callClaude(conversation);
  if (response.stop_reason !== "tool_use") {
    return response.content; // final answer
  }
  await handleToolUse(response, conversation);
  iterations++;
}

This small loop, plus solid tool definitions, is genuinely the core of most production agents — the complexity usually lives in the tools themselves (auth, rate limits, error handling), not in the orchestration logic.

Handling Errors and Edge Cases

Tools fail — a lookup returns nothing, an API times out, an argument is malformed. Return these as tool results too, with a clear error message, rather than throwing exceptions that break the loop:

content: JSON.stringify({ error: "Order not found", order_id: toolCall.input.order_id })

Claude generally handles this gracefully and will either retry with corrected input or explain the failure to the user. Also validate tool inputs before executing them — the model is good at following your schema, but you should never trust tool arguments blindly, especially for anything that writes data or calls paid APIs.

Running the Agent in Production

Once the loop works locally, the operational concerns are the usual ones: API key management, per-user usage tracking, retry logic on transient errors, and streaming partial output for longer agent runs so users aren't staring at a spinner.

If you're wiring Claude into a product rather than a personal script, SubToAPI sits in front of your existing Claude access and gives you application-specific API keys (sub_live_...), streaming, and per-key usage metadata without extra infrastructure. Tool use works the same way you'd use it directly — see /docs/tools — and /docs/streaming covers streaming the agent's final response back to a UI while it's still generating. The quickstart gets a working agent loop calling the API in a few minutes, and pricing starts at €9/month with a free trial at signup.

Questions

Do I need a framework to build a Claude agent? No. The agent loop is about 20 lines of code: call the model, check stop_reason, run the tool if requested, append the result, repeat. Frameworks add convenience for multi-agent orchestration, but a single-agent tool loop is simple enough to write directly against the Messages API.

How many tools can an agent have? There's no hard limit, but accuracy drops as tool count and overlap increase. Keep tool sets focused per agent — if you need many unrelated capabilities, consider splitting into multiple specialized agents rather than one agent with dozens of tools.

Can the agent call multiple tools in one turn? Yes, Claude can return multiple tool_use blocks in a single response when it determines several calls are needed before continuing. Your loop should execute all of them and return all corresponding tool_result blocks together in the next message.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →