LLMs don’t reach into your code – they hand you a request, and you run the function. That simple fact flips the myth that “the model magically calls my Python routine” and forces developers to rethink debugging and security.
The dispatch loop, step by step
When a language model (LLM) needs a tool, it follows a deterministic sequence:
- Planning – the model decides an action is required (e.g., “refund a payment”).
- Generating a request – it outputs structured text—usually JSON—that names the tool and supplies arguments.
- Parsing – your app or a supporting framework reads that text.
- Matching – the framework looks up the name in the registry of real functions you exposed.
- Validating – it checks that the arguments match the function’s schema and that the caller is authorized.
- Executing – the matched function runs in your environment, performing the work.
- Returning – the result is packaged and sent back to the model for further reasoning.
Think of the LLM as a planner, the framework as a dispatcher, and the function as the worker that actually moves data or money.
Why the “magic” myth persists
Most developers see a single line of model output that looks like a function call and assume the model performed the operation itself. The term “tool calling” in provider docs sounds like the model is directly invoking code.
In reality, the model only produces text that describes a call. Your process does the heavy lifting—lookup, type checking, permission enforcement, error handling.
Frameworks that hide the plumbing
Libraries such as PydanticAI and LangChain abstract the loop so you can focus on business logic. They automatically:
- Validate arguments against a schema (e.g., a Pydantic model).
- Enforce permissions, ensuring the user may trigger the tool.
- Retry on failure, looping back to the model when a tool returns an error.
- Guard against runaway loops, capping consecutive tool calls.
- Maintain conversation state, stitching tool results into the dialogue.
Even with these helpers, the pattern stays the same: the model never executes code.
Native tool-calling support from providers
Some providers ship a “native” tool-calling interface that standardizes tool definitions and request formats. It smooths integration but does not remove the dispatch step. You still write (or import) the code that actually runs the requested operation.
Debugging becomes easier when you rename the problem
Instead of blaming a “confused agent,” say the issue is “the model response contained no tool calls.” The distinction matters:
- No tool call – the model answered directly or failed to generate a correctly formatted request.
- Malformed request – the JSON is syntactically wrong or missing required fields, so the dispatcher rejects it.
- Validation failure – arguments don’t match the schema, triggering an error before execution.
Categorizing failures lets you log each stage of the loop and pinpoint where things went off-track.
Practical tips for a reliable pipeline
- Treat model output as untrusted input. Run every request through deterministic validation before invoking any side-effecting code.
- Log the raw request and the result of each validation step. This creates a replayable trail when something goes wrong.
- Set explicit limits on consecutive tool calls; a runaway loop can exhaust resources or hit rate limits.
- Wrap each function in a try/except block that returns a structured error object the model can understand, prompting a retry or graceful fallback.
- Separate permission checks from business logic. Verify the caller’s rights before the function runs, especially for privileged actions like “delete user.”
- Use schema-driven definitions (e.g., Pydantic models) so the framework can auto-generate the JSON schema the model must follow.
What to watch next
As providers refine native tool-calling APIs, expect tighter contracts around request formats and richer error codes. Those changes will make validation easier and let developers build stricter security fences. Keep an eye on library updates—many are adding built-in support for the newest provider features.
Takeaway
LLM to zaawansowany generator tekstu, a nie wykonawca. Twój kod pozostaje jedynym podmiotem decyzyjnym wykonującym działania, a zbudowany (lub zaimportowany) przez Ciebie dispatcher pełni rolę strażnika, który waliduje, autoryzuje i uruchamia te działania. Zmiana sposobu postrzegania przepływu pracy eliminuje mit „magii”, usprawnia debugowanie i wymusza dyscyplinę bezpieczeństwa, której wymaga każdy system produkcyjny.
