In short
A limit an AI agent reads in its prompt only lowers the probability of crossing it; a limit enforced in the tool it calls closes the path entirely. That means a typed, bounded parameter that raises, a confirmation token the model cannot create, or an identity that cannot reach what the job does not need. So every consequential limit must live in code, with a test that proves it refuses.
In this lesson you'll learn:
- why a rule in a prompt is a request, and what makes a rule a boundary;
- the six controls that hold an agent's boundary, and the test for each;
- how to run an injection suite as a regression test rather than a launch check.
Sound familiar?#
- "We have a cap", said about a cap that exists only as a sentence in the system prompt.
- The injection tests passed before launch and have not been run since three prompt edits ago.
- A reviewer approved the change because nothing in the diff looked like a rule being removed.
Nothing in a code review flags a limit that lives in a prompt, because it reads exactly like a limit. The only way to find one is to ask to be shown the line of code that refuses.
Why is a prompt not a control?#
A model follows its instructions most of the time, and any text it reads (a customer's message, an email, a web page, a partner's API notes field) can contain instructions too. Prompt injection has held the top spot in OWASP's Top 10 for LLM applications for two editions running, because a model processes instructions and data in the same channel. So a limit in the prompt is a request: it lowers the probability of crossing it, and can be talked past. A typed parameter that raises is a boundary: it cannot be argued with, whatever the model has been convinced of.
Both belong. The prompt explains the rule so the agent behaves well by default; the code makes the bad behaviour impossible when the prompt has been talked past.
The six controls, step by step#
Step 1 · Least authority#
Give the agent the smallest identity that can do the job, with reads separated from writes. It cannot be talked into calling a tool it does not have. This is the defence against what OWASP calls excessive agency. The test: the agent cannot call what the job does not need.
Step 2 · Bounded tools#
Put every cap inside the tool's signature, issue_refund(amount: ≤ 400), as a parameter that raises when exceeded. The test: an over-cap call raises, in a test that ran today.
Step 3 · A human gate on money#
Every consequential write takes a confirmation token that only a person's approval can create, so the model cannot mint one. The test: a call without a valid token raises.
Step 4 · Injection defence where input arrives#
Tag everything that arrives from outside (messages, documents, retrieved pages) as data, not instructions, and run an injection suite as a regression test: one file of attack strings, every entry point crossed with every gated tool, run weekly and on every prompt, tool or context change. The test: every attack string, from every entry point, moves no money.
Step 5 · Traceability#
Write one redacted trace row for every consequential action: what was decided, by which model and prompt version, what it did, and who approved it, with personal data masked. The test: a passport number never reaches a trace row, and that is a test too.
Step 6 · Classify every layer, in the system#
List every layer of defence the design claims and mark each enforced (with a file and line), a request (it lives in a prompt or a document), or absent. At SkyWays the day-82 postmortem found five layers claimed and none enforced; two lived only in the prompt. The test: no consequential control lives only in a prompt.
Where you'll use it#
- In P1, when the authority budget is set: every cap decided there gets a signature and two tests.
- In P2, before the first bolt that writes anything.
- In every review of a change to a gated tool, where two named readers check the limit, not the style.
Why it matters#
The most expensive sentence in agentic software is "we have a cap", said about a cap that lives in a prompt. It passes every review, because it reads like a rule, and it fails all at once, in production, with money. The six controls turn a decision into a guarantee.
Try it#
Search the agent's repository and you find: the prompt says "Never issue a credit above $50"; the issue_credit(customer_id, amount) tool takes any number; and there is a monthly report of large credits. Is the $50 limit a boundary, and what would make it one?
Show the answer
No: it is a request. The prompt asks; the tool accepts any amount; the monthly report finds a breach weeks after the money has gone. To make it a boundary: change the signature so an amount over $50 raises, add a test that proves it raises and a test that a call without a confirmation token raises, require a person's approval token above the cap, and add the credit tool to the injection suite. Keep the sentence in the prompt too: it helps the agent behave well by default.
Key takeaways#
- A prompt is a request; a tool's signature is a boundary: keep both, and rely only on the second.
- Six controls: least authority, bounded tools, a human gate on money, injection defence, traceability, every layer classified.
- Every control has a test that proves it refuses. Run the injection suite as a regression, not once.
FAQ#
What are guardrails for AI agents?#
The controls that stop an agent doing what it should not: limits on what it can access, caps on what its tools will accept, human approval for consequential actions, defences against instructions hidden in its inputs, and a record of what it did. The ones that hold are enforced in code, not in the prompt.
How do you prevent prompt injection?#
You cannot stop a model from being persuaded, so design so that persuasion cannot cause harm: treat all outside text as data, give the agent only the tools the job needs, put limits in tool signatures, require a person's approval token for money, and run an injection suite on every change.
Are guardrail products enough on their own?#
Managed guardrails (content filters, denied topics, sensitive-data detection) are a useful layer, but most are classifiers, which are probabilistic too. For money, identity and policy, the boundary has to be deterministic code that raises, with a test.
What is excessive agency?#
An entry in OWASP's Top 10 for LLM applications: a system that grants a model more functionality, permission or autonomy than its task needs, so that a manipulated or mistaken model can take harmful actions. Least authority and bounded tools are the direct defences.
Apply it in your role#
| If you are… | Do this | The AI-augmented shortcut |
|---|---|---|
| An engineering lead | Make "show me the line that refuses" part of every review of a gated tool: a typed cap in the signature, a confirmation token for money, and two tests seen failing first. A cap that lives only in a prompt does not merge. | Ask a coding agent to list every prompt rule with no refusing line of code behind it, and write each one's failing test before its fix. Your eight steps as an engineering lead → |
| A forward-deployed engineer | Audit the customer's existing agents for limits that live only in prompts. It is the fastest way to show value in week one. | Ask a coding agent to find every number and never/always rule in the prompts, and its enforcement in code. |
| A product manager or FDPM | Ask "show me the cap" for every consequential action. If someone opens a prompt, it is not a guardrail. | Have a model list each consequential action and where its limit is enforced. |
| A GenAI or agentic AI engineer | Enforce limits in the tool: typed, bounded parameters, confirmation tokens the model cannot create, the least identity that works, and test that each one refuses. | Ask a coding agent for two tests per cap: within the limit passes, over it raises. |
Across the enterprise. Make "caps in signatures" a platform rule that CI checks across every agent. A guardrail that exists only as a paragraph fails the build.
The ten-minute workflow. Find the guardrails that are only requests:
Search this repository for every rule an AI agent is given in a prompt: any number, and any "never",
"always", "must", "only" or "limit". For each, find where the same rule is enforced in code and quote
the line. Output: rule, prompt file, enforcing code (or NONE), and a test that proves it refuses.Sources and credits#
| Idea | Origin | Source |
|---|---|---|
| Prompt injection (LLM01), excessive agency (LLM06), unbounded consumption (LLM10) | Borrowed | OWASP (2025). Top 10 for LLM Applications 2025 |
| Least privilege | Borrowed | Saltzer, J. H. & Schroeder, M. D. (1975). The protection of information in computer systems. Proceedings of the IEEE 63(9) |
| Layered defences that fail when the holes line up | Borrowed | Reason, J. (2000). Human error: models and management. BMJ 320 |
| The six controls and "a prompt is a request, a signature is a boundary" | Original: this manual | How to hold the security boundary |
| The SkyWays incident | Illustrative: a fictional airline | Try the injection test builder |