Gates and brakes
Lesson 4 of 5 in Tool Scoping and Least Privilege: Making the Dangerous Thing Impossible.
Scoping removes capability. Gates and brakes handle what is left: the actions you genuinely need, that you genuinely cannot bound in a schema. Both are weaker than removal, and it matters that you know why.
An approval gate does not make the dangerous action impossible — it moves the decision to a human. So its strength is exactly the quality of that human decision, which makes it the one control that degrades silently over time as reviewers habituate. A brake — a rate limit, a budget, a cap — does not prevent the wrong action either; it bounds how much wrong action fits in one run. Neither is a substitute for not having the permission.
| Brake | What it bounds | The failure it converts | Enforcement point |
|---|---|---|---|
Tool-call budget per run | How many actions one hijacked session can take. | An unbounded loop becomes a run that stops after N calls and escalates. | The runtime loop — a counter, not an instruction |
Per-tool rate limit | Repetition of one dangerous action: refunds per hour, emails per run, rows deleted per minute. | Mass action becomes a handful plus an alert while a human still has time to intervene. | Tool handler or API gateway, keyed by session and tenant |
Spend and token budget | Money: model spend, third-party API cost, refunded dollars per day. | Silent cost blowout becomes a hard stop — OWASP’s LLM10:2025 Unbounded Consumption. | Billing guardrails plus a runtime ledger the model cannot write to |
Row and batch caps | Breadth of a single write: rows updated, files touched, recipients addressed. | “Delete all” becomes “delete up to 50, then require approval.” | Query builder / tool handler, enforced before execution |
Concurrency and fan-out caps | How many sessions or subagents act at once with the same authority. | A systemic incident becomes a contained one; keeps the kill switch fast enough to matter. | Orchestrator / scheduler |
Session TTL and context reset | How long injected content persists and keeps steering the loop. | A single poisoned observation stops being a permanent resident of the session. | Session manager — and note this is what Meta’s Rule of Two means by within a session |
Order of preference, when you can only do one thing this quarter: remove the tool, narrow the parameters, deny the egress, cap the volume, then gate. Gates sit last on purpose — they consume the scarcest resource in the system, which is human attention, and they are the control most likely to be quietly gone in six months while still on the architecture diagram.
Walk one tool through the decision below. Do it per tool, not per agent.
Choose the control for one tool
Interactive decision tree — outcomes:
- Do not register it here
The cheapest control on the ladder. Build task-specific toolsets and let the omnibus agent go: a tool absent from the session cannot be injected into, mis-parameterised, or mistakenly approved.
- Read-only, and leave it alone
Register it, keep the credential scoped and short-lived, log the calls. A read-only tool with no outward path is the cheap part of your agent — spend your review budget elsewhere.
- Read-only, plus egress control
Read-only does not mean harmless once the data can leave: this is trifecta legs one and three meeting. Default-deny outbound destinations at the proxy, strip external hosts from rendered output, and treat a blocked attempt as a security alert rather than a bug report.
- Constrain the parameters in code
Enums over free strings, ceilings on amounts, canonicalised path prefixes, arguments related to session state, and — best of all — parameters deleted because the runtime can fill them itself. Validate in the handler, not in the description the model reads.
- Cap the volume and monitor
Reversible plus observable is the profile that brakes are for: a per-run cap, a rate limit keyed by session and tenant, an alert on the rate. You are converting a possible mass-action incident into a small, noticed, undoable one.
- Gate it — on exact parameters
Irreversible, unconstrainable, and judgeable: this is what approval gates are for. Render the real arguments, bind the approval to them, expire it, and keep the gate list short enough that reviewers still read. Then watch review time and rejection rate as metrics — a gate everyone approves in three seconds has already stopped being a control.
- Do not ship this as an agent action yet
An approval no one can evaluate is theatre, and “Always allow” is the button users actually press — Invariant Labs called that out in the GitHub MCP flow. Make verification cheap first: dry-run modes that show the diff, smaller and more legible actions, staged rollouts, or a human executing while the agent proposes.
Interactive checkpoint quiz (2 questions) — open this page in a browser to take it.