Tool / Function-Calling Design

How tool calling actually works - the complete picture

A language model can't book a flight, run a query, or read today's price on its own - it only produces text. Tool calling bridges that gap: you describe your functions as typed schemas, the model emits a structured call when it needs one, your host executes it, and the result flows back into the conversation. Repeat the loop and a chat model becomes an agent that can act.

JSON-Schema params tool_use / tool_result Parallel calls Validation & safety
01 - What

What is tool calling?

Tool calling (also called function calling) lets a language model invoke code you control. You give the model a list of tool definitions - each with a name, a description, and a JSON-Schema for its arguments. When the model decides a tool would help, it doesn't run anything itself; it emits a structured request naming the tool and its arguments. Your application executes the function and hands the result back, and the model continues with that new information in hand.

๐Ÿ“‹ Define (you)

Declare tools as name + description + typed parameter schema. This is the contract the model reads to decide what it can do.

๐Ÿ› ๏ธ Decide (model)

Given the conversation and tools, the model emits a structured tool_use block with arguments - or answers directly if no tool is needed.

โ†ฉ๏ธ Execute & return (you)

Your host validates the args, runs the function, and sends a tool_result back so the model can finish the answer.

The core building blocks

PieceWhat it doesNotes
Tool definitionName, description, and JSON-Schema of parametersThe description is prompt - write it for the model to read
tool_use blockModel's structured request: tool name + argument objectCarries a unique id to pair with its result
Host executorValidates args, runs the function, catches errorsYour trust boundary - never execute blindly
tool_result blockReturn value (or error) sent back to the modelReferences the same tool_use_id
Agent loopRepeats call โ†’ execute โ†’ return until doneEnds when the model stops requesting tools
Key mental model: the model never runs your code - it only asks for a call in a structured, schema-shaped form. The host is always in the loop, which is exactly where you put validation, permissions, and safety.
02 - Why

Why tool calling exists

On its own a model is a closed box: no live data, no side effects, no arithmetic you can trust. Tool calling turns it into a controller that reasons about which action to take, while your code does the acting - reliably, verifiably, and within your rules.

๐ŸŒ Real-time & private data

Fetch today's inventory, a customer record, or a live price. The model reasons; your tool provides ground truth it never memorized.

๐ŸŽฌ Take real actions

Send an email, open a ticket, run a deployment. Tools let a model do things, not just describe them - turning chat into an agent.

๐Ÿ“ Structured, reliable outputs

A JSON-Schema forces arguments into typed, validated shapes, so you get parseable structure instead of free-text you must guess at.

๐Ÿ”’ Control & auditability

Every action passes through your executor, where you enforce permissions, log calls, and gate anything risky behind confirmation.

In Plain Terms

Tool calling explained with analogies

Same idea, four ways to picture it, so it clicks whoever you are.

๐ŸŽ“ For a student

Tool calling is like a take-home test where you may use a calculator. You still do the thinking, but for the arithmetic you fill in the exact numbers on the calculator, press the button, and copy the result back into your answer.

๐Ÿ‘ฉโ€๐Ÿ’ป For a developer

It's the model calling a typed API. You publish function signatures as JSON-Schema; the model returns a structured argument object; your code runs the real function and returns the value, just like an RPC where the model is the caller.

๐Ÿข For a professional

Think of a manager who delegates by filling out a proper request form. The manager decides what needs doing and specifies the details, but a specialist actually executes it and reports the outcome back.

๐Ÿฝ๏ธ Everyday version

A waiter taking a structured order to the kitchen. The waiter does not cook; they write down exactly what you want in a form the kitchen understands, hand it over, and bring back the finished dish.

03 - How

How it works under the hood

Tool calling is a multi-turn loop, not a single request. The host sends the tools plus the conversation; the model replies with either an answer or one or more tool_use blocks; the host executes and appends tool_result blocks; the loop repeats until the model is done.

๐Ÿงฉ The contract

Each tool is name + description + a JSON-Schema of parameters (types, enums, required fields). The model reads this like documentation to choose a tool and shape its arguments.

