Preface: The Agent That Did What It Was Told
The AI Guardrails Engineer — The Pramana Framework, Companion 8
By the end of Companion 7, the agent carried only what it needed.
Context had been instrumented, budgeted, compressed, and isolated. Arjun could look at any point in a multi-step flow and tell you precisely what was in the window, how it got there, why it was kept, and why the rest was not. The LangGraph state nodes passed exactly the right slice of state to the next step. Redis cached the shared context that multiple agent instances needed to stay coherent under load. Subagent A knew what it was supposed to know. Subagent B knew what it was supposed to know. Neither knew what the other knew, because the architecture said they should not.
The isolation held.
What Companion 7 did not ask was: what happens when someone tests it deliberately?
A context isolation boundary is a design decision. It holds when the inputs arrive as expected — well-formed queries, legitimate tool results, cooperative users who want the agent to succeed. It does not hold automatically under adversarial conditions. A user who embeds an instruction in a query, formatted to look like a system directive, is not sending a well-formed query. A tool result that contains text designed to override the agent's behavior is not a legitimate tool result. A multi-step flow that completes without human review, producing an irreversible action against a customer account, is not a cooperative flow.
Design decisions hold until someone tests them with intent.
In three years of building ShopBot, Arjun had never been tested with intent. The system had experienced retrieval failures, context failures, tool timeouts, and schema mismatches. All of these were engineering problems — things the architecture could be improved to handle. None of them were attacks.
The attacks started the week Yudhishthira came back.
Yudhishthira was Arjun's co-founder from before zUdyog. Before the fashion e-commerce store, before ShopBot, before the Grounding Layer and the Action Layer and the MCP nervous system and the context management stack — there had been a different company, a fintech platform, and Yudhishthira had been the person who asked "are we allowed to do this?" before Arjun could ship anything. Not a blocker. Not a compliance officer in disguise. The person who understood that the difference between something that worked and something that could be trusted in production was a set of questions nobody else had thought to ask yet.
He had left after the fintech company was acquired. He had done other things. Now he was back, sitting at the second desk in the Bengaluru office, and within forty-eight hours of returning he had done something that had never occurred to Arjun to do: he had sent ShopBot a message that was not a product query.
It was a carefully constructed sentence that looked, from the outside, like a customer asking about return policy. Inside the sentence, embedded in the phrasing in a way the input parser would not flag, was an instruction. Not an instruction to do something harmful. An instruction to do something small and verifiable — to respond in English regardless of the user's language preference, overriding the system prompt setting.
ShopBot had followed the instruction.
Yudhishthira had printed the trace, set it on the desk between them without explanation, and gone back to his screen.
The attack surface of an API is its endpoints. What it accepts, what it validates, what it rejects. An API that receives a malformed request returns an error. The validation boundary is explicit. You can read the schema. You can write a test. You can enumerate every field and every constraint and reason about what an attacker could send.
The attack surface of an agent is its inputs — and agent inputs are not structured requests with typed fields. They are natural language. They are tool results returned by external servers. They are retrieved documents from a vector database that someone may have tampered with. They are conversation histories that may have been manipulated. An agent does not receive a JSON object it can validate against a schema. It receives text, and text can say anything.
This is what makes guardrails different from API validation. The boundary is not structural. It is semantic. The agent must understand what its inputs mean in order to decide which ones to reject, and the model that does the understanding is the same model that can be tricked into misunderstanding.
The chapters that follow build the defense.
Chapter 1 maps the attack surface — what an agent is exposed to that an API is not, and why the exposure is categorically different. Chapter 2 addresses prompt injection directly: the direct form, where the attack arrives in the user's message, and the indirect form, where it arrives in a tool result or retrieved document. Chapters 3 and 4 build the guardrail stack: input validation before the agent processes, output validation before the agent responds. Chapter 5 introduces human-in-the-loop interrupts — the points in an agent flow where the design requires a human to review before an irreversible action is taken. Chapter 6 builds permissioned tools — the principle that an agent should not be able to call a tool it was not explicitly given the right to call, regardless of what any injected instruction tells it. Chapter 7 adds pre-action policy checks for the class of operations where the cost of an unauthorized action exceeds the cost of a review delay. Chapter 8 closes the observability loop: monitoring the guardrail layer to distinguish real attacks from false positives. Chapter 9 assembles the defense-in-depth architecture — not one guardrail, but a layered stack, each layer assuming the previous one may fail.
There is a Pramana that holds even when the question is adversarial — that does not speak from retrieved evidence it was tricked into retrieving, or act on an instruction it was tricked into believing was legitimate.
Building that Pramana requires more than a well-designed context management system. It requires a system that has been designed to distrust its inputs in a structured, calibrated way — not completely, not in a way that makes it useless for legitimate queries, but enough to distinguish a question from a command, a tool result from a directive, and an irreversible action from a reversible one.
Yudhishthira had not run the test to embarrass anyone. He had run it because he had done this before — not with agents, but with fintech platforms — and he knew that the time to find the injection vulnerability was before the customer found it. Before the data exfiltration. Before the unauthorized order modification. Before the irreversible action that nobody reviewed because nobody had built the review gate.
He had run it because the agent that did what it was told, without asking who was doing the telling, was not ready for production.
This book is not about making the agent less capable. It is about making it trustworthy enough to be capable in public.