Guardrails and Safe Defaults
Layered defenses for agent actions: input screening, permission gating, sandboxing, and designing irreversible switches to fail closed.
Defense in depth, not one magic filter
A single guardrail will be bypassed. Reliable systems layer independent checks so that no one failure is fatal:
| Layer | Catches | Implementation |
|---|---|---|
| Input screening | Obvious injection attempts | Cheap classifier or pattern list |
| Permission gating | Actions beyond scope | Allowlist per agent, enforced in code |
| Sandboxing | Damage from allowed actions | Restricted FS, network egress, timeouts |
| Human confirmation | Irreversible consequences | Explicit prompt before dangerous ops |
| Audit logging | Post-hoc understanding | Append-only record of decisions and actions |
The critical principle: permissions are enforced in your code, not requested from the model. An agent cannot be trusted to decline — asking nicely is not access control.
Prompt injection is not solvable by prompting
Any text the agent reads can contain instructions: retrieved documents, tool results, user-uploaded files, web pages. There is no prompt that reliably makes a model ignore later instructions.
Practical mitigations, roughly in order of value:
- Separate untrusted content clearly. Tag retrieved/tool content as data, distinct from instructions.
- Constrain capability, not comprehension. Even a fully injected agent can only do what its tools permit. A read-only agent cannot delete.
- Require confirmation for state changes triggered from untrusted content.
- Keep the human in the approval path for anything irreversible.
Note that layer 2 is the one that actually holds. Everything else raises the bar; capability restriction sets a ceiling.
Irreversible actions must default to safe
This is where real damage happens. Delete, publish, send, pay, deploy — once done, not undoable.
Concrete rules:
- Dry-run by default. Require an explicit flag to actually act.
- Show the diff/preview first. Let the human see what will happen.
- Scope the blast radius. Operate on one record until proven on many.
- Never let an irreversible action be implied by a vaguely-worded request.
A particularly sharp trap in UI code: a boolean flag that, when undefined, evaluates to “proceed”. If mode === 'push' gates publishing, a mis-set flag silently goes live. Test for the affirmative value; never rely on negation being absent.
Sandboxing essentials
Even trusted agents should run constrained:
- Filesystem: scoped to a working directory; no writes outside it
- Network: allowlist domains; block metadata endpoints (
169.254.169.254) - Execution: timeouts, memory caps, no shell unless unavoidable
- Credentials: scoped, short-lived, never pasted into context
Treat every tool result as untrusted input to the next step.
Auditing for learning, not blame
Log enough to reconstruct a decision: inputs, the chosen action, why, and the outcome. Append-only. The point is answering “what happened last Tuesday”, and spotting patterns — a tool that fails 40% of the time, a confirmation step everyone blindly clicks through.
That last finding is the actionable one: a guardrail humans always approve is decoration, and should be redesigned.