Skip to content

How AI agents use tools: function calling in plain English

A language model on its own can only write text. It can’t look up today’s free appointment slots, check whether an invoice has been paid or create an order. Yet AI agents do exactly these things. The mechanism behind it is called function calling, or tool use.

You don’t need to write code to understand it, and it’s worth understanding if you’re deciding whether to let AI near your systems. It shows where the control sits, and the answer is reassuring: the model only asks. Your code decides what actually happens. (If you’re new to agents, start with What is an AI agent?)

The model never touches your systems

When an agent “books an appointment”, the model doesn’t log in to your calendar. It returns a structured request: the name of a tool and the inputs, as data. Your application receives that request, checks it, runs it against your system with its own permissions, and sends the result back to the model.

One tool call

  1. Model reads the request Plus instructions and the tool list
  2. Model asks for a tool Tool name and inputs, as data
  3. Your code checks it Permissions, valid inputs, limits
  4. Your system does the work Calendar, CRM, database
  5. Result goes back Short and relevant
  6. Model answers or asks again
The model only asks. Your code checks the request and does the work.

This split is the most important thing to understand about agents. Everything the model wants to do passes through code your developers control. That’s where the permission checks, validation, limits, approvals and logs go.

How function calling works, step by step

Current models from OpenAI, Anthropic and Google all support function calling, and they work in much the same way:

  1. You describe the tools. Each tool has a name, a description in plain language and a list of inputs with their types. The inputs are written as a JSON schema: a precise description of which fields are allowed and in what format.
  2. You send the request with the tool list. Along with the user’s message and your instructions, the model receives the descriptions of the tools it may use.
  3. The model decides. It either answers in text or replies with a tool call: which tool, with which inputs. When two lookups don’t depend on each other, it can ask for both at once.
  4. Your code runs the tool. It checks the inputs, does the work (a database query, an API call) and passes the result back to the model.
  5. The model continues. With the result in view, it calls another tool or writes the final answer. This repeats, and that repetition is the agent loop.

Here is what a tool description looks like, for a clinic’s booking system. Field names differ slightly between providers, but the idea is the same:

{
  "name": "find_free_slots",
  "description": "Find free appointment slots for one service between two dates. Use this before offering times to a patient. Returns at most 5 slots.",
  "input_schema": {
    "type": "object",
    "properties": {
      "service": { "type": "string", "enum": ["physiotherapy", "sports_massage", "first_consultation"] },
      "from": { "type": "string", "description": "Start date, YYYY-MM-DD" },
      "to": { "type": "string", "description": "End date, YYYY-MM-DD" }
    },
    "required": ["service", "from", "to"]
  }
}

The description isn’t decoration. The model reads it to decide when and how to use the tool, so it deserves as much care as the main instructions. Most providers can also enforce the schema strictly, so a tool call always arrives in the right shape. Whether the values make sense is still your code’s job.

Example: a booking agent with three tools

A physiotherapy clinic wants patients to book through a chat on its website. The agent gets three tools:

  • find_patient (read): finds an existing patient by name and date of birth.
  • find_free_slots (read): returns up to five free slots for a service between two dates.
  • book_appointment (write): books one slot for one patient and returns a reference.

Clinic booking agent

  1. You: Hi, it’s Jana Nováková, born 3 May 1988. Can I get a sports massage next Tuesday or Wednesday afternoon?
  2. Tool call: find_patient(name: Jana Nováková, born: 1988-05-03)
  3. Tool call: find_free_slots(service: sports_massage, from: 2026-07-14, to: 2026-07-15)
  4. Result: patient P-2231 · free: Tue 15:30, Wed 14:00, Wed 16:30
  5. AI: I have Tuesday at 15:30, or Wednesday at 14:00 or 16:30. Which suits you?
  6. You: Wednesday at 16:30, please.
  7. Tool call: book_appointment(patient: P-2231, slot: 2026-07-15 16:30)
  8. Result: confirmed · ref B-7781
  9. AI: Booked: sports massage on Wednesday 15 July at 16:30. Your reference is B-7781, and you’ll get a reminder the day before.
The first two lookups run in parallel. Only the last call changes anything.

The conversation looks simple, but the code behind each tool does real work:

  • find_patient returns only the patient ID and first name, not the full record. The agent doesn’t need more, so it doesn’t get more.
  • book_appointment checks that the slot is still free, that it’s in the future and that the patient exists. If someone else took the slot a second ago, it returns an error with fresh alternatives.
  • If the same booking request arrives twice (a network retry, or the model repeating itself), the second one returns the same reference instead of creating a duplicate. Developers call this making the tool idempotent.
  • Cancelling isn’t a tool at all. Patients who want to cancel are handed to reception. That’s a business decision, and it’s written into the tool list rather than left to the model’s judgement.

Read tools and write tools

Sort every tool into one of two groups, because they need different treatment.

