Function Calling: Tool-Use Patterns for Production Agents

7 min readYaseen Khatib · MERN + AI Architect

Function calling is the moment a language model stopped being a text generator and became a controller. Instead of only emitting words, the model can choose to invoke a typed function you expose — query a database, hit an API, run a calculation — and use the result. It is the primitive every agent is built on, and getting the tool design right matters more than the model you use.

From text-out to action

You give the model a menu of tools, each with a name, a description, and a typed argument schema. The model reads the request, decides whether a tool is needed, and returns a structured call — which your code executes, feeding the result back. The model never touches your systems directly; it proposes, your runtime disposes.

tools.ts
// expose narrow, typed, well-described tools
const tools = [{
  name: "get_case",
  description: "Fetch a case record by its ID.",
  parameters: z.object({ id: z.string() }),
}];

const call = await llm.run(prompt, { tools });
if (call.tool) {
  const result = await registry[call.tool](call.args);
  // feed result back to the model for the final answer
}

Designing tools the model can use

Tools should be narrow, typed, and honestly described. A vague tool ("do_stuff") gets misused; a sprawling one with a dozen optional arguments confuses the model. The description is part of the interface — it is how the model decides when to reach for it. Treat each tool like a public API you are documenting for a capable but literal-minded consumer.

Guardrails are not optional

The model proposes calls; it must never be trusted to execute them unchecked. Validate every argument against its schema before running, scope what each tool can touch, and gate anything destructive behind an explicit confirmation. Autonomy without guardrails is just a faster path to a production incident.

Function calling turns a model into an agent. The agent is only as safe as the narrowest, best-validated tool you gave it.

Tool-driven control loops are the core of the Agentic RAG architecture and the intent-driven router.

Looking to architect a similar system?

Let's ship it at AI-speed.

Start a conversation →