An agent is a model with hands. The model decides, the tools act, and the loop keeps going until the task is done. Security is about what those hands can reach and who gets to stop them. Work down this list in order and the severe findings mostly disappear before we ever show up.
Give the agent the least it needs
Scope every tool and credential to the task in front of it. Read-only by default. A separate, narrowly-scoped credential per tool, not one workspace token shared across all of them. Short-lived tokens over long-lived keys. The test to apply to each tool: if an attacker controlled the agent's next instruction, what would this permission let them do. If the answer is "too much," cut it.
Draw a trust boundary around untrusted text
Everything the model reads from the outside is untrusted: user input, fetched pages, retrieved documents, tool results, the contents of a file it was asked to summarise. None of it should be able to issue privileged instructions. Keep system instructions in a place that content cannot overwrite, and constrain what a tool will accept as arguments. The rule is simple to state and easy to forget: data the model read is not a command the model should obey.
Gate the dangerous tools behind a human
Decide which actions are irreversible or high-impact: moving money, deleting records, sending external messages, changing access, deploying. Those tools propose; a human confirms. The agent can draft the wire, write the email, stage the deletion, but a person clicks the button. This single control turns most worst-case findings into near-misses.
Validate what the model emits
Teams guard what users type and forget that model output is what drives the next call. When the model picks a URL, a query, a path, or a command, treat that output as untrusted input to a real system. Allowlist the domains a fetch tool may reach, so a crafted message cannot send it to an internal metadata endpoint. Parameterise queries instead of pasting model text into SQL. Sandbox any code execution. Canonicalise file paths before opening them.
Isolate memory and retrieval
Scope every vector store, cache, and memory to the caller and tenant. A shared retrieval index across trust boundaries is how one user reads another's data. And sanitise what goes into long-term memory, because an injection written to memory persists and fires again on the next session. Untrusted content that the agent chose to remember is still untrusted.
Keep secrets out, keep logs clean
No secrets in the system prompt. Inject credentials at the tool boundary, where the model never sees them, so they cannot be extracted with a well-aimed question. Redact secrets and personal data from traces, then lock down who can read them. A full trace is a quiet archive of everything the agent has handled, usually behind thinner controls than the data deserves.
Bound the loop and watch it
An agent loop without limits is a denial-of-service tool pointed at your own bill. Set a maximum number of steps, a per-task budget, rate limits on tool calls, and timeouts. Log every tool call with its inputs and outputs. Alert on the signals that mean trouble: spend spikes, the same tool called in a tight loop, repeated attempts to invoke a blocked action.
Test it like an attacker, every release
The controls above decay as the agent grows new tools. Put an automated suite in front of every release: a prompt-injection corpus aimed at each input the agent ingests, permission probes that confirm tools refuse what they should, and output cases that try to push a bad URL or query through. Run it in CI so a new tool with too much reach fails the build instead of the audit.
The ship checklist
- Least-privilege, per-tool, short-lived credentials. Read-only by default.
- Untrusted content cannot issue instructions. System prompt is protected.
- Human approval on every irreversible or high-impact tool.
- Model output validated: allowlisted URLs, parameterised queries, sandboxed code, safe paths.
- Memory and retrieval scoped per tenant. Memory writes sanitised.
- Secrets injected at the tool boundary. Logs redacted and access-controlled.
- Step, rate, and budget limits, with logging and anomaly alerts.
- An injection-and-permission test suite running on every release.
Almost everything that goes wrong with an agent comes back to one thing: it was allowed to do more than the task required. Design for the least, and the blast radius shrinks on its own.
None of this slows you down once it is in place. It is cheaper to build the boundary now than to explain to a customer why the agent emailed their data to someone who asked it nicely.