Free live cohort on Google Meet — register your interest →
← AI Engineering Fundamentals

Tool-Calling Agent

An agent that calls tools — search, save, and lookup functions — inside a loop that keeps running until the model has a real answer or a hard iteration cap kicks in. This is the shift from “an LLM that responds” to “an LLM that acts”: every project after this one in the path assumes you’re comfortable with a model deciding, mid-conversation, that it needs to call something before it can answer.

What you’re building

tool-calling-agent gives the model a small set of functions it can request — not run, request — and wraps a single conversation in a loop that executes those requests, feeds the results back, and lets the model reason again with that new information. The model never touches a file system or a network call directly; it only ever produces a structured request that your code decides whether to honor. That distinction — the model requests, your code executes — is the one piece of mental model that makes every failure mode in this project make sense.

The agent loop

Tool-calling agent loop: call the model with the tool list, branch on stop_reason, validate any requested tool name against an allowlist before executing it, inject the result, and repeat until end_turn or a max-iterations guard trips

Every turn of the loop passes through the same two checks — is this a real, registered tool? and has the loop run too many times? — and both exist specifically to stop the model’s own output from taking your code somewhere it shouldn’t go.

Core concepts, three levels deep

1. Tool definitions

  • Definition: a JSON structure with a name, a description, and an input_schema — handed to the model alongside the conversation so it knows what it’s allowed to ask for.
  • In this project: the description field is doing the real work. It’s the only place you tell the model when this tool applies and, just as importantly, when it doesn’t — a vague description (“use this for information”) gets the tool called for things it was never meant to handle.
  • Practical consequence: write the description like you’re briefing a new teammate who can only read that one sentence — state the trigger condition and the exclusion in the same breath, the way the reference tool definitions in this project do (“use this when X… do NOT use this for Y”).

2. The agent loop (ReAct cycle)

  • Definition: a control structure — observe, reason, act, observe again — that repeats until a stop condition ends it. The model reasons over the current context, optionally emits a tool call, your code executes it and injects the result as the next “observation,” and the cycle continues.
  • In this project: every user message can trigger zero, one, or several trips around this loop before a final text answer comes back. The loop’s state is just the growing message history — there’s no separate memory store.
  • Practical consequence: check stop_reason on every response. "end_turn" means the model is done and produced text — return it. "tool_use" means it wants something executed — dispatch it and loop again. Missing this branch is the single most common way to ship a loop that never terminates on its own.

3. Hallucinated tool calls and stop conditions

  • Definition: a hallucinated tool call is a tool_use block naming a function that was never actually registered with the model — the model predicted a plausible-looking request, not a real one. A stop condition is whatever explicit rule ends the loop: end_turn, a max-iteration cap, or a user-issued “done.”
  • In this project: nothing stops the model from emitting a tool name it invented, and nothing stops a loop from running forever except a rule your code enforces — neither failure mode is prevented by the model “behaving well” on average.
  • Practical consequence: validate every requested tool name against an explicit allowlist before executing anything, and enforce a hard MAX_ITERATIONS ceiling independent of whatever the model decides to do. Both checks live in your code, not in the prompt.

4. Tool output poisoning

  • Definition: a security failure where content returned by a tool contains instructions, and the model follows them because it treats tool results as trusted context, the same way it treats a system prompt.
  • In this project: any tool that can return content you didn’t author yourself — a fetched web page, a file, an external API response — is a place an attacker can smuggle instructions directly into the model’s next reasoning step.
  • Practical consequence: treat tool output as untrusted input, not as a system-level instruction. Cap its length before injecting it, and don’t assume “it came back from my own tool” means it’s safe just because the call was legitimate — the content still needs to be handled like user-controlled data.

Decision rules

If…Then…
A tool’s name doesn’t match anything you actually registeredReject it and return an error tool_result — never execute a name you don’t recognize
The model keeps calling tools past a reasonable number of turnsEnforce a hard MAX_ITERATIONS cap independent of the model’s own behavior
A tool returns content from outside your control (a web page, a file, a search result)Treat it as untrusted — cap its size and don’t let it silently override prior instructions
All the information the model needs already fits in the prompt, with no external action requiredSkip the loop — a single-shot prompt is simpler, cheaper, and has fewer failure surfaces

Common mistakes

  • Writing a vague tool description (“use this for information”) instead of stating exactly when the tool applies and when it doesn’t — the model will call it in cases you didn’t intend.
  • Trusting a tool name without validating it — a tool_use block naming an unregistered function is a hallucinated call, not a real request; execute only what’s on your allowlist.
  • Building a loop with no iteration ceiling — a missing or broken stop condition doesn’t fail loudly, it just runs (and bills) until something external kills the process.
  • Reaching for an agent loop by default — if a single prompt with the right context in it can already answer the question, a loop only adds latency, cost, and new places to fail.

Key concepts at a glance

ConceptOne-line definitionWhy it matters for tool-calling-agent
Tool definitionName + description + input_schema handed to the modelThe description is what actually drives correct tool selection
Agent loop (ReAct)Observe → reason → act → observe, repeated until a stop conditionThe control structure the whole project runs inside
Hallucinated tool callA tool_use block naming a function that was never registeredWhy every tool name must be checked against an allowlist before executing
Tool output poisoningUntrusted content in a tool result treated as trusted instructionsWhy tool output needs the same skepticism as any other user-controlled input
Go deeper: Tool Use & Single-Agent Loops — the full concept walkthrough (tool definitions, the ReAct cycle, stop conditions, MCP) →

Tool-calling agents are the foundation of 'AI agent' roles now appearing across the industry — this is the entry point into agentic AI engineering specifically.