Read tools look things up: find an order, list free slots, search documents. The main risk is showing data to the wrong person, so they should run with the permissions of the person the agent is working for, not as an administrator.

Write tools change something: book, send, update, pay. Give each one the narrowest scope possible and decide which ones need a person’s approval. Prefer drafts: draft_email rather than send_email, at least until you trust the agent. Irreversible actions such as payments or deletions should almost always go through a person.

Where the control sits

  1. Patient or employee Asks in a chat, an email or an app
  2. Model Picks a tool and fills in the inputs
  3. Tool list The only actions it can ask for: two read, one write
  4. Your code Permissions, validation, approvals, logs
  5. Your systems Booking calendar, patient records
The model never reaches your systems directly. Every request passes through the tool list and your code.

How to design good tools

Many of the agent problems we see are tool problems, not model problems. The model picked the wrong tool because two had similar names. It passed a date in the wrong format. A tool returned 400 rows and buried the answer. Anthropic’s published guidance on building agents makes the same point: tool definitions deserve as much attention as the prompts themselves.

Good tool design

  • One job per tool book_appointment, not run_query
  • Clear names and descriptions Say when to use it and what it returns
  • Few, typed inputs Fixed choices as lists, one date format
  • Validate everything in code Never trust the inputs the model sends
  • Safe to repeat A retried booking doesn’t book twice
  • Safe defaults Draft before send, small result limits
  • Short, relevant results Five slots, not the whole calendar
  • Errors that explain What went wrong and what to try instead

Two more habits save a lot of trouble.

Keep the list short. Every tool description goes to the model with each request. With five clear tools, it rarely picks the wrong one. With forty overlapping ones, it often does. If an agent seems to need dozens of tools, it’s usually doing several jobs at once. Merge similar tools into one with a clear option, or split the work, as we discuss in Multi-agent systems.

Test the tools without the model. Each tool is ordinary code. Call it directly with good inputs, bad inputs and awkward cases (a slot in the past, a patient who doesn’t exist, the same booking sent twice) before any AI is involved. Then the problems you find later really are about the model’s choices, and those are much easier to track down.

When tools fail

Tools fail all the time: a system is down, a slot was taken a second ago, a search finds nothing. Plan for it:

  • Return errors the model can act on. “Slot no longer free. Next free slots: Wed 17:00, Thu 9:30” lets it recover. “Error 500” doesn’t.
  • Limit retries and steps. Cap how many tool calls one task may make, so a confused agent stops instead of going round in circles and running up costs.
  • Hand over cleanly. When the agent can’t finish, it passes the case to a person with a summary of what it tried.
  • Log every call. Tool name, inputs, result and time. When something goes wrong, the log tells you whether the model asked for the wrong thing or the tool did the wrong thing.

Untrusted content is a separate risk. If a tool returns text from an email or a web page, that text could contain instructions aimed at the model. This is called prompt injection, and it’s one more reason write tools need limits even when the model seems well behaved. We cover the defences in Keeping AI agents safe.

Where MCP fits

Function calling is the mechanism inside one AI application. If you want the same tools in several applications (your own agent, an AI assistant on employees’ desktops, a coding tool), you’d normally have to wire them up separately for each one.

The Model Context Protocol (MCP) removes that duplication. It’s an open standard for packaging tools and data once, in an “MCP server” that any compatible app can use. Anthropic introduced it in late 2024, and the major AI providers now support it. Underneath, the model still makes tool calls exactly as described above. MCP standardises how the tools are described and reached. Read more in What is MCP?

We used this approach for Shovels’ Charlie, an assistant that answers questions about construction permits. MCP server integrations let the model query the live database, so answers come from current records rather than from what the model happens to remember.

What to do next

If you’re planning an agent, write the tool list before anything else:

  1. List the actions a person takes to do the task today.
  2. Turn each into a narrow tool with a clear name and as few inputs as possible.
  3. Mark each one read or write, and decide which writes need approval.
  4. Check your systems can actually do each action through an API.
  5. Write test cases: ten requests that should use each tool, and five that shouldn’t.

If your list is short and clear, the agent will usually be easier to build than you expect. If you’d like us to look at it with you, book a 30-minute call.

More articles.

  1. How to bring generative AI into your company: a 90-day plan

    A practical 90-day plan for generative AI: pick the first process, assign owners, choose tools, run a checked pilot, manage risks, avoid stalling.

  2. What is an AI agent? A plain-English guide for business teams

    What an AI agent is, how it differs from a chatbot and an AI workflow, what it’s made of, and where it’s worth using in an ordinary company.

  3. What is MCP? The Model Context Protocol explained for companies

    What the Model Context Protocol is, how it connects AI apps to your CRM, files and databases, when you need it and what to secure first.

All articles

Want a second opinion on your project?

Book a call and we’ll talk through your options.

JurajCEO, QikBuild

You leave the call with

  • What we would build first
  • A rough price range
  • Whether custom software makes sense for you
Book a 30-minute call

Or write to hello@qikbuild.com