๐Ÿ” The loop

Model requests a call โ†’ host validates & runs it โ†’ host returns the result โ†’ model reads it and either calls again or answers. Parallel calls fan out and rejoin before the model continues.

The architecture at a glance

Architecture - the model decides, the host executes, results feed back
flowchart LR
    subgraph Client["๐Ÿ–ฅ๏ธ Host application"]
        U["๐Ÿ‘ค User message"] --> ORC["๐Ÿ” Agent loop"]
        ORC --> REG["๐Ÿ“‹ Tool registry + schemas"]
        VAL["โœ… Validate args"] --> EXEC["๐Ÿ› ๏ธ Execute tool"]
        EXEC --> EXT[("๐ŸŒ APIs / DB / systems")]
    end
    subgraph Model["๐Ÿง  LLM"]
        REASON["๐Ÿ’ญ Reason over tools"]
    end
    ORC --> REASON
    REASON -->|"tool_use"| VAL
    EXEC -->|"tool_result"| ORC
    ORC -->|"final text"| ANS["โœ… Answer to user"]
        

A tool schema and the call loop

// 1) You declare the tool (name + description + JSON-Schema)
{
  "name": "get_weather",
  "description": "Get the current weather for a city. Use when the user asks about weather.",
  "input_schema": {
    "type": "object",
    "properties": {
      "city":  { "type": "string", "description": "City name, e.g. 'Paris'" },
      "units": { "type": "string", "enum": ["celsius", "fahrenheit"], "default": "celsius" }
    },
    "required": ["city"]
  }
}

// 2) The loop the host runs
messages = [ user("What's the weather in Paris?") ]
while True:
    reply = model.generate(messages, tools=[get_weather, ...])
    if reply.stop_reason != "tool_use":
        return reply.text                      # model is done
    for call in reply.tool_calls:              # may be several (parallel)
        args   = validate(call.input, schema)  # reject bad args early
        result = registry[call.name](**args)   # actually run it
        messages.append(tool_result(call.id, result))
    messages.append(reply)                      # keep the tool_use turn too

Notice the id that ties each tool_result to its originating tool_use, and that the host - never the model - is the thing that validates arguments and executes code. That boundary is where safety lives.

04 - Sequence Diagrams

Detailed sequence diagrams

Three views: a single tool-call round trip, parallel tool calls that fan out and rejoin, and an invalid-arguments validation-and-retry loop.

Diagram 1 - A single tool-call round trip (the core loop)
sequenceDiagram
    autonumber
    participant U as ๐Ÿ‘ค User
    participant H as ๐Ÿ–ฅ๏ธ Host app
    participant M as ๐Ÿง  LLM
    participant T as ๐Ÿ› ๏ธ Tool

    U->>H: Ask a question
    H->>M: messages + tool definitions
    M-->>H: tool_use get_weather city=Paris
    H->>H: Validate arguments against schema
    H->>T: Execute get_weather(Paris)
    T-->>H: 22C sunny
    H->>M: tool_result for that tool_use id
    M-->>H: Final natural-language answer
    H-->>U: It is 22C and sunny in Paris
        
Diagram 2 - Parallel tool calls fan out and rejoin before the model continues
sequenceDiagram
    autonumber
    participant H as ๐Ÿ–ฅ๏ธ Host app
    participant M as ๐Ÿง  LLM
    participant W as ๐ŸŒฆ๏ธ Weather tool
    participant F as ๐Ÿ’ฑ FX tool

    H->>M: Compare weather and currency for two cities
    M-->>H: Two tool_use blocks in one turn
    Note over H: Dispatch both calls concurrently
    par Weather lookup
        H->>W: get_weather(Tokyo)
        W-->>H: 18C rain
    and FX lookup
        H->>F: get_rate(JPY, USD)
        F-->>H: 0.0064
    end
    Note over H: Join both results before replying
    H->>M: tool_result weather + tool_result fx
    M-->>H: Combined answer using both results
        
