LLM Agents and Tool Use
Function calling, memory, multi-agent coordination, and the architecture behind every production AI agent.
A chatbot answers questions. An agent takes actions — it calls APIs, runs code, searches the web, writes files, and coordinates with other agents to complete multi-step tasks.
Module 53 showed ReAct as a prompting pattern — manually parsing tool calls from LLM text output. That works but is fragile. Modern LLM APIs support native function calling: you define tools as JSON schemas, the LLM returns a structured tool call object (not text to parse), you execute the function, return the result, and the LLM continues. No regex. No parsing failures. The LLM decides which tool to call, with which arguments, at each step of a multi-step task.
At Stripe, an agent handling merchant disputes can: look up transaction details in the database, check the dispute deadline, draft a response email, send it via the email API, and update the CRM — all from a single natural language request from a support engineer. What took 20 minutes of copy-pasting across four tabs takes 30 seconds.
A chatbot is a knowledgeable advisor — they can tell you what to do but you have to do it yourself. An agent is a capable employee — you tell them what you want and they figure out the steps, use the right tools, and hand you the result. The difference is agency: the ability to act in the world, not just generate text about acting.
The key constraint: agents are only as reliable as the LLM driving them. Every tool call is an LLM decision — and LLMs make mistakes. Production agents need guardrails, confirmation steps for irreversible actions, and human-in-the-loop for high-stakes decisions.
Function calling — structured tool invocation without text parsing
Function calling lets you define tools as JSON schemas and pass them to the LLM alongside the user message. When the LLM decides to use a tool it returns a structured tool_call object — not text. You execute the function with the provided arguments, return the result as a tool message, and the LLM generates its next response informed by the result.
Agent memory — short-term, long-term, and semantic memory
A stateless agent forgets everything between conversations. Production agents need memory: what the user said earlier in this conversation, what this user has asked about in past sessions, and relevant facts retrieved from external storage. Three types of memory serve different purposes.
The full message history of the current conversation. Passed in every API call.
Facts about the user, preferences, and important outcomes from past sessions. Stored in a database.
Past conversations and documents stored as embeddings. Retrieve by semantic similarity.
Multi-agent coordination — orchestrator and specialist agents
Complex tasks exceed what a single agent can reliably handle. A multi-agent system uses an orchestrator agent that plans and delegates to specialist agents — each with its own tools, context, and expertise. The orchestrator never executes tools directly. It breaks the task into sub-tasks and routes each to the right specialist.
Guardrails — preventing agents from doing the wrong thing
Agents that can take real-world actions — send emails, call APIs, write to databases — need guardrails. Without them a hallucinating agent can send wrong emails to customers, corrupt database records, or call expensive APIs in loops. Three layers of protection are standard in production agent systems.
Every common agent mistake — explained and fixed
Production agent deployments — what actually ships, and what stops it from breaking things
Teams that ship agents to production rarely start with full autonomy. A support triage agent typically launches read-only — it can look up orders, transactions, and account history, draft a response, and hand it to a human to send. Write access (sending the email, issuing the refund) is added weeks later, after the read-only version has run long enough to build confidence in its judgment. Coding agents follow the same arc: propose a diff and a pull request first, merge-on-approval only, direct commit access last and often never. The common pattern across every real deployment is that autonomy is earned incrementally, gated by evidence, not granted on day one because the demo looked impressive.
The engineering effort in a production agent is disproportionately spent on the parts that are not the LLM call. A team that spends a week wiring up function calling typically spends a month building the guardrail, monitoring, and cost-control layer around it — the part that decides an agent is stuck, spending too much, or about to do something it should not do alone.
None of these controls are visible in the ReAct-style demo code earlier in this module — they live in a separate layer that wraps the agent loop, usually built once per company and reused across every agent the company ships, rather than reimplemented per project. A cost-tracking and circuit-breaker layer like the one below is typical of what that shared layer looks like in practice.
Five things people get wrong about LLM agents
A single request-response turn where the model calls one function and returns an answer — what is the weather in Austin, followed by one weather-API lookup — is tool use, not agency. What makes something an agent is a loop: the model observes a result, decides what to do next based on that result, and keeps deciding across multiple steps without a human choosing each step in advance. The Stripe dispute example in this module — look up the transaction, then decide whether to check the deadline, then decide whether to draft an email — is an agent because each decision depends on the previous tool's output. One tool call bolted onto a chatbot is not.
Every additional tool is an additional way for the LLM to pick wrong. With three tools (get_transaction, get_settlement_status, calculate_fee) the model rarely confuses which one to call. With thirty overlapping tools — several that could plausibly answer the same question — tool selection itself becomes a failure mode, and hallucinated arguments get more likely because the model is juggling more schemas at once. Production agents are usually more reliable with a small, sharply-scoped toolset than a large general-purpose one; if an agent needs thirty capabilities, that is often a sign it should be several specialist agents behind an orchestrator, not one agent with thirty tools.
ReAct and function calling solve different problems. Function calling is the wire format — how a tool call is represented and returned (structured JSON instead of text you regex out). ReAct is the reasoning pattern — the model explicitly reasons through what it knows, what it still needs, and which tool gets it there, before acting, then observes the result and reasons again before the next action. You can, and in production usually do, implement ReAct-style reasoning using native function calling as the execution mechanism. Dropping the reasoning step entirely — jumping straight to tool calls with no visible intermediate reasoning — is what actually causes agents to call plausible-sounding tools that do not fit the actual task.
A workflow (or chain) has its control flow fixed by the developer ahead of time: step one always runs, then step two, then step three, regardless of what step one returns — the orchestrator code decides the sequence. An agent has its control flow decided by the LLM at runtime: the multi-agent orchestrator in this module writes a plan and can route to a different specialist, skip a step, or loop back depending on what a previous specialist found. Workflows are more predictable and cheaper to run; agents are more flexible but strictly less predictable, because the same input can legitimately take a different path through the system on different runs. Choosing between them is an engineering trade-off, not a matter of which sounds more impressive.
Nothing about the agent loop guarantees this. Left unmanaged, an LLM that gets an error or an empty result from a tool frequently retries the identical call rather than changing strategy — this module's errors section covers exactly this failure mode. Self-correction only happens because you engineer it: tracking (tool_name, args) pairs already tried, injecting an explicit message when a repeat is detected, returning structured error types the model can reason about instead of opaque failures, and capping max_turns so a stuck agent stops instead of burning cost indefinitely. Robust agent behaviour is a designed property of the system around the LLM, not an emergent property of the LLM itself.
LLM agents — 5 questions interviewers actually ask
A simple function-calling pipeline executes one, or a fixed sequence of, tool calls per request and returns an answer — the developer decides how many calls happen and in what order. An agent runs a loop: after each tool result, the LLM itself decides whether it has enough information to answer or needs to call another tool, and if so, which one — that decision is made by the model at each step, not hardcoded by the developer. The practical consequence is that an agent's number of steps and exact path are not known in advance, which is exactly why production agents need max_turns caps, loop detection, and cost budgets that a fixed pipeline does not need.
Two dominant failure modes: infinite or repeated tool calls, where the LLM retries the same call after getting an error or null result instead of changing approach; and hallucinated arguments, where the model invents plausible-sounding field names or values that are not in the tool's schema. In production you catch the first by hashing the tool name and arguments for every call in the current run and flagging repeats back to the model with the prior result attached, plus a hard max_turns ceiling as a backstop. You catch the second by making schemas strict — required fields listed explicitly, additionalProperties set to false, enum constraints on categorical fields — and validating every tool call against the schema before executing it, feeding validation errors back to the model rather than letting a malformed call reach a real system.
ReAct interleaves reasoning and acting: the model explicitly reasons about what it knows and what it needs, takes an action (a tool call), observes the result, then reasons again before the next action — as opposed to jumping straight from a question to a tool call with no visible intermediate reasoning. It is still relevant because it addresses a different layer than native function calling. Function calling is just the transport — how a tool call is structured and returned. ReAct is about forcing the model to think before each action, which measurably reduces wrong-tool selection and hallucinated arguments on multi-step tasks. In practice you implement ReAct-style reasoning on top of native function calling — they are complementary, not competing.
Several layers, applied together: a hard max_turns and max_tool_calls ceiling so a stuck agent stops instead of looping indefinitely; per-tool call-count limits so one unreliable tool doesn't dominate the budget; classification of every tool as reversible or irreversible, with irreversible actions — send email, process a refund, delete a record — routed through an explicit human confirmation step rather than executed automatically; a dry_run mode during development so tools log intended actions without executing them; and output validation before acting on the agent's final answer, checking for signals like hallucination phrases or malformed structured output. None of these are optional extras — an agent that can take real-world actions without all of them is not production-ready regardless of how good the underlying LLM is.
Ask whether the sequence of steps can be known ahead of time. If the task always follows the same steps regardless of intermediate results — fetch data, transform it, write it somewhere — a deterministic workflow is more reliable, cheaper, and easier to debug than an agent, because its control flow doesn't depend on an LLM's per-step judgment. Reach for an agent when the right next step genuinely depends on what a previous step returned in a way you can't enumerate in advance — like the multi-agent dispute system in this module, where whether compliance needs to flag risk depends on what the transaction lookup actually found. The rule of thumb: use the least autonomous architecture that gets the job done, since every increment of autonomy trades predictability and cost control for flexibility.
The NLP section is complete. Section 9 — Computer Vision — begins next.
You have completed the full NLP section: tokenisation, BERT, PEFT/LoRA, RAG, prompt engineering, and agents. Section 9 goes deeper into computer vision beyond the CNNs of Module 46 — image fundamentals, data augmentation, object detection with YOLO, and semantic segmentation. Every module builds directly on the deep learning foundation from Section 7.
How computers see images. Pixel values, colour channels, image tensors, normalisation, and the preprocessing pipeline every vision model expects.
🎯 Key Takeaways
- ✓An agent is an LLM that can take actions — call APIs, run code, write files — not just generate text. Function calling is the reliable way to implement this: define tools as JSON schemas, the LLM returns structured tool_call objects (not text to parse), you execute the function, return the result as a tool message, repeat.
- ✓The function calling message loop has four message types: user (question), assistant with tool_calls (LLM decides to call a tool), tool (result of the function execution), assistant without tool_calls (final answer). Pass all messages in every API call — the full history is the agent's working memory.
- ✓Three types of agent memory: short-term (conversation buffer — pass all messages each turn, compress when approaching context limit), long-term (persist key facts in a database across sessions, retrieve at session start), semantic (vector store of past conversations, retrieve by similarity to current query).
- ✓Multi-agent systems use an orchestrator that plans and delegates to specialist agents. The orchestrator never calls tools directly — it breaks the task into sub-tasks and routes each to the right specialist. Pass shared context between specialists so they do not contradict each other.
- ✓Production agents need three guardrail layers: tool-level validation (max call counts, logging, dry-run mode), confirmation for irreversible actions (send email, process refund, delete record — always require human approval), and output validation (check for hallucination signals before acting on agent output).
- ✓The biggest agent failure mode is irreversible actions based on hallucinated data. Classify every tool as reversible or irreversible. Queue irreversible actions for human review rather than executing synchronously. In development, always use dry_run=True. Never ship an agent that can take irreversible real-world actions without a confirmation step.
Discussion
0Have a better approach? Found something outdated? Share it — your knowledge helps everyone learning here.