Tool Use and Function Calling: How AI Agents Touch Real Systems

Function calling is easy to demo and hard to productionize. How we design tool layers for AI agents across 9 connected systems: schemas, idempotency, permissions.

Ostap Kovalisko

Founder & AI Systems Architect

October 23, 20258 min read

Function calling is the moment an AI system stops being a text box and starts being an agent: the model emits a structured call, your code executes it against a real API, and something actually happens — an email sends, a task appears, a billing entry posts. It's also the moment your error budget drops to near zero, because the failures are no longer wrong words but wrong actions.

Our production platform exposes 30 actions across 9 connected sources — email, tasks, documents, chat, billing, CRM, signatures, meetings, and calendar-adjacent tooling. Here's what we've learned about building the tool layer that sits between an LLM and systems that matter.

Tools Are an API You Design for a Model

The biggest mental shift: your tool definitions are a UI, and the model is the user. The same design failures that confuse humans confuse models.

  • One tool, one job. A manage_tasks tool with a mode parameter gets misused constantly. Separate create_task, complete_task, and reassign_task tools almost never do.
  • Descriptions are prompts. Every tool and parameter description gets read on every call. Say when to use the tool, when not to, and what happens on execution — the "when not to" clause prevents more misfires than anything else.
  • Enums over free text. Any parameter with a known value set becomes an enum. Free-text status fields produce "Done", "done", "completed", and "finished ✅" within a week.
  • Small tool sets per context. We never hand the model all 30 actions' tools at once. Intent classification picks the action first; the execution step sees only the 2–5 tools that action needs. Accuracy goes up, tokens go down.

The Execution Wrapper

The model proposes a call; it never touches the API directly. Every call passes through a wrapper that enforces the properties LLMs can't guarantee:

LayerWhat it doesFailure it prevents
Schema validationReject malformed or incomplete arguments before executionGarbage writes to downstream systems
Reference resolutionVerify IDs exist; resolve names to records, ask if ambiguousActing on hallucinated or wrong entities
Permission checkEnforce the acting user's rights, not the agent'sPrivilege escalation through the AI
Risk gateRoute consequential calls to the approval queueAutonomous mistakes with external blast radius
Idempotency keyDeduplicate retried callsDouble-sent emails, duplicate billing entries
Audit writeRecord call, arguments, result, and approverUnreconstructable incidents

Idempotency deserves emphasis. Agent loops retry; networks flake; users double-click. Every mutating tool takes a deterministic key derived from the triggering event, and the wrapper drops duplicates. The first duplicated client email teaches this lesson expensively — learn it from this paragraph instead.

Error Messages Are for the Model

When a tool fails, the error text goes back into the model's context — so write errors the model can act on. "Error 422" produces a retry loop. "Client 'Acme Corp' matched 2 records: Acme Corp (ID 118), Acme Corp Holdings (ID 240). Specify which."produces a clarifying question to the user. We treat tool error strings with the same care as prompts, because that's what they are.

A good tool layer makes the model's job boring: pick the obvious tool, fill the obvious fields, let the wrapper handle everything sharp.

Read Tools vs Write Tools

We split the catalog hard along this line. Read tools (search, fetch, summarize across the 9 sources) execute freely — worst case is a useless answer. Write tools carry risk tiers: low-risk writes auto-complete with a revert path, and anything client-facing lands in the approval queue where a human sees the exact payload before it runs. This split is also how new integrations ship fast: reads go live in shadow-validated days, writes graduate one at a time as approval rates prove out.

Testing the Tool Layer

  1. Unit-test tools without the model: every tool runs against fixtures and a sandbox tenant — a tool you can't test in isolation is a tool you can't trust
  2. Replay real transcripts: store production tool-call sequences and replay them against changes to catch regressions in argument construction
  3. Fuzz the arguments: models will eventually send empty strings, wrong-locale dates, and 10,000-character notes; the wrapper must reject all of it gracefully
  4. Chaos the dependencies: kill a downstream API in staging and verify the agent reports the failure instead of hallucinating success

At 500+ tool executions per week, the model is honestly the most reliable component in the chain — modern LLMs format calls well. The engineering value is all in the wrapper: validation, resolution, permissions, idempotency, audit. Build that layer once, properly, and every new action becomes a schema, a handler, and a risk tier — a day's work instead of a project.

Let's Talk About Your Project

Have questions about nearshoring or AI development? Our team is here to help you make the right decision.

  • Free consultation on your AI project
  • Custom cost estimates and timeline
  • Access to nearshore talent pools