Diagram 3 - Invalid arguments: validate, report the error, let the model retry
sequenceDiagram
    autonumber
    participant H as ๐Ÿ–ฅ๏ธ Host app
    participant M as ๐Ÿง  LLM
    participant V as โœ… Validator
    participant T as ๐Ÿ› ๏ธ Tool

    H->>M: Book a flight for the user
    M-->>H: tool_use book_flight date=32/13
    H->>V: Validate args against schema
    V-->>H: Invalid date and missing passenger
    alt arguments invalid
        H->>M: tool_result is_error with reason
        M-->>H: Corrected tool_use with valid args
    end
    H->>V: Re-validate corrected args
    V-->>H: OK
    H->>T: Execute book_flight
    T-->>H: Booking confirmed
    H->>M: tool_result success
    M-->>H: Confirmation for the user
        
05 - Step by Step

The 0 โ†’ 100 flow

From defining a tool to delivering an answer built from real actions - the whole journey in order.

00
Design

Define the tool contract

Give each tool a clear name, a description written for the model, and a JSON-Schema for its parameters with types, enums, and required fields.

10
Register

Expose a minimal tool set

Hand the model only the tools this task needs. Too many overlapping tools confuse selection; a tight, well-named set improves accuracy.

20
Prompt

Send messages + tools

The host sends the conversation plus the tool definitions. The model reads the descriptions and schemas to understand what it can do.

30
Decide

Model chooses a tool

The model reasons about the request and either answers directly or emits one or more structured tool_use blocks with arguments.

40
Validate

Check the arguments

The host validates the emitted arguments against the schema - types, ranges, enums, required fields - rejecting anything malformed before it runs.

50
Authorize

Enforce permissions & safety

For side-effecting tools, check the user's rights, apply rate limits, and gate destructive actions behind confirmation or a dry run.

60
Execute

Run the function

Call the underlying API, database, or service. Parallel calls fan out concurrently; use idempotency keys so retries never double-apply.

70
Handle

Capture results or errors

Return a structured result, or a clear is_error message on failure, so the model can adapt, retry, or ask the user for missing input.

80
Return

Feed results back

Append each tool_result keyed to its tool_use id, plus the model's own tool-use turn, so the conversation stays consistent.

90
Loop

Continue or finish

The model reads the results and either requests more tools - repeating the loop - or produces a final natural-language answer.

100
Deliver

Answer grounded in actions

The user gets a response built from real data and real effects. Logs of every call feed evals and guardrail tuning over time.

Common Pitfalls

Pitfalls & anti-patterns

Most tool-calling failures come from the tool design, not the model. These are the usual culprits.

๐Ÿงฐ Too many, overlapping tools

Handing the model dozens of tools, several doing near-identical things, wrecks selection accuracy. It picks the wrong one or dithers. Expose a small, distinct set scoped to the task.

๐Ÿท๏ธ Vague names & descriptions

Names like do_thing and one-line descriptions leave the model guessing when to call and how. The description is prompt, write it to say precisely what the tool does and when to use it.

๐Ÿšซ Unvalidated arguments

Trusting the model's emitted arguments and passing them straight to an API invites bad dates, injection, and out-of-range values. Validate types, enums, and ranges against the schema before executing.

๐Ÿ’ฅ Non-idempotent side effects

Write actions with no confirmation or idempotency key double-charge, double-book, or double-send on a retry. Gate destructive actions behind approval and key them so replays are safe.

โ™ป๏ธ No error handling / infinite retry

Returning raw stack traces, or looping forever on the same failing call, burns tokens and stalls the agent. Return a clear is_error message and cap retries so the model can adapt or stop.

๐Ÿ“œ Oversized JSON schemas

Sprawling schemas with deep nesting, dozens of optional fields, and no descriptions confuse the model and bloat the prompt. Keep parameter shapes flat, minimal, and clearly documented.

How to Measure

How to measure tool calling

Track selection and execution separately, so you know whether to fix the tool set or the tools themselves.

