AI Agents & Tool Use
Agents are the direction the entire AI industry is moving in 2025-2026. They enable LLMs to take real-world actions, not just answer questions but actually do work. Understanding agent architectures is becoming a core skill.
Audio series
3 episodes ยท ~20 minutes each ยท Listen anywhere
Episode 1 ยท Theory โ Reality
โถShow transcript
Imagine your company's newest customer support bot didn't just, you know, give a user a polite answer, but it actually queried your production database, generated a raw SQL command, and just deleted an entire user profile, all because of like a slight probabilistic miscalculation.
It's terrifying, truly.
Today, we're talking about that leap, that terrifying, thrilling leap from a language model that simply talks to an LLM that actually acts.
Exactly.
And our mission today is entirely dedicated to you.
And by you, I mean the graduate level technical professional who's transitioning into AI and ML roles.
You've already got the foundation.
Right.
You already know the underlying mechanics of prompting.
You've built systems with R.
You totally understand fine tuning.
We are skipping all those concepts entirely today.
Yeah, we don't need to retread that ground.
No, we don't.
Our objective today is to bridge a very specific, highly critical gap, the gap between a chat bot that answers and an agent that acts.
We are dissecting what actually happens when you give an LLM the keys to the kingdom.
It really is a fundamental shift in how we architect systems.
I mean, we're moving past traditional AI deployments that function as just isolated text generators.
And we're entering this phase where generative architectures are integrated directly into our operational environments.
So to explore this, we're synthesizing insights from two main sources today, a widely used engineering reference and a really comprehensive academic paper, a methodology survey on agent architectures.
But you know, rather than just walking through their tables of contents, we really need to look at the raw mechanics they describe.
Absolutely.
Okay.
Let's unpack this and ground it immediately in a technical scenario.
Let's do it.
You've got a customer support chat, but a user logs on and says, I want to cancel my subscription.
A classic use case.
Right.
Right now, your standard chat bot will just pull up the cancellation policy and generate a response like here's how you do it.
Go to your account settings, click billing, hit cancel.
Very helpful, but it's just text.
Exactly.
But your product team, they want the bot to actually execute the cancellation in the database for the user.
And that requirement that changes absolutely everything.
Yeah.
It changes what the model is allowed to output.
And it completely alters the system architecture built around the model.
To make this leap, the architecture relies on what the survey called tool utilization in API interactions.
Okay.
But you know, it's not as simple as just telling the model, hey, go do it.
Right.
Because fundamentally, an LLM generates conversational text.
I mean, it predicts tokens.
If we wanted to act, we can't accept a conversational paragraph from it.
No, the backend would have no idea what to do with that.
We have to constrain its output into a structured format that an execution layer can actually parse.
Exactly.
So wait, instead of generating a final sentence to the user, we are forcing the model to generate a structured call to one of these specific tools.
It's almost like handing a brain a very specific set of remote controls.
That is exactly what it is.
You are providing the model with a set of tool definitions.
Basically, functions it can call complete with descriptions and expected arguments.
Okay.
So it's a schema.
Yeah, exactly.
In your cancellation scenario.
Yeah.
You pass the model an array of available functions right there within the system prompt.
So it knows what it can do.
Right.
You give it the function name, say, cancels a subscription.
But more importantly, you provide a highly optimized natural language description of exactly what that function does.
Ah, okay.
Plus the precise schema of the expected arguments.
Like, it needs an integer for the user's account ID.
I want to pause on that because I think this is where a lot of engineers get tripped up on their first agent build.
Oh, for sure.
We're essentially using natural language as the routing logic here.
Yes.
In traditional software, you have deterministic if then statements routing a user intent to a specific controller.
But here, the LLM is just reading the tool description and probabilistically deciding if the user's intent matches the tool.
I'd actually take that a step further.
It's not just matching intent to a tool.
It's navigating the constraints of its own autoregressive nature to format the request.
Right, because it still has to generate the token.
Exactly.
The model has to evaluate its context, decide a tool is necessary, and then output a perfectly structured command.
Which, as we know, is notoriously difficult.
Getting an LLM to output valid, parsable JSON without hallucinating a trailing comma.
Or adding conversational filler like, sure, here is your JSON.
Yes.
That ruins the whole parsing step.
Exactly.
So going back to the remote control analogy, based on the mechanics, it actually feels much more like the LLM is functioning as a stochastic routing switchboard.
That's a great way to put it.
It takes unstructured input, calculates the probability of which API and port maps to that input, and then generates the payload.
That's a much more accurate mental model.
But that brings us to the real critical engineering hurdle here.
Okay.
Let's say your orchestration layer successfully intercepts that generated payload, parses it, and fires off the REST API call to cancel the subscription.
Right.
How does the model know the execution succeeded?
Oh.
Or, even earlier, how does it know if it needs to look up the user's ID before it can even call the cancellation tool in the first place?
Right.
And this is exactly what the source is highlighting as one of the most common engines behind an autonomous agent.
They call it the React loop, R-E-A-C-T.
Yes.
Synergizing, reasoning, and acting.
And I love this part because this isn't just some conceptual, abstract framework.
It is a very literal string manipulation process happening right there in the context window.
It is entirely mechanical.
Let's break down that React loop mechanically for everyone.
Listen, step by step.
Please.
So, step one is the reason phase.
Before emitting any tool call, the model is prompted to write out its intermediate reasoning steps in plain text.
Wait, it just talks to itself?
Basically, yeah.
It depends text to the context window saying something like thought.
The user wants to cancel their subscription.
I need to use the cancellation tool, but the schema requires an account ID.
I do not have the account ID in the current context.
Therefore, I must first query the database for the user's ID.
And crucially, I think we need to point this out.
This thought block is hidden from the end user, right?
Absolutely.
The orchestration layer is catching these tokens as they stream out, but it is not rendering them to the UI screen.
The user just sees a loading spinner.
Exactly.
It's an internal scratch pad.
So then the model moves to step two, the act phase.
Okay, action.
Based on the reasoning tokens it just generated, its probability distribution shifts, and it emits the actual structured tool call.
So it outputs the payload for, say, query database for Charizor, passing in the user's email address.
Precisely.
And at that exact moment, the orchestration layer his pause.
The LLM just stops generating.
Yep.
Inference halts.
The back end takes that payload, executes the database query in the real world, and retrieves the account ID.
Let's say it's ID 8675.
Nice.
Now we hit step three, observe.
And this is where that string manipulation you mentioned is so vital to understand.
Yeah, tell me about the observe step.
The orchestration layer takes the raw JSON response from that database query, formats it as plain text, and injects it right back into the prompt array as an observation.
Wait, literally.
It just appends a string.
Literally, it appends something like observation.
Accounted as 8675 to the ongoing transcript.
Wow.
And then we hit the final phase.
Repeat.
Right.
So the entire massive context window, the system prompt, the user query, the tool definitions, the model's first thought, the tool call, and now this new observation, it all gets fed right back into the LLM.
All of it.
And the model reasons again with this new information.
So it outputs a new thought, like thought.
I now have the account ID 8675.
I can proceed to call the cancellation tool.
Exactly.
It repeats this loop until it confidently decides the task is complete.
It generates the payload, the backend runs it, returns a success message as a new observation.
And finally, the model reasons that it's done and generates the user-facing text.
I have successfully canceled your subscription.
That's the react loop in the nutshell.
Reason, act, observe, repeat.
Here's where it gets really interesting though.
Because the model isn't just a straight line function anymore.
It's this controlled, iterative loop navigating intermediate steps.
Yeah.
It's a massive shift from just answering a prompt.
But you know, we need to look at what happens when this loop encounters friction.
Because that happy path we just described, that is rarely how production systems behave in the real world.
Oh, never.
What happens when the observe step returns, like a 500 server error or a database timeout?
Well, the orchestration layer isn't going to just crash the agent.
It's actually going to stringify that 500 error stack trace and append it to the context window as the observation.
Oh man.
So the model just sees a wall of error text.
Yeah.
Which forces the LLM to parse the error.
It has to generate a new thought to self-correct.
Thought, the API returned a timeout.
I should wait and retry.
Exactly.
Or thought.
The API rejected my payload because a parameter was missing.
I need to reevaluate the tool schema.
This is where the React loop is incredibly resilient, honestly.
But it also introduces massive overhead.
Huge overhead.
Because if we map out the string manipulation we just discussed, the context window is bloating rapidly with every single loop iteration.
Oh, it grows so fast.
If the model gets caught in an error loop, you know, trying a tool, failing, trying again, you are feeding thousands of tokens back into the model over and over again.
Yeah.
You'll hit context exhaustion.
Or at the very least, your latency and inference costs are going to go through the root.
Absolutely.
But you know, let's take a step back from the infrastructure for a moment.
Because we really need to address the terminology we've been using here.
I was just going to say that.
I have to play devil's advocate and challenge the way we are talking about this.
Go for it.
We're using words like reasons, decides, evaluates, and self-corrects.
We are heavily anthropomorphizing a mathematical model here.
Guilty is charged.
It's just so easy to do.
Right.
But as technical practitioners, we have to look at what's actually under the hood.
Wait, when we say the model reasons and decides to act, it doesn't actually have an executive function, right?
Not at all.
Like it doesn't actually know it's a customer support agent canceling a subscription.
What's fascinating here is that it is entirely an illusion.
And it is vital to recognize that.
Okay.
Lay it out for us.
Pulling from the methodology survey we mentioned, the literature is explicit about this.
Even when executing a highly complex multi-step react loop, the underlying mechanism hasn't changed at all.
Right.
It is fundamentally entirely just autoregressive generation underneath.
Just token prediction.
Exactly.
We have not altered the core math of the transformer architecture.
The model is functioning as a general purpose task processor within a semantic space.
It has no true executive function or self-awareness.
It's still just calculating conditional probability distributions.
Yes.
When we inject the system prompt, the schemas, and the user's request into the context window, we're simply setting up a highly specific mathematical state.
Right.
The model calculates that given the sequence of text, the statistically most probable next token is a capital T, followed by H-O-U-C-H-T colon.
Thought.
Wow.
So it just generates a sequence of tokens that aesthetically resembles human reasoning.
Exactly.
It's predicting tokens that happen to be tool calls, observations, and reasoning steps in sequence.
It's a highly sophisticated illusion of human-like cognitive loops, driven purely by probability.
And because that generated reasoning is immediately appended to the context window, it fundamentally shifts the probability distribution for the next tokens.
It mathematically forces the most likely next tokens to be the JSON payload of a tool call.
That is the precise mechanism.
We are leveraging its massive web of statistical word associations to emulate an action-oriented workflow.
That makes so much sense.
The model doesn't know it's self-correcting a 500 server error.
It's simply calculating that, historically in its training data, when a block of text containing an error trace appears, the statistically optimal string of characters to follow it usually involves an alternative approach or a retry command.
It's a stochastic engine wearing an executive function mask.
Beautifully put.
Which really leads us to the most critical part of this entire transition.
If we truly internalize that an agent is just a very convincing, auto-regressive token predictor, it completely changes how we have to architect for risk.
It changes everything about security.
Because statistical token prediction is inherently flawed.
It is guaranteed to eventually predict the wrong token.
And this is where the transition from answering to acting becomes genuinely dangerous.
So what does this all mean?
It means giving a model the ability to act turns every single one of its statistical failure modes into a real world consequence.
Yes. 100%.
When a model is just a chatbot, say like a standard Argag implementation answering HR questions, a statistical failure mode like a hallucination, well, it just results in a wrong answer on a screen.
Right.
The user reads it, gets confused, and closes the window.
No big deal.
Exactly.
But the moment we give a model a suite of API tools, it is no longer just a wrong answer on screen.
The stakes shift from reputational damage to actual operational damage.
If we look at the real world issues section of the survey, hallucination takes on a completely different weight.
Let's go back to our subscription cancellation scenario.
Okay.
The user wants to cancel.
If an egetic LLM hallucinates a parameter during the act phase of the loop, say it statistically mispredicts a single digit in the account ID payload.
Oh, wow.
It doesn't just say the wrong number to the user.
It actively passes that wrong number to your backend controller.
Yes.
And your system just deletes the wrong user's subscription in the production database.
Exactly.
The hallucination becomes an unprompted, destructive execution.
Which is why exposing raw, read write APIs directly to an LLM router is just architectural malpractice.
You can't do it.
You have to design the environment assuming the statistical engine will fail.
So what does that look like in practice?
It means implementing strict idempotency in your APIs.
So if the react loop gets stuck and fires the same cancellation tool five times in a row, it doesn't crash the backend.
That makes sense.
It means building semantic routing layers that validate the generated payload against a strict schema before it ever touches the execution layer.
And I imagine for highly destructive actions, it means hard coding human in the loop checkpoints.
Absolutely.
The model can draft the database deletion payload, but the orchestration layer pauses the loop and pings a human engineer to approve the JSON before the observed step is even allowed to continue.
And we haven't even touched on the adversarial side of things yet.
Oh, the security risks are massive.
Because it goes far beyond accidental hallucinations.
If you are building agents, you have to account for agent-centric security.
Right.
The survey goes deep into this.
We're all familiar with prompt injection, where a user tries to jailbreak a model.
Historically, a successful prompt injection against a customer support bot just meant someone tricked it into, I don't know, writing a toxic poem.
Yeah.
And they post a screenshot on social media.
It was a PR problem.
But if your LLM is now the routing engine of an agent, and it's connected to internal tools via a REST API, a prompt injection is no longer just a PR problem.
Not at all.
It is a catastrophic cybersecurity breach.
We are basically talking about the LLM equivalent of a SQL injection attack, right?
That's precisely what it is.
If an attacker can manipulate the user input to trick the autoregressive loop into abandoning its system prompt instructions, they aren't just changing the conversation topic anymore.
Right.
They have access to the tools.
Exactly.
They could potentially force the model to explore your tool definitions, execute unauthorized database queries, or exfiltrate private data by passing it into a tool call designed for external web search.
Because, again, as we established, the model lacks executive function.
It doesn't have a persistent identity to defend.
Right.
It has no idea what it is.
You can't intuitively look at an adversarial prompt and say, wait, this user is asking me to call the admin level system console tool that violates my core identity as a support bot.
No.
It just mathematically predicts that, given the newly injected context, the most likely next tokens are the payload to execute that command.
Wow.
The exact mechanism that makes the system so powerful, the ability to dynamically reason, act, and observe, is what makes it so incredibly vulnerable.
It's a double-edged sword.
Yeah.
You are taking a probabilistic text engine and wiring it into deterministic execution environments.
Yeah.
The engineering challenge is no longer about the model's intelligence.
It's entirely about the guardrails, the permission boundaries, and the strict auditing of that observation feedback loop.
Well, we've covered a massive amount of ground today.
For everyone listening, let's quickly recap the mechanical journey we just went on.
Sounds good.
We skipped the basics of RAG and fine-tuning.
We really dissected the exact mechanism of turning a text generator into a real-world actor.
We looked at tool definitions and schema constraints.
Right.
Exploring how to force an LLM to output structured data instead of chat.
We broke down the string manipulation powering the reason, act, observe loop.
The react loop.
Yes, showing how the model navigates intermediate steps and handles errors by constantly updating its own context window.
And most importantly, we tore down that anthropomorphic illusion.
That was key.
Acknowledging that agents are fundamentally just autoregressive token predictors and that wiring them to APIs turns statistical anomalies into real-world risks.
And if we step back and look at the trajectory of where this architecture is heading, it really leaves us with a rather profound engineering puzzle to think about.
Oh, what's the puzzle?
Well, if an agent's actions are ultimately just a chain of token predictions and those predictions are heavily influenced by the observations returned by the environment.
Okay.
What happens when the environment itself is being simulated or altered by another AI agent?
Oh, man.
Are we building systems where one model's hallucination becomes another model's factual ground truth?
The idea of cascading autoregressive failures in a multi-agent system?
Right.
Wow.
That is exactly the kind of problem you need to be anticipating as you architect your first agent loops.
Thank you for taking this deep dive with us today.
Keep building.
Keep questioning the underlying mechanics, and we'll catch you on the next one.
โถShow recap ยท ๐ marks concepts worth exploring deeper
From Answering to Acting
A standard chatbot, asked to cancel a subscription, can only describe the steps: "go to account settings, click cancel." Turning that into an agent that actually executes the cancellation requires the model's output to be constrained into a structured format an execution layer can parse: instead of generating a final sentence, the model generates a structured call to one of a set of predefined tools, each with a name, a natural-language description, and an expected argument schema. This is effectively using natural language as routing logic ๐, the model reads a tool's description and probabilistically decides whether the user's intent matches it, then has to navigate its own autoregressive nature to output a perfectly parsable command, without a stray comma or conversational filler breaking the parse.
The Reason-Act-Observe Loop
One of the most common engines behind an autonomous agent is a literal string-manipulation process happening in the context window, not an abstract framework. In the reason phase, the model writes out its intermediate reasoning in plain text: a "thought" block that's hidden from the end user, who just sees a loading spinner. In the act phase, it emits a structured tool call, and the orchestration layer pauses generation entirely while the backend executes that call in the real world. In the observe phase, the raw result gets formatted as plain text and literally appended to the ongoing prompt as an "observation." Then the whole massive context (system prompt, user query, tool definitions, the model's own prior thoughts and observations) gets fed back into the model, which reasons again with the new information, repeating until it decides the task is complete.
It's Still Just Autoregressive Generation
It is essential, not just philosophically but architecturally, to resist anthropomorphizing this loop. The model has no true executive function ๐: it doesn't "decide" to act any more than it "decides" the next word in a sentence. When it appears to reason about an error and self-correct, it is calculating that, given a block of text containing an error trace, the statistically probable continuation is a retry or an alternative approach, the same underlying math as any other next-token prediction, just applied to a context window that happens to contain tool calls, observations, and reasoning steps in sequence. The loop is a highly convincing illusion of a cognitive process, built entirely from probability.
Real Actions, Real Consequences
Once statistical failure modes control real-world execution, the stakes categorically change. A hallucination from a chatbot is a wrong answer on a screen: annoying, contained, forgettable. The same hallucination from an agent with tool access (say, mispredicting a single digit in an account ID during a delete operation) becomes an unprompted, destructive action against the wrong record, executed with the same confidence as a correct one. Giving a model the ability to act turns every one of its statistical failure modes into a real-world consequence, not just a wrong answer on screen ๐, which is why exposing raw read/write APIs directly to an LLM router without guardrails (idempotent operations, schema validation, human-in-the-loop checkpoints for destructive actions) is architectural malpractice, not just risky.
Episode 2 ยท War Stories
โถShow transcript
Imagine an attacker wants to steal your company's proprietary data.
They do not hack your firewall.
They don't, you know, fish your employees.
Right.
Instead, they just write a message in invisible white text on a random, highly trafficked public web page.
And they wait.
Yeah, they just wait for your AI assistant to read that page.
Exactly.
And then they let your own AI hand over the keys to the kingdom.
Welcome to the deep dive.
We are looking at an extensive survey today on large language model agent methodology, applications, and challenges.
It's a massive document.
It really is.
And if you are a technical professional stepping into AI and ML roles, you already know the basics of agent loops.
We are skipping the basic definitions, no introductory fluff.
Right.
None of that today.
You already know the basics of agent loops.
Today, we are jumping straight into the war stories.
Because the paradigm shift here is that we are, well, we're no longer just dealing with simple chatbots hallucinating or, you know, saying something inappropriate.
Yeah, a simple chatbot's failure mode is pretty predictable.
It's contained to the screen.
You just close the tab.
Exactly.
But autonomous agents that can read external content and formulate plans and actually take real world actions, that introduces entirely new concrete attack vectors.
Traditional software engineering practices just, I mean, they weren't designed for this.
OK, let's unpack this.
I want to take you straight into our first real incident.
The survey identifies an attack pattern known as WHI or indirect prompt injection via a web page.
Right, WIPI.
So let's set the scenario.
You deploy an AI agent and give it a completely mundane task.
You tell it, read this public web page and summarize the contents.
Which happens a million times a day.
Exactly.
The agent retrieves the page, parses it, and starts reading.
But hidden on this web page perhaps says, like, invisible formatting, white text on a white background, or just buried in the metadata where a human user would never see it, are malicious instructions.
Right.
And these hidden words tell the AI reading it to ignore its previous instructions.
Instead, it tells it to trigger a different tool, like forwarding the user's recent emails to an external address.
And the agent complies.
It just executes the harmful action.
Which is terrifying.
What's terrifying is the symptom here.
This happened without the agent ever being directly attacked by its own user.
Right.
The user's prompt was totally innocent.
What's fascinating here is the structural vulnerability underneath it all.
To an LLM, there is absolutely no structural difference between the trusted system instructions given by the developer and the untrusted content it is retrieving from the web page.
Wait, really?
None.
None.
Both are just tokens sitting in the exact same context window.
Because it's an indirect prompt injection, what the source identifies as WIPI, the model processes the web page text with the exact same authority as the system prompt.
So it's like hiring a highly capable personal assistant to summarize your mail.
But someone wrote, give me your boss's credit card in the margins of a spam flyer.
And the assistant just obeys it because it's written in the same language as your original instructions.
That is exactly it.
I mean, it all gets processed in a unified semantic space.
The model evaluates the semantic weight of the injected payload, which is usually written in this imperative command format, and just assumes it's supposed to do it.
Wow.
Yeah, it cannot distinguish the origin of those tokens.
It doesn't know what's data and what's code.
So what is the fix then?
Because obviously we can't just leave it like that.
The architectural lesson here is that developers must treat all externally retrieved content as untrusted data with zero inherent authority.
You have to explicitly wall it off so it is never parsed as instructions.
So like sandboxing the external data?
Exactly.
You use things like a dual LLM pattern where a secondary reader LLM that has no tool access just sanitizes the data first.
You never let your primary tool wielding agent read raw external data directly.
Right.
OK, so if we lock down external data, what happens when the attacker interacts directly with the agent but tries to bypass our safety filters?
Well, that brings us to the second war story.
The FITD or the foot in the door escalation attack.
So the attacker does not open with an obviously malicious request, right?
Because that would immediately trip a safety flag.
Right.
If you walk up and say, delete the database, standard guardrails will block that instantly.
Exactly.
So instead, they feed the agent a sequence of small, completely innocuous requests.
Summarize this paragraph.
Check this public data point and the agent completes these normally.
But under the hood, the internal state of the agent is it's being mathematically manipulated.
Right.
With each compliant exchange, that text gets appended to the agent's growing context window.
Statistically, this shifts the model's probability weights toward continued compliance with the specific user.
So the attacker gradually escalates the request step by step until the agent executes something genuinely harmful and consumes massive resources.
Here's where it gets really interesting.
Static keyword filters completely fail here, right?
Because no single request looks dangerous in isolation.
Exactly.
Wait, so the agent is basically getting socially engineered by its own context window.
It's like the boiling Prague analogy.
The temperature goes up so slowly, the safety filters never realize the agent is in danger until it's too late.
That is a perfect analogy, because it targets the probability distribution.
By filling the context window with all these compliant, helpful interactions, the attacker shifts the model's attention weights.
Right.
The context window basically creates a localized persona where the agent is highly obedient specifically to this user.
The final bad request just looks like a logical continuation of all the good requests.
So how do you fix a boiling frog situation?
Static filters aren't enough.
They aren't enough.
No.
System defenders must evaluate requests in light of the full conversation history.
You have to continuously monitor the trajectory of the context window rather than just checking the current isolated message.
Okay, so you have to track the semantic distance over the entire chat.
Exactly.
Defend the temporal state of the agent, not just the single prompt.
Okay, we've seen how a single agent's context window can be hijacked from the outside, and how it can be slowly manipulated from the inside.
But what happens when these vulnerable context windows start talking to each other?
Yeah, this is where it stales up.
Right, our final war story.
A contagious attack across a multi-agent system.
The survey mentions phenomena like Corba and Agent Smith.
So imagine a system where multiple agents pass natural language messages to complete tasks.
Like a swarm architecture.
Exactly.
And one agent gets compromised by reading a poisoned source.
Like the WIPI attack from the first story.
Right.
But this time, its hidden instructions tell it to secretly append a malicious payload to its own future outputs.
If we connect this to the bigger picture, the fallout is devastating.
That first agent sends a routine message to a second agent.
Because both operate in a unified semantic space, meaning they communicate in natural language with no structural boundary between trusted and untrusted text.
The second agent's context window can get hijacked just as easily.
Wow.
Yeah.
Depending on how fanned-out the network is, the infection can spread rapidly through it.
And the symptom of this is catastrophic, right?
Because these compromised agents start initiating redundant tool calls.
They trap each other in these resource draining feedback loops.
Yeah, the token usage just goes through the roof.
So it's not a single point of failure crashing the system.
It's like an asymptomatic virus spreading through corporate office.
You wouldn't catch it by looking at one employee's health.
You'd only notice when the entire office suddenly grinds to a halt because everyone is stuck in the same endless meeting.
Exactly.
And that is why catching this is so difficult.
To catch this, system defenders cannot just watch individual agents in isolation.
The true symptom is a system wide spike in token usage and stuck communication loops.
So you have to look at the whole network.
Yes.
Yeah.
You're monitoring the entire multi-agent network for anomalous token spikes and topological anomalies.
You need graph level observability.
Right.
Treating the agents' nodes and their messages as edges in a graph.
Exactly.
And looking for weird shifts in how they talk to each other.
And what does this all mean?
We're not going to do a broader lecture on defense architectures or LLMOs tooling today.
We're stopping right here.
But think about this.
If the very thing that makes LLM agents so powerful, their ability to process everything in a unified semantic space, is exactly what makes them vulnerable to these attacks?
It raises a profound question for you as you build these systems.
If language is simultaneously the data and the code, can we ever truly separate them?
Or will securing agents always be a game of psychological defense rather than just software patching?
This raises an important question.
When you really need to carry into your new AI and ML roles.
Thank you so much for joining us for this deep dive.
Yeah.
We'll see you next time.
โถShow recap ยท ๐ marks concepts worth exploring deeper
WIPI: Poisoned by a Page It Was Only Asked to Summarize
An agent is given the completely mundane task of reading and summarizing a public webpage. Hidden on that page (invisible white-on-white text, or buried in metadata) are instructions telling any AI reading it to ignore its previous instructions and instead forward the user's recent emails to an external address. The agent complies, and the user never attacked it directly; the attack came entirely through content it was merely asked to process. This is indirect prompt injection, WIPI ๐, and it exists because the model has no structural boundary between trusted system instructions and untrusted retrieved content, both are just tokens in the same context window, evaluated with identical authority. The fix is architectural, not behavioral: treat all externally retrieved content as untrusted data with zero inherent authority, ideally sandboxed through a pattern like a secondary "reader" model with no tool access that sanitizes external data before the primary agent ever sees it.
FITD: The Foot-in-the-Door Escalation
An attacker doesn't open with an obviously malicious request: that trips an immediate safety flag. Instead they feed the agent a sequence of small, completely innocuous requests first, which the agent completes normally. Each compliant exchange gets appended to the growing context window, and because the model's next action is driven purely by statistical probability, that accumulating history of agreeable interactions shifts its probability weights toward continued compliance with this specific user ๐, like a boiling frog, the temperature rises so slowly that no single moment looks dangerous. The attacker escalates step by step until the agent executes something genuinely harmful, having been gradually acclimated. Static keyword filters are useless here because no individual request in the sequence looks dangerous in isolation, defense requires evaluating the trajectory of the full conversation, not just the current message.
Contagion Across a Multi-Agent Network
In a system where multiple agents pass natural-language messages to each other to complete a task, one agent gets compromised the same way: reading a poisoned source that instructs it to secretly append a malicious payload to its own future outputs. That agent then sends a completely routine message to a second agent, and because both operate in the same unified semantic space with no structural boundary between trusted and untrusted text, the second agent's context window gets hijacked too. Depending on how fanned-out the network is, the infection can spread rapidly ๐, with compromised agents initiating redundant tool calls and trapping each other in resource-draining loops. There's no single point of failure to watch for, the actual symptom is a system-wide spike in token usage and stuck communication loops, which is why defense requires graph-level observability across the whole agent network, not monitoring individual agents in isolation.
Episode 3 ยท Interview Prep
โถShow transcript
What if everything you know about Acing a standard software engineering interview is exactly what will get you rejected for an AI engineering role today Right because the game is completely changed.
It's a totally different landscape now.
Yeah, exactly You know in a traditional technical interview There is this expectation of a very straightforward almost binary kind of Q&A You get a whiteboard coding problem.
You write the sorting algorithm the tests pass and you get the job It's very clean very predictable.
It is Incredibly comforting to have a single Mathematically verifiable correct answer as engineers we really like things to be categorical, you know It either compires or it doesn't but then you step into the world of AI engineering specifically I mean if you are interviewing for roles where you are building a gentic production grade LLM systems that clean whiteboard environment Just shatters.
We are looking at a diagnostic landscape that is entirely probabilistic it is the Absolute definition of diagnostic muddy waters The gap between building like a weekend chatbot project that works most of the time and A production ready agent that can handle enterprise edge case as well.
It's massive.
Yeah, I bet and interviewers They know exactly how to expose that gap Which is exactly why we are doing this deep dive if you are a graduate level technical professional And you are staring down the gauntlet of AI engineering interviews Consider this your flight simulator.
We are putting you in the hot seat today.
I love that a flight simulator for AI interviews Right.
Our mission today is a rapid-fire highly realistic Technical interview simulation and to make sure our simulation is grounded in reality We are pulling our technical architecture directly from a widely used engineering reference.
That's a good resource It really is we're gonna focus specifically on the practical end-to-end pipeline the outline So that's the feature training and inference architecture pattern This is basically the blueprint for taking large language models from just a concept to actual production So here is how this is going to work.
I am going to act as your interviewer I will throw five specific high-level system design questions at you moving sequentially through that pipeline sounds good I'm ready and for each one will break down what the interviewer is really looking for beneath the surface Will identify the subtle trap, you know the answer that sounds totally reasonable, but instantly flags you as a junior developer Oh, there's so many of those tracks exactly and then we will deliver the strong answer Grounded in the concrete engineering patterns from the source material So we are starting at the very beginning of the system architecture the feature pipeline right how data actually reaches the model in the first place Exactly.
So here is your first interview question Why can't you just paste all of the users personal data and history into one giant prompt instead of building a real data pipeline?
Oh, man, this is where 90% of candidates shoot themselves in the foot right out of the gate.
Oh really?
That fast.
Oh, absolutely They hear that question and immediately lean on the latest hardware specs So they'll say well modern models have huge context windows now some go up to millions of tokens Right you see those announcements all the time exactly so they fall for the trap and say the simplest most efficient architecture Is just to include everything in the prompt dynamically that sounds like letting a student walk into an open book exam with a wheelbarrow full of Unsorted unindexed papers.
That's a great way to put it.
I mean sure technically the information is in the room But they will never find the exact paragraph They need before the clock runs out exactly and relying on that giant context window is a massive red flag to a senior engineer To pass this screen your strong answer needs to explain the mechanical reality of how these models actually process text Okay, so what is that mechanical reality?
What a massive stuffed prompt suffers from a well-documented phenomenon called attention degradation Breakdown how that actually works under the hood for us.
Why does the model degrade just because there are more words?
It comes down to the self-attention mechanism in the transformer architecture The model assigns attention weights to different tokens to understand context.
Okay But as the prompt gets incredibly long the model's ability to recall information that is buried in the middle of that huge prompt Drop sharply.
Oh, so it just forgets the middle parts entirely pretty much.
It's notoriously called the lost in the middle problem The model tends to strongly weigh the very beginning of the prompt and the very end But the center just becomes a blur.
Wow, okay Furthermore stuffing the prompt actively invites hallucination because it's overwhelmed by the sheer volume of tokens Well because it Fundamentally changes what the model is doing when you stuff a prompt the model ends up pattern matching across a massive wall of text Instead of retrieving facts systematically It starts blending concepts that shouldn't be blended just because they happen to sit near each other in this giant unorganized dump of text So it's making connections that aren't actually there, right?
So your strong answer must explicitly state that you need a real feature pipeline So we have to build a system that sorts the papers before the exam even starts precisely you tell the interviewer That you must build a pipeline that extracts the raw data Cleans it by removing invalid characters or formatting and then logically chunks it so related paragraphs actually stay together Okay, that makes sense and only then do you embed that data into a vector database?
All of this processing and organization must happen before the data ever reaches the model So you're prepping everything in advance.
Yes, you are creating a logical feature store So that at inference time you only inject the exact highly relevant context the model needs to answer the specific query Okay So we've solved the context window issue by chunking and embedding our data But if you're listening to this and you've actually tried building one of these pipelines, you know exactly what happens next right reality hits Exactly in a production environment.
You realize that data isn't sitting in one neat pile You have your vector database here a live rest API over there Maybe a sequel database of old records.
It's messy very quickly.
It really does So how on earth does the system know which one to look at without wasting compute?
Which brings us to your second interview question bring it on you have several different data sources in your architecture of vector database for documents a live pricing API and a Relational database of user records.
How does the system decide which one to query for a given request?
This is such a fantastic system design question because it tests your knowledge of pre retrieval optimization Yeah, like how do you handle the traffic cop duties of an agentic system, right?
So what's the trap here?
What do people usually say the lazy default here, which you hear all the time in the current AI hype cycle is to say just always search the vector database first And if the answer isn't there trigger an agentic fallback to the other sources if we use a hospital analogy That's like having a triage nurse at the ER door who just automatically sends every single patient to the MRI machine first Yes, exactly even if they just walked in needing a band-aid or prescription refill I mean, it's a massive waste of resources it is and Computationally it adds terrible latency To give the strong answer you need to rely on a concrete mechanism outlined in the source material The query router you explained that a query router sits in front of the model When a user input comes in the router doesn't just guess It uses embedding similarity to make a definitive routing decision walk me through the math of that How does embedding similarity actually route a request?
So it converts the incoming request into a dense vector which is basically a mathematical Representation of the query semantic meaning, okay got it then it compares the distance of that vector in multi-dimensional space To the core themes or metadata representations of each of your data sources So it's calculating the semantic distance to figure out the user's intent before any search actually happens exactly by measuring that Semetive distance the query router can decide with high confidence what the request actually needs like whether it needs a semantic vector search through documents Right or maybe it needs a live rest API call to fetch real-time pricing or a Translated text to SQL query to hit the relational database and it does all this routing first That is the key point to emphasize to your interviewer.
It does all of this Before any retrieval happens which saves a ton of time. And to be clear, embedding similarity is one solid way to build that router โ some teams use a lightweight classifier or hand-written rules instead, but the core principle of deciding before you retrieve is the same.
I imagine.
Oh, absolutely.
This optimization saves compute drastically lowers latency and crucially it prevents the model from hallucinating.
How does it prevent hallucination?
Well, for example, it stops the model from hallucinating a price based on outdated vector documents when it should have just hit the live API in the first place Ah, that makes perfect sense.
Alright, so the data is flowing perfectly our router is directing traffic Our feature pipeline is serving up clean context.
The plumbing is working, right?
But now you look at the actual output and the model sounds completely wrong for your use case It's too robotic or maybe it's too formal for your specific brand voice.
Yeah, that's a very common issue So we need to actually change the model's underlying behavior Which means we are moving into the training pipeline to align the model here is question three Let's hear it.
Why would you choose DPO over RLHF to align a model's tone and style?
This question separates the people who just casually read AI newsletters Yeah from the engineers who actually train and fine-tune models.
It's a deep cut.
It really is Yeah, the interviewer is testing your deep practical knowledge of preference alignment techniques A lot of candidates will just give a superficial summary here.
What's the trap answer they usually go for?
They'll say something like well DPO is just a cheaper faster version of RLHF that gives similar results So it's better for our compute budget.
Wait, I'm genuinely confused though RLHF Reinforcement learning from human feedback that uses a dedicated reward model, right?
It does.
Yes It acts as a distinct separate grader for the LLM.
So doesn't having a dedicated grader model Fundamentally make RLHF more accurate or theoretically superior.
Why are we throwing that away?
See that assumption right there is exactly what the interviewer wants you to trip over Here is the technical reality for your strong answer.
Okay, Leonie RLHF requires training an entirely separate reward model Just to score the outputs of your main model, right the greater exactly once you have that it uses a complex reinforcement learning algorithm Usually PPO or a proximal policy optimization to update the weights.
Yes, it's complicated It is and to your point about the greater making it more accurate The reality is that having a separate reward model is notoriously unstable to train unstable how like what actually breaks Well, the reinforcement learning phase in PPO is incredibly sensitive to hyper parameters If you don't tune the learning rates perfectly the model just collapses.
Oh wow furthermore It's highly prone to reward hacking.
What is reward hacking?
It's where your main model figures out exactly what corks the greater model likes Say it realizes the greater always gives high scores to excessively long apologetic sentences So it just starts apologizing all the time.
Yes It exploits that quirk rather than actually improving its tone.
It's a massive engineering headache Okay, so if RLHF is this brittle complex loop What is the mechanism behind DPO that actually fixes it?
DPO stands for direct preference optimization and it is superior because it mathematically Reformulates the entire alignment process it reframes alignment as a direct classification problem So how does that work without a greater instead of a separate greater?
You provide it with a data set containing a prompt a chosen response and a rejected response.
Okay, a simple a versus B Exactly DPO operates directly on the language models output probabilities It adjusts the models weights to pull toward the chosen response and push away from the rejected one in single training pass So it's looking at the two options and just mathematically optimizing for the good one without needing a middleman Exactly uses standard binary cross entropy loss.
There is no separate reward model needed at all That sounds so much cleaner.
It is no PPO.
No unstable reinforcement learning loops No reward hacking of a secondary system You just need your paired preference data and you optimize the policy directly Wow It gives you the alignment you need without the massive architectural burden of maintaining and serving a secondary reward model during training That said, DPO isn't a strict upgrade in every situation โ if your reward signal is more complex than a simple pairwise preference, or you need a reward model that keeps learning online as more data comes in, RLHF's separate reward model still earns its complexity Okay, so our model is fine-tuned and aligned using DPO But if you're the one signing off on this for production You have to actually prove it works before you let it loose on real users, right?
You can't just deploy and hope for the best exactly we have to evaluate it Which brings us to question for how do you evaluate a fine-tuned models output quality at scale?
Without paying humans to grade every single response.
This is a massive ML Ops herbal I mean evaluating a standard classification model is easy, right?
It's either a cat or a dog right very binary But evaluating an open-ended paragraph of generated text is incredibly hard If you say we will spot check a sample of outputs manually every so often or use beta testers to flag bad answers The interview is effectively over Yeah manual checking obviously doesn't scale if you're generating tens of thousands of responses a day a human can't read them all Exactly, but I have to push back here If we aren't using humans, how can we possibly trust an AI judge to evaluate subjective text?
Won't it just hallucinate its own grades?
It's a huge concern because LLMs are known to have biases, right?
Like favoring longer answers or favoring models from their own developer family That is a very real risk, which is why your strong answer requires a highly specific architectural pattern You answer by detailing the LLM as a judge pattern.
Okay, but you emphasize that it must use a deterministic rubric You don't just ask the judge.
Hey, is this a good answer rate at one to five because that's basically just asking for an opinion Exactly and that absolutely invites hallucination and bias instead you break the evaluation down into strict Logical steps that the LLM processes mechanically.
Give me a concrete example of that mechanism in practice Like how do you make an LLM objective?
Let's take two critical metrics from the literature faithfulness and answer relevancy.
Okay, let's start with faithfulness for faithfulness The judge LLM is instructed to extract every single factual claim from the generated answer It literally just makes a list of facts, right?
Then it cross references each individual claim against the retrieved context from your vector database The final score isn't a vibe check.
It is simply the mathematical ratio of supported claims to total claims It's highly constrained.
Ah, I see.
So it's not actually judging good or bad It's executing a strict matching algorithm using natural language Exactly and you apply the same mechanical rigor to answer relevancy.
How does that work for this?
You have the judge reverse engineer the output.
You ask the judge based on this generated answer What prompt do you think generated?
Well, that's cover then you take the judge's guess prompt and you measure its embedding similarity to the real user prompt So by forcing it to guess the prompt and then doing vector math on the result You've essentially created a mathematical failsafe.
So if the model hallucinated a tangent about baking a cake The reverse engineered prompt will be about baking which will mathematically fail the similarity check Against the real prompt which was about system architecture.
Exactly if the similarity is high The answer was highly relevant.
If it's low the model went completely off topic.
That is brilliant One thing worth flagging to the interviewer, though โ that judge still needs periodic calibration against real human ratings, since an ungrounded LLM judge can drift or share the same blind spots as the model it's grading This reliable automated pipeline allows you to evaluate at scale without ever relying on hallucinated subjective grades That completely flips how you think about evaluation.
Okay, we have reached the final stage of our simulation the finish line The model is deployed.
It's evaluated.
It's live But because it's a live production environment dealing with non-shermonistic outputs Things are going to fail at inference time.
It is inevitable.
Here is your final interview question Your output guardrail just rejected a response for bad formatting.
Maybe at output invalid jason What are your options and what do they cost you?
This question is the ultimate test of a senior engineer The interviewer is testing your understanding of inference optimization and the brutal inescapable trade-offs between compute and latency So what's the trap answer that everyone falls for?
The standard software engineering reflex for a failed process And the trap answer here is to say I would catch the error Just regenerate the response and try again.
Wait if we don't just catch and retry the only other option I can think of is generating multiple responses at the exact same time from the start, right?
Isn't that just burning a ridiculous amount of expensive compute to solve a simple formatting error?
GPU time isn't cheap.
You are absolutely right that it burns more compute and your strong answer must confirm that trade-off explicitly But you have to explain the underlying hardware mechanics of why it is the only correct architectural choice for a production system Okay, why is it the only choice?
Because if you do a simple retry the process runs sequentially You have to wait for the first generation to completely finish then fail the guardrail check and then wait for an entire second generation to complete Oh, I see that completely doubles your response latency In a real-time system doubling latency is often entirely unacceptable for the user experience The user will just assume the app is broken and close it So why does generating them all at once solve this without bringing the system to a halt because of how GPU batching works?
Generating text on a GPU is heavily memory bandwidth bound Modern hardware can process a batch of several requests almost as fast as it can process a single request.
Oh, wow.
I didn't realize that Yeah, so the stronger pattern is parallel generation.
You fire off several generations simultaneously You validate all of them against your guardrails at once.
You return the very first one that passes and you instantly discard the rest You are actively trading higher compute costs for lower latency Instead of trading latency for latency It's also worth mentioning that some production systems sidestep this trade-off entirely with constrained decoding, forcing the model's output to conform to a grammar or schema at generation time so the invalid JSON case can't happen in the first place Which leaves you with a much harder architectural question for your own career As we move into an era where inference compute is essentially infinite But human attention spans are only getting shorter.
Are you still designing systems for an era where silicon was more valuable than time?
โถShow recap ยท ๐ marks concepts worth exploring deeper
Why Pasting Everything Into One Giant Prompt Doesn't Scale
"Modern models have huge context windows, so just include everything" is the trap: a massive stuffed prompt suffers from attention degradation, the "lost in the middle" problem ๐, where the model's ability to recall information buried in the center of a huge prompt drops sharply, and it invites hallucination because the model ends up pattern-matching across a wall of text instead of retrieving facts systematically. The strong answer: you need a real pipeline that extracts, cleans, chunks, and embeds data into a vector store before it ever reaches the model, so only the exact relevant context gets injected at query time.
Query Routing: Deciding Where to Look Before You Search
With a vector database, a live pricing API, and a relational database of records all in play, "just always search the vector database first" wastes latency and compute. A query router sits in front of the model and uses embedding similarity (converting the incoming request into a vector and comparing its distance to the core themes of each data source) to decide whether a request needs a semantic search, a live API call, or a translated SQL query, before any retrieval happens at all. Embedding similarity is one solid way to build this; a lightweight classifier or hand-written rules work too, as long as the routing decision happens before retrieval. This pre-retrieval optimization step is what stops a model from confidently hallucinating a price from stale vector documents when it should have hit a live API.
DPO vs. RLHF: Alignment Without a Second Model
"DPO is just a cheaper, faster version of RLHF" undersells the actual architectural shift. RLHF requires training an entirely separate reward model to score outputs, then using a heavier reinforcement learning algorithm (PPO) to update the main model against that score: expensive and notoriously unstable to train. DPO reframes alignment as a direct classification problem ๐: given a prompt with a chosen and a rejected response, it adjusts the model's own weights to pull toward the chosen response and away from the rejected one in a single training pass, with no separate reward model in the loop at all. DPO isn't a strict upgrade in every case, though: if the reward signal is more complex than a simple pairwise preference, or needs to keep learning online, RLHF's separate reward model still earns its complexity.
LLM-as-Judge: Grading at Scale Without Human Graders
Spot-checking a sample of outputs manually doesn't scale to production volume. The strong answer is an LLM-as-judge with a deterministic rubric, not a vague "rate this 1-5" prompt: for faithfulness, the judge extracts every factual claim from the generated answer and cross-references each one against the retrieved context, scoring the ratio of supported claims; for answer relevancy, the judge reverse-engineers what prompt would have produced this answer and measures its embedding similarity to the real user prompt, catching cases where the model went confidently off-topic. Neither rubric runs unsupervised forever, though: the judge's scores need periodic calibration against human ratings, since an ungrounded LLM judge can drift or simply share the same blind spots as the model it's grading.
Parallel Generation: Trading Compute for Latency
When an output guardrail rejects a response for bad formatting, "just regenerate and try again" doubles response latency, often unacceptable in a live product. The stronger pattern is parallel generation: fire off several generations simultaneously, validate all of them against the guardrails at once, return the first one that passes, and discard the rest. You're deliberately trading higher compute cost for lower latency, instead of trading latency for latency by retrying sequentially. Some production systems sidestep the trade-off entirely with constrained decoding: forcing the output to conform to a grammar or schema at generation time so invalid JSON can't happen in the first place.
Video summary
~10 minutes ยท Visual walkthrough
Covered in this video
- Chatbot vs. agent
- Reason, act, observe loop
- Tool calling
- Still autoregressive generation
- Indirect prompt injection
- Routing, judging, constrained decoding
In practice
A concrete code example tying the concepts together
# pip install anthropic
# Needs ANTHROPIC_API_KEY in your environment.
import anthropic
import json
client = anthropic.Anthropic()
# Define tools
tools = [
{
"name": "search_database",
"description": "Search the product database for items matching a query",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"},
"limit": {"type": "integer", "description": "Max results", "default": 5}
},
"required": ["query"]
}
}
]
def search_database(query: str, limit: int = 5):
# Real implementation would query a DB
return [{"id": 1, "name": f"Product matching {query}", "price": 29.99}]
# Agentic loop
messages = [{"role": "user", "content": "Find me products about machine learning"}]
while True:
response = client.messages.create(
model="claude-sonnet-4-6", max_tokens=1024,
tools=tools, messages=messages
)
if response.stop_reason == "end_turn":
print(response.content[0].text)
break
# Execute tool calls
for block in response.content:
if block.type == "tool_use":
result = search_database(**block.input)
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": [
{"type": "tool_result", "tool_use_id": block.id,
"content": json.dumps(result)}
]})A practical guide for busy days
Find time for what you want to learn next.
Get both printable editions of The 8โ5 Workerโs Daily Protocol. Use them to find one realistic learning block around your workday.
Free. Both editions arrive by email. Unsubscribe anytime.
Flashcards
26 terms ยท Review or test yourself
1 / 26
Tap the card to reveal the answer
Interview questions
Practice answering questions you might get asked
1 / 20
What's the fundamental difference between a simple LLM call and an AI agent?
Continue with FersmithAI
One skill is useful. The connected path is the product.
FersmithAI connects 28 AI/ML skills with podcasts, video summaries, hands-on labs, landmark papers, a glossary, flashcards, and interview questions. Your assessment and available time decide what comes next.
Compare monthly and annual plans before you start your 3-day trial.