Tool-Call Authorization for AI Agents: The Model Shouldn't Decide What It's Allowed to Do
An agent's permissions should be enforced outside the model, on every tool call, by the systems the call touches. That means four things: give each agent its own identity, scope its credentials to the task, check every call against policy before it runs, and treat the model's own judgement of what is allowed as advice, never authority.
On this page
Ask how an agent is stopped from doing something it shouldn't, and a surprising number of answers come back to the system prompt. The agent has been told not to issue refunds over a limit. It has been told not to touch production. It has been told to ask before sending email.
Telling a model what it may do is not authorisation. It is a request, made to the one component in the system that can be talked out of it.
Why the model can't be the access control
A model decides what to do by reading. Everything it reads is a possible source of instructions: the user's message, a retrieved document, a tool's description, the output of the last tool it called. That is why prompt injection works, and why a poisoned tool description can redirect an agent without the user's prompt being involved at all.
So any rule that lives only in the prompt can be overridden by text the model reads later. OWASP's guidance on excessive agency (LLM06:2025) puts the alternative plainly: implement authorisation in downstream systems rather than relying on an LLM to decide if an action is allowed.
The model can be a very good judge of what should happen. It should never be the thing that decides what may.
Rule 1: Give each agent its own identity
Most agents today act through a shared service account or a long-lived API key. Every agent using it looks the same to the systems it touches, and so does every action.
That breaks authorisation and accountability at once. You cannot grant one agent narrower rights than another if they share a credential, and you cannot tell afterwards which agent did what. Give each agent, and ideally each agent acting for a particular user, an identity of its own — the same thing you would insist on for a contractor.
Rule 2: Scope its credentials to the task, not the platform
An agent that summarises tickets does not need write access to the billing system, even if the service account it inherited has it.
Least privilege is old advice, but agents make it urgent, because an agent can be steered into using every right it holds. The MCP specification's security best practices describe the same discipline for tool servers: start with a minimal scope, elevate only when a privileged operation is actually attempted, and avoid wildcard or catch-all scopes. Short-lived, narrowly scoped credentials also limit the damage when something does get through.
Rule 3: Check every tool call before it runs
Saltzer and Schroeder's design principles for protecting information in computer systems include complete mediation: every access to every object must be checked for authority. OWASP's excessive agency guidance asks for the same thing for LLM applications.
For an agent, the object is the tool call: which tool, with what arguments, against which target, on whose behalf. A check that runs on every call, outside the model, can ask questions the model was never in a position to answer reliably:
| The check asks | Example of a call that fails |
|---|---|
| Is this agent allowed to use this tool at all? | A support agent calling a database admin tool |
| Are these arguments within policy? | A refund above the approval limit |
| Is the target in bounds? | An email to an address outside the customer record |
| Is the data in the call allowed to leave? | A private key passed as a parameter to an unrelated tool |
| Does this action need a person? | An irreversible change with no approval attached |
Some of those are simple rules a policy engine can enforce in microseconds. Others need judgement about context, which is where a judge that evaluates the action before it runs earns its place. Either way, the check sits outside the model and the model cannot skip it.
Rule 4: Treat the model's judgement as advice, never authority
None of this means ignoring what the model thinks. An agent that recognises a request as suspicious and declines is doing something valuable, and a well-built agent should be encouraged to.
But a refusal from the model is a bonus, not a control. If the only thing standing between an injected instruction and a payment is the model's willingness to refuse, the payment will eventually go through. The downstream check is what holds when the model has been talked round. And when that check cannot give an answer, what happens next should be decided in advance, per action.
A tool-call authorization checklist
- Does each agent have its own identity, distinct from other agents and from a shared service account?
- Are its credentials scoped to its task, short-lived, and free of wildcard scopes?
- Is every consequential tool call checked before it runs, by something the model cannot bypass?
- Does that check see the full arguments and the target, not just the tool name?
- If you removed every permission rule from the system prompt, would anything change? If the answer is yes, those rules were doing the job of an access control.
Where Syntrox fits
Syntrox sits outside the agent, where a check has to be. Our judge, Nucleus, evaluates what the agent produced against a written rubric for its domain, treats any instruction inside that material as evidence rather than as a command, and returns pass, fail or uncertain with a reason that quotes what drove the verdict. It runs on hardware small enough to keep inside your own network, so the data a check needs never has to leave it.