LLM function calling lets a model output a structured request for an external tool β a search engine, a database, a calculator β which a host application executes and returns results from. An agent is something different: an autonomous loop where the LLM repeatedly calls tools, processes what comes back, and decides what to do next until it achieves a goal or hits a defined limit.
These two patterns are often conflated, but the engineering tradeoffs between them are substantial. A 2026 paper titled "The Bitter Lesson of Tool Calling" (Patel, Sen, Lumer & Subbiah; arXiv:2608.06370) makes the distinction sharper: testing 14 language models on the Berkeley Function Calling Leaderboard v4 (BFCL v4), the authors compared native JSON tool calling β where the model emits rigid structured function specs β against programmatic tool calling (PTC), where tools are expressed as callable code that the model can chain, parallelize, and conditionally invoke. PTC consistently outperformed JSON-based calling on complex multi-step tasks. For single-step tasks, the two approaches performed comparably.
The practical implication: the right pattern depends on task complexity, not just on what the LLM provider supports natively.
How Function Calling Works: The Core Mechanics
Modern function calling follows a structured, stateless exchange:
- Tool definition: The developer provides a schema β typically JSON β describing available functions: their names, parameter types, return types, and natural-language descriptions of what each does and when to use it.
- Model invocation: The LLM receives this schema alongside the user's prompt. When it determines a tool is needed, it outputs a structured call object instead of plain text β specifying the function name and parameter values.
- Host execution: The application extracts the structured call, validates it, executes the actual function, and returns the result to the model as a new context entry.
- Final synthesis: The model generates its final response incorporating the tool's output.
This is deterministic and developer-controlled. The model never runs the function itself β it only requests it. The application decides whether to honor the request, validate the parameters, and inject the result. This constraint is a feature, not a limitation: it makes function-calling systems auditable and safe by design.
Agents: When the Loop Takes Control
Image: Example of a generative agent architecture β Park JS, O'Brien JC, Cai CJ, Morris MR, Liang P, Bernstein MS (CC BY-SA 4.0), via Wikimedia Commons
Agents extend function calling into an autonomous loop. The generative agent architecture above shows what this loop involves: the model maintains a memory stream of past interactions, retrieves relevant context before each action, reflects to form higher-level conclusions from accumulated experience, and plans multi-step sequences β deciding at each step whether to call another tool, synthesize existing results, or terminate.
Modern reasoning-capable LLMs push this further. Extended thinking β visible in interfaces like the one below β allows models to work through multi-step tool orchestration problems before committing to an action, reducing errors on tasks that require conditional logic across multiple tool calls.
Image: GPT-5 Reasoning UI β StereoFolic (CC BY-SA 4.0), via Wikimedia Commons
But agents introduce failure modes that single function calls don't have. A 2026 paper on agent trajectory debugging (TRAJDEBUG, arXiv:2608.06346) found that failures in long-horizon agent tasks cluster at a small number of critical decision points β particularly when the agent must decide whether to retry a failed tool call, synthesize ambiguous prior results, or recognize that the task is not solvable with available tools and stop. Unconstrained agents tend to retry rather than stop, compounding errors rather than recovering from them.
Programmatic vs. JSON Tool Calling: What the Research Shows
The "Bitter Lesson" paper's central finding has direct engineering implications. For tasks that require:
- Chaining multiple tool calls conditionally ("if the first API returns X, query Y instead of Z")
- Parallelizing independent calls to reduce end-to-end latency
- Dynamic error handling based on intermediate results
- Looping over collections of items with per-item tool invocations
...expressing tools as callable Python or JavaScript functions and letting the model write code to orchestrate them outperforms schema-based JSON calling, particularly as task complexity increases. The intuition: code is a richer language for expressing control flow than a JSON function spec. Conditionals, loops, and error recovery that require multiple JSON round-trips can be expressed in a single block of generated code.
That said, native JSON calling remains appropriate for:
- Single-step, deterministic tool invocations where the schema clearly maps to the request
- Production environments where auditability and human review of each call is required
- Contexts where generated code execution introduces unacceptable security surface area
Choosing the Right Pattern
| Criterion | Single Function Call | Agent Loop |
|---|---|---|
| Task structure | Single, well-defined operation | Multi-step, goal-directed |
| Next action depends on prior result | No | Yes β core use case |
| Latency sensitivity | Low overhead | Higher β multiple LLM calls |
| Auditability requirement | Excellent β one supervised step | Requires full trace logging |
| Failure handling | Simple β caller handles error | Complex β agent may loop on failure |
| Cost | Single inference call | Potentially many β budget accordingly |
| Terminal condition | Implicit β function returns | Must be explicitly defined |
Engineering Reliable Tool-Use Systems
Several patterns have emerged as non-negotiable in production:
Keep tool schemas tight and unambiguous. Ambiguous parameter descriptions cause hallucinated values. Every parameter should have a clear type, an explicit description of what it means (not what the function does), and ideally a constrained set of valid values or worked examples. If the model is guessing at parameter intent, the schema needs revision.
Validate tool outputs before injecting them into context. The model trusts whatever comes back from a tool call. A malformed API response injected directly into context as if it were valid data can silently corrupt the model's subsequent reasoning. Parse and validate before passing back.
Set explicit retry limits and fail-fast thresholds. The TRAJDEBUG research found that unconstrained retries dramatically increase cascading errors. An agent that retries a broken API call ten times before stopping has consumed ten times the budget and returned nothing useful. Two retries with exponential backoff, then halt and report, is a better policy for nearly all production cases.
Enforce structured output at the final synthesis step. Even within agent loops, the model's final response should conform to a defined schema. Open-ended generation at the output stage is the most common source of format errors in production deployments β and the easiest to prevent.
Log every call and result with full context. Debugging agent failures without traces is effectively impossible. Structured logs of every tool invocation β function name, parameters, result, latency, error codes β are necessary for diagnosing the specific decision point where things went wrong.
Frequently Asked Questions
What is the difference between function calling and tool use?
These terms describe the same mechanism and are now used interchangeably across the industry. "Function calling" originated with OpenAI's API naming in 2023; "tool use" is the broader framing adopted by Anthropic, Google, and open-source frameworks. Both refer to the model outputting a structured invocation for an external capability that the host application then executes.
When should I use an agent loop instead of a single function call?
Use a single function call when the task maps cleanly to one external operation with a deterministic result. Build an agent loop when the task is genuinely multi-step, when the next action depends on the result of a prior tool call, or when the goal is exploratory and the terminal condition can't be specified in advance. The overhead and failure surface of agent loops make them the wrong choice for well-scoped, single-turn tasks β a mistake that's common and expensive in production.
Are LLM agents reliable enough for production use in 2026?
For bounded, well-tested task domains, yes β agents handling code review, structured data extraction, and customer support workflows are widely deployed. For open-ended tasks with large tool surfaces, reliability remains a significant engineering challenge. The TRAJDEBUG findings suggest reliability gains come primarily from constraining the action space and adding explicit error-recovery checkpoints, not from relying on model capability alone.
Bottom Line
Function calling is the right default: simple, auditable, and natively supported across all major LLM providers. Reach for agent loops when the task genuinely requires multi-step reasoning that cannot be preplanned β but build in hard constraints from day one. Token budgets, retry caps, structured output validation, and full trace logging are not optional engineering polish. The 2026 research consensus is consistent: unconstrained agents fail in predictable, preventable ways, and the engineering decisions that prevent those failures are all implementable before you deploy.
Sources & References:
Patel I, Sen S, Lumer E, Subbiah VK. The Bitter Lesson of Tool Calling. arXiv:2608.06370 (2026-08-06).
TRAJDEBUG: Tracing Error Lifecycle to Identify Critical Failures in Long-Horizon Agent Trajectories. arXiv:2608.06346 (2026-08-06).
Park JS, et al. Generative Agents: Interactive Simulacra of Human Behavior. arXiv:2304.03442 (2023).
Disclaimer: This article is for informational purposes only. Technology landscapes change rapidly; verify information with official sources before making technical decisions.