← Blog

How to Build an AI Agent with Tool Calling

2026-09-24 · 5 min read · SubToAPI Team

Building an AI agent with tool calling means giving a language model access to functions it can invoke — search, database lookups, calculators, API calls — and letting it decide when and how to use them to complete a task. The model doesn't execute code itself; it outputs a structured request describing which tool to call and with what arguments, your application runs that function, and you feed the result back so the model can continue reasoning or respond to the user.

This article walks through the actual mechanics: how tool calling works under the hood, how to structure the agent loop, common failure modes, and how to get it running quickly using an API.

What "Tool Calling" Actually Means

When you send a request to a modern LLM API, you can include a list of tool definitions — each one a name, a description, and a JSON schema for its parameters. The model reads the conversation, decides whether a tool is needed, and if so, returns a structured object instead of (or alongside) plain text, specifying the tool name and arguments.

Your code is responsible for:

  1. Parsing that tool call request
  2. Executing the actual function (hitting a database, calling a weather API, running a calculation)
  3. Sending the result back to the model as a new message
  4. Letting the model decide the next step — call another tool, or respond to the user

This request/execute/respond cycle is the entire mechanism behind "agents." There's no magic — it's a loop with structured JSON in the middle.

Step 1: Define Your Tools with Clear Schemas

The single biggest factor in reliable tool calling is schema quality. Vague descriptions produce vague (or wrong) tool calls.

{
  "name": "get_order_status",
  "description": "Look up the current status of a customer order by order ID. Returns shipping status, estimated delivery, and tracking number.",
  "input_schema": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "The order ID, formatted like ORD-12345"
      }
    },
    "required": ["order_id"]
  }
}

Keep descriptions specific about what the tool does, what it returns, and any constraints (formats, ranges, units). Models rely entirely on this text to decide when to call the tool — there's no other signal.

Step 2: Build the Agent Loop

A minimal agent loop looks like this in JavaScript:

async function runAgent(userMessage, tools) {
  let messages = [{ role: "user", content: userMessage }];

  while (true) {
    const response = await callModel(messages, tools);

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

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

    return response.content;
  }
}

The loop keeps running until the model stops requesting tools and returns a final text answer. Most agents cap this at some maximum number of iterations (5–10 is typical) to avoid infinite loops from a misbehaving prompt or flaky tool.

Step 3: Handle Errors Inside the Loop, Not Around It

A common mistake is treating tool execution failures as application-level errors that crash the loop. Instead, feed the error back to the model as a tool result:

try {
  const result = await executeTool(toolCall.name, toolCall.input);
  return { tool_use_id: toolCall.id, content: JSON.stringify(result) };
} catch (err) {
  return {
    tool_use_id: toolCall.id,
    content: JSON.stringify({ error: err.message }),
    is_error: true
  };
}

Models are generally good at recovering — retrying with different arguments, trying a different tool, or explaining to the user why something failed — as long as they actually see the error instead of the conversation just breaking.

Step 4: Limit What Tools Can Do

Tool calling gives the model real-world side effects. Before wiring up anything that writes data, sends emails, or spends money, add guardrails:

Step 5: Pick the Right Model API

Tool calling quality varies significantly between models — some are much better at picking the correct tool, filling in schemas correctly, and knowing when not to call a tool. If your agent depends on Claude's tool-use behavior specifically, you need a way to call it from your backend or app without dealing with raw provider credentials, billing tiers, or key rotation yourself.

This is where SubToAPI fits: it turns your existing Claude access into a standard HTTPS API with application-scoped keys (sub_live_...), so each service or team member gets its own key instead of sharing one credential. Tool use, streaming, and usage metadata all work through the same interface — see the tool use docs for the exact request format, or the quickstart to get a key running in a few minutes.

A basic call with tools defined looks like this:

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4",
    "max_tokens": 1024,
    "tools": [{
      "name": "get_order_status",
      "description": "Look up order status by order ID",
      "input_schema": {
        "type": "object",
        "properties": { "order_id": { "type": "string" } },
        "required": ["order_id"]
      }
    }],
    "messages": [{ "role": "user", "content": "Where is order ORD-12345?" }]
  }'

For teams building multiple agents, seat-based plans (Solo €9, Team €19/seat, Scale €49/seat) mean you don't need to renegotiate access every time someone new joins the project — see pricing for details, and there's a free trial at signup.

Step 6: Test with Adversarial Inputs

Before shipping, test your agent against:

Agents that work well on the happy path often break down on these edge cases, and that's where most production bugs live.

Questions

Do I need a special "agent framework" to build tool calling? No. Tool calling is a request/response loop you can build with plain code, as shown above. Frameworks add convenience for complex multi-agent orchestration, but a single well-scoped agent rarely needs one.

How many tools can I give a model at once? Technically dozens, but accuracy drops as the list grows and tools become similar. Keep it under 10–15 well-differentiated tools per agent; split broader tasks into separate agents if needed.

Can the model call multiple tools in one turn? Some models support returning several tool calls in a single response, which you then execute (in parallel or sequence) before responding. Check the specific API's messages docs for supported behavior.

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 →