Why architecture matters here

Tool use matters because it's what connects LLMs to the real world -- live data, reliable computation, and actions -- transforming them from text generators into agents that can accomplish tasks. An LLM alone is limited to generating text from its training (no live data -- it doesn't know today's information; unreliable at precise tasks -- math, lookups; no actions -- it can't do anything in the world). Tool use removes these limits: the model can call tools to fetch live data (a search, an API), do reliable computation (a calculator, code execution), query systems (a database), and take actions (sending an email, updating a record) -- so it's grounded in real data and can act. This transforms LLMs from text generators into capable assistants and agents (LLMs using tools in a loop to accomplish tasks -- the foundation of agentic AI). For building useful LLM applications (which almost always need live data, reliable operations, or actions -- beyond pure text generation), tool use is essential, and understanding it (how the model calls tools and your code executes them) is understanding the foundation of grounded, capable LLM applications and agents.

The model-requests-your-code-executes insight is the crucial architectural understanding, and it clarifies the division of responsibility. A common misunderstanding is that the model 'runs' tools -- it doesn't. The model only produces text (or structured output) -- so what it does for tool use is request a tool (emit a structured tool call -- the tool name and arguments -- as its output). The model doesn't execute anything (it can't -- it only generates output). Your execution layer (your application code) is what executes the tool: it receives the model's tool-call request, validates it, calls the actual function (the real database query, API call, calculation), gets the result, and injects the result back into the conversation (as a message the model observes). So the division is clear: the model decides which tool to call and with what arguments (the reasoning/selection -- its job), and your code executes the tool and returns the result (the execution -- your job). This division has important implications: your code controls the execution (so you can validate arguments, enforce policies, handle errors, sandbox -- the security and control are in your execution layer, not the model), and the model only sees the results you feed back (so you control what it observes). Understanding the model-requests-your-code-executes division (the model requests tools, your code executes them and returns results) is understanding the crucial architecture of tool use (and where control and security live -- in your execution layer).

And the call-execute-observe-loop insight is the operational core, and it's how tool use accomplishes multi-step tasks. Tool use isn't a single call -- it's a loop. The model calls a tool (requests it), your code executes it and feeds the result back (observe), and the model continues -- now with the tool's result in its context, it can reason further (possibly calling more tools -- e.g., using the first tool's result to decide the next tool, or calling several tools to gather information) -- until it has what it needs to produce its final response. This loop (call → execute → observe, repeated) is how the model accomplishes multi-step tasks: it gathers information and takes actions step by step (each tool call informed by the previous results) -- e.g., to answer a complex question, it might search (tool call), read the results (observe), then look up specifics (another tool call), then compute (another) -- building up to the answer through the loop. This is the essence of an agent (an LLM using tools in a loop to accomplish a task -- the call-execute-observe loop being the agent loop). So the loop (call, execute, observe, repeat -- until done) is the operational core of tool use (how it accomplishes multi-step tasks through iterative tool use) -- and it's the foundation of agents. Understanding the call-execute-observe loop (iterative tool use building to a result -- the agent loop) is understanding how tool use accomplishes tasks.

Advertisement

The architecture: every piece explained

Top row: the idea and mechanism. The idea: the model calls functions (tools) -- requesting your code run a function to fetch data, compute, or act. Tool schemas: describing the tools to the model -- each tool's name, a description (what it does, when to use it), and its parameters (the arguments, with types) -- how the model knows what tools exist and how to use them. The loop: call → execute → observe -- the model calls a tool, your code executes it, the result is fed back for the model to observe, and it continues. Structured output: the model emits a tool call (a structured output -- the tool name and arguments -- rather than free text) -- the request format.

Middle row: execution and selection. Execution layer: your code runs the tool (receiving the model's request, validating it, calling the actual function -- the database/API/calculation) -- the execution (where control and security live). Result injection: feeding the tool's result back into the conversation (as a message the model observes) -- so the model sees the result and continues. Parallel tool calls: the model requesting multiple tools at once (independent tools -- executed concurrently -- for efficiency) -- parallel execution. Tool selection: the model choosing which tool to call, when (guided by the tool descriptions -- selecting the right tool for the sub-task) -- the model's reasoning about tools.

Bottom rows: robustness and protocol. Errors + validation: validating the model's arguments (against the schema -- catching malformed/invalid arguments) and handling tool failures (a tool erroring -- feeding the error back so the model can retry or adjust) -- robust tool use. vs MCP: MCP (the Model Context Protocol -- a standard protocol for exposing tools to models -- so tools are defined once and reused across applications) vs ad-hoc per-application tool definitions -- MCP standardizing tool exposure (versus each app defining tools ad-hoc). The ops strip: schema design (designing the tool schemas -- especially the descriptions, which are load-bearing -- so the model understands and correctly selects/uses the tools -- good descriptions are crucial), error handling (handling tool errors and invalid arguments -- validation, feeding errors back for the model to adjust -- robustness), and observability (observing the tool use -- which tools are called, with what arguments, results, errors -- for debugging and understanding the model's behavior).

LLM tool use -- connecting models to actions and datathe model requests, your code executes, the result returnsThe ideamodel calls functionsTool schemasname, description, paramsThe loopcall -> execute -> observeStructured outputmodel emits a tool callExecution layeryour code runs the toolResult injectionfeed result backParallel tool callsmultiple at onceTool selectionwhich tool, whenErrors + validationbad args, tool failuresvs MCPprotocol for toolsOps — schema design + error handling + observabilityexecuteinjectparallelselecterrormcpoperateoperateoperate
LLM tool use: the model emits a structured tool call (name + arguments), your execution layer runs the tool, and the result is injected back for the model to observe -- a call/execute/observe loop.
Advertisement

End-to-end flow

Trace the call-execute-observe loop answering a question. A user asks 'What's the weather in the city where our next meeting is?' The model (with calendar and weather tools) reasons: it needs the meeting location, then the weather there. It calls the calendar tool (a structured tool call -- get_next_meeting) -- your execution layer runs it (querying the calendar), getting the meeting (in, say, Seattle), and injects the result back. The model observes the result (Seattle), then calls the weather tool (get_weather with city=Seattle) -- your code executes it (calling the weather API), getting the weather, and injects it back. The model observes the weather and produces the final response ('The weather in Seattle, where your next meeting is, is ...'). The loop (call calendar → execute → observe → call weather → execute → observe → respond) accomplished the multi-step task (finding the meeting location, then the weather there) -- the model calling tools, your code executing them, results fed back, building to the answer. The call-execute-observe loop (iterative tool use) accomplished the task.

The division and parallel vignettes show the architecture and efficiency. A division case: the model requested the weather tool with city=Seattle -- but it didn't execute anything (it only emitted the request). Your execution layer executed it (calling the weather API, with control -- validating the city argument, handling the API call, sandboxing/policies as needed) and returned the result -- the model only seeing the result you fed back. The division (model requests, your code executes -- with control in your layer) kept the execution and security in your code (not the model). A parallel case: for a query needing multiple independent lookups (e.g., the weather in three cities), the model requests all three weather tool calls at once (parallel tool calls) -- your execution layer runs them concurrently (three API calls in parallel) and feeds all the results back -- faster than sequential (the parallel calls executed concurrently). The parallel tool calls improved efficiency for the independent lookups.

The error and schema vignettes complete it. An error case: the model calls a tool with an invalid argument (e.g., a malformed date) -- your execution layer validates it (against the schema), catches the invalid argument, and feeds an error back ('invalid date format') -- so the model observes the error and adjusts (correcting the argument and retrying) -- the error handling (validation, feeding errors back) making the tool use robust (the model recovering from the error). A schema case: the team finds the model sometimes selects the wrong tool (or misuses one) -- and improves the tool descriptions (making them clearer -- precisely describing what each tool does and when to use it) -- so the model selects and uses the tools correctly (the descriptions being load-bearing -- the model's tool understanding coming from them). The improved schemas fixed the tool selection. The consolidated discipline the team documents: use tool use to connect the LLM to data and actions (the model requesting tools, your code executing them -- grounding the model and enabling actions), understand the division (the model requests tools and reasons about them; your execution layer executes them, with control and security -- and returns results), drive it with the call-execute-observe loop (iterative tool use accomplishing multi-step tasks -- the agent loop), design good tool schemas (especially descriptions -- load-bearing for the model's tool understanding and selection), use parallel tool calls for efficiency, validate arguments and handle tool errors (feeding errors back for the model to adjust -- robustness), consider MCP for standardized tool exposure, and observe the tool use -- because tool use is what connects LLMs to the real world (data, computation, actions), transforming them into capable agents, via the model requesting tools and your code executing them in the call-execute-observe loop.