Should I test that?

Should I test LLM tool calls?

Verdict

Yes

Test the code that runs LLM tool calls: in CI, feed each tool handler scripted calls with valid, malformed and out-of-range arguments, and assert what it stores and which error it returns to the model.

Why

Test the handlers that run LLM tool calls, with scripted calls in CI. My typical case is a feature where a hosted model calls your own functions, such as moving a booking to another date. Blast radius is users, because a wrong call changes a customer's booking. Change frequency is regularly, because schemas and handlers change about once a month. Detectability is eventually, because a handler that accepts a loose argument stores a plausible wrong value without an error, and Reversibility is with-effort, because support repairs each record. Test cost is moderate, because a scripted call is a fixed object that a test compares exactly, so rule R11 gives Test.

When the decision changes
WhenDecisionWhy
The failure to catch is the model picking the wrong tool or argument value after a prompt, tool description or model changeTest it differently: an evaluation set of logged requests that checks the tool name and key arguments, run on every such changeTest cost rises to heavy, because the real model's calls differ between runs
A tool issues a refund with an amount taken from the model's argumentsTest mandatory: scripted calls with an amount above the order total, a negative amount and a repeated callBlast radius rises to money and Reversibility to costly, because an overpaid refund needs a claw-back
A tool reads records by a customer ID taken from the model's argumentsTest mandatory: scripted calls with another customer's ID that assert the tool returns no dataBlast radius rises to safety-or-legal and Detectability to never, because a leaked record reads like a normal answer
Every tool only reads public catalogue data for a live chat reply, and a rejected call shows an error that users reportTest minimally: one scripted call per tool, plus a regression test for each reported bad callDetectability moves to same-day and Reversibility to trivial, because users see the error and nothing is saved
Only staff use the tool-calling assistant, and the tool writes each change only after the staff member confirms it in an internal screenDo not write tool-call tests; the staff member who confirms each change is the checkBlast radius falls to internal, Detectability to same-day and Reversibility to trivial, because nothing is stored before the staff member confirms it
The tools run in a prototype on your own machine against your own test accountDo not test; try the calls by hand, and write handler tests before a customer uses the featureBlast radius falls to none, because only you run the prototype

What breaks if you don't test

The model sends an argument your handler did not expect: a number as a string, a missing optional field, a date in the customer's own format. The handler guesses, the call succeeds, and the model tells the customer the change is done. Nobody sees the wrong value until the customer acts on it.

What you lose if you over-test

Handler tests that call the real model fail at random and cost tokens on every push. Tests that assert the exact JSON the model produced break on every prompt edit. With strict mode on, the provider constrains each call to your schema, so a test that the call is valid JSON checks the provider instead of your code.

How to test

  1. Build each tool call by hand as the object your SDK passes to the handler.
  2. For each tool, write one valid call, one call per argument the handler must reject, and boundary values; pytest parametrize keeps the bad arguments in one test.
  3. Assert what the handler stores and which error it returns. Anthropic's guide to handling tool calls returns errors with is_error and a message the model can act on.
  4. Turn on strict tool use or OpenAI's strict function calling, so wrong types never reach the handler.

When the answer changes

  • A tool moves money or reads records by an ID the model supplies.
  • You change the model or a tool description and need to know it still picks the right tool.
  • A staff member confirms each change before the tool stores it.

Real incident + Code example

The visits that moved a month early

On a field-service booking app I worked on, the reschedule_visit tool took its date as a plain string, and the handler passed it to a lenient parser. UK customers typed "04/05" for 4 May, the model copied that format into the call, and the parser, reading the month first, stored 5 April. The model confirmed the date in words, so customers saw nothing wrong. Twelve days later a dispatcher asked why technicians kept finding nobody home. By then 41 visits had moved, and support phoned every customer to ask which date they meant.

We made the handler reject anything but YYYY-MM-DD and added these tests:

from datetime import date
import pytest
from booking.tools import handle_tool_call

def reschedule(visit_date):
    return {"id": "t1", "name": "reschedule_visit",
            "input": {"visit_id": 7, "date": visit_date}}

def test_iso_date_moves_the_visit(customer_visits):
    result = handle_tool_call(reschedule("2026-05-04"), customer_visits)
    assert not result.get("is_error")
    assert customer_visits.get(7).date == date(2026, 5, 4)

@pytest.mark.parametrize("bad", ["04/05/2026", "next Monday", ""])
def test_other_formats_go_back_to_the_model(customer_visits, bad):
    result = handle_tool_call(reschedule(bad), customer_visits)
    assert result["is_error"] is True
    assert "YYYY-MM-DD" in result["content"]
    assert customer_visits.get(7).date == date(2026, 5, 20)

FAQ

Should I test function calling?

Yes, test the code that runs function calls by feeding each handler scripted calls with valid and invalid arguments. Check whether the model picks the right function in a separate evaluation set.

Does strict mode make tool-call tests unnecessary?

Strict mode does not make tool-call tests unnecessary, because it guarantees only that a call matches your schema. A date in the right format can still be the wrong date, and a valid ID can belong to another customer.

How do I test that the model picks the right tool?

Test the model's choice of tool with an evaluation set of real user requests, each labelled with the expected tool and key arguments. Run it against the real model on every prompt, tool description or model change.