MetricWhat it tells youGood sign
Correct tool-selection rateHow often the model picks the right tool for the taskHigh: names and descriptions are clear
Argument validity rateFraction of calls whose arguments pass schema validationHigh: schemas guide the model well
Task completion rateShare of requests the agent finishes end to endHigh: the loop resolves reliably
Tool error / exception rateHow often executions fail or throwLow: robust tools and inputs
Unnecessary-call rateCalls made when none was needed, or redundant repeatsLow: the model calls only when useful
Latency per callTime each tool round trip adds to the turnWithin your SLA and budget
Rule of thumb: if selection is wrong, fix names and descriptions and prune overlapping tools; if arguments are invalid, tighten the schema and its field descriptions. Measure both before blaming the model.
06 - Case Studies

Real-world case studies

Three representative patterns showing tool calling in production-style use.

โœˆ๏ธ

1 ยท Travel & booking assistant

Pattern: multi-step tool orchestration with guarded actions

A travel assistant plans trips end to end - searching flights, checking hotels, then booking - mixing read-only lookups with real, side-effecting purchases.

  • Read tools (search_flights, get_hotel_availability) run freely and often in parallel to compare options fast.
  • The write tool book_flight is gated: it requires explicit user confirmation and carries an idempotency key so a retry never double-books.
  • Typed, constrained params (IATA codes, ISO dates, passenger counts) are validated before any provider call, and errors are re-asked to the model.
โœ… Outcome: The assistant plans and books complex trips while a strict host boundary keeps purchases safe, confirmed, and never accidentally repeated.
๐Ÿ“Š

2 ยท Data analyst with a query tool

Pattern: natural language to structured, read-only queries

An analytics assistant answers business questions by turning them into SQL through a single, tightly-scoped query tool over the warehouse.

  • The run_sql tool accepts a query string but runs against a read-only replica with row limits and a statement timeout.
  • Structured results come back as typed rows the model can summarize, chart, or drill into with a follow-up call.
  • Malformed or unsafe queries are rejected by validation and returned as errors, prompting the model to refine and retry.
โœ… Outcome: Non-technical users get accurate, data-grounded answers, while a constrained tool keeps the warehouse safe from runaway or destructive queries.
๐Ÿ”ง

3 ยท DevOps agent taking guarded actions

Pattern: side-effecting operations with idempotency & approval

An on-call assistant triages incidents - reading logs and metrics, then executing remediation like scaling a service or rolling back a deploy.

  • Diagnostic tools (get_logs, get_metrics) are read-only and unrestricted for fast investigation.
  • Action tools (scale_service, rollback) require an approval step and run with idempotency keys so replays are safe.
  • Every call is logged with actor, arguments, and result for a full audit trail, and destructive actions support a dry-run mode first.
โœ… Outcome: The agent shortens time-to-recovery by acting on evidence, while approvals, idempotency, and audit logs keep every action reversible and accountable.
07 - Future

Where tool calling is heading

Tool calling is evolving from a single function invocation into the backbone of agentic systems - standardized, composable, and safer by design.

๐Ÿ”Œ MCP & standard tool protocols

Open standards like the Model Context Protocol let any model connect to any tool server, so integrations become plug-and-play instead of bespoke.

๐Ÿค Multi-agent tool sharing

Specialized agents expose their skills as tools to one another, composing into systems where each agent calls the right teammate for a subtask.

๐Ÿ›ก๏ธ Fine-grained permissions

Capability scopes, per-tool policies, and human-in-the-loop gates make side-effecting actions auditable and safe by default.

โšก Smarter parallelism

Models increasingly plan and dispatch independent calls at once, cutting latency for tasks that touch many systems.

๐ŸŽฏ Tool-use evals as first-class

Measuring selection accuracy, argument validity, and recovery from errors becomes the metric that governs agent reliability.

๐Ÿง  Self-correcting agents

Agents that read tool errors, reflect, and retry with corrected arguments - turning brittle calls into robust, resilient workflows.

Bottom line: tool calling is how a text-only model becomes a system that can see live data and take real action - under your validation, permissions, and audit. As protocols standardize and agents compose, well-designed tools become the most durable part of any AI product.