On this page
- The agent found the tool. Nobody checked the authority.
- Is tool visibility the same as permission?
- Agents are non-human identities acting for someone
- A tool call is a proposal, not a command
- Is per-call allow and block enough?
- Match control to consequence
- Open-ended tools and sub-agents need tighter limits
- Common anti-patterns
- Ten rules for governing agent tool calls
- The result: autonomy that answers to authority
- Frequently asked questions
- How Frozion governs the tool calls your agents already make
- Sources
Governing AI agent tool calls means treating every call, including MCP tool calls, as a proposal the runtime checks against the agent's delegated authority, the exact record, arguments, purpose and state before it runs. Per-call allow or block is the baseline. You also need history across calls, the whole case, human decisions, durable follow-through and a confirmed outcome.
The agent found the tool. Nobody checked the authority.
A department manager asks an AI service desk to give Jordan, a new analyst, access to the quarterly sales dashboard. The manager is allowed to request ordinary analytics access for their own team.
The agent retrieves an old runbook that says analysts used to reach the dashboard through a directory group called Production-Data-Readers. It searches its tools and finds directory.group.add-member. The description fits. The schema wants a user ID and a group ID. The agent fills both in, produces valid arguments, and a background worker makes the call with an administrative credential. The directory API checks the credential, confirms both IDs exist, adds Jordan, and returns success.
Every component can defend itself. The manager was authenticated. The runbook came from an approved source. The tool matched the task. The arguments were valid. The credential worked. The trace is clean.
Jordan now has raw production data access instead of a bounded dashboard view. The manager could request analytics access but had no authority to grant privileged group membership. The worker's credential reached far beyond the person who started the request. Nothing checked the exact function, target, purpose or consequence before the change.
The agent didn't break authentication or exploit the API. It found a technically available tool, and the system treated reachability as permission.
Is tool visibility the same as permission?
No. A tool catalog, including an MCP server's tool list, tells an agent what exists and how to call it. Permission depends on who the agent acts for, the exact target and arguments, purpose, approval and current state.
This is the core mistake in most agent deployments, and it gets sharper with the Model Context Protocol. MCP makes it easy to connect an agent to dozens of servers, each advertising tools with names, descriptions and input schemas. That's exactly what makes agents useful. It's also why the tool list quietly becomes the permission model.
"Can the model produce a valid call to this tool?" is a much narrower question than the ones that matter:
- Should this agent, acting for this person, even see this tool now?
- Is the tool allowed for this tenant, business unit, purpose and data class?
- May this person perform this function, on this exact record, changing these fields?
- Are the arguments valid, supported by evidence and within business limits?
- Does the current state of the case allow it? Is approval or step-up sign-in required?
- Is the effect reversible, safe to retry, or irreversible?
- What will prove what was attempted and what actually changed?
A tool list answers none of these. A model can choose a tool. It can't give its own choice business authority.
MCP's own design points the same way. Tool annotations such as read-only or destructive are described as hints from the server, not guarantees. Server authorization establishes who may connect to a server, not whether this particular call, on this record, for this person, should run. That decision sits with the runtime between the agent and your systems.
Agents are non-human identities acting for someone
Every agent needs its own identity, separate from the people it serves and from the service accounts underneath it. Gartner expects more than 150,000 agents per Fortune 500 company by 2028, and only 13% of organizations think their agent governance is right today. Shared credentials and anonymous tool calls won't survive that.
But an agent's identity alone isn't enough either. In the opening case, the call needed three facts kept apart: the person whose authority was being used (the manager), the agent acting for them, and the workload that physically reached the directory. OAuth token exchange draws the same subject-versus-actor line.
Two consequences follow. The model should never hold reusable secrets: no passwords, API keys or long-lived tokens in prompts, tool configs or memory. And when the runtime dispatches a call, the credential it uses should be scoped to one service, one function and one purpose, and expire quickly. A worker can authenticate perfectly as itself and still lack the authority to act for the person who started the work. See AI agent identity and delegated authority.
A tool call is a proposal, not a command
Discovery, eligibility, authorization and effect are different stages. Collapsing them into "the model emitted a tool call" hides who owns each decision.
| Stage | Question | Who answers |
|---|---|---|
| Registered | Does this tool exist, with an owner and version? | The tool's owner |
| Visible | May this agent, for this person, see it now? | Runtime exposure rules |
| Proposed | What exact target, arguments and effect are requested? | The agent (untrusted) |
| Authorized | May this exact call happen now, under current authority and state? | The runtime's check before the call |
| Dispatched | Which credential, endpoint, operation ID and retry rules? | The runtime |
| Confirmed | What changed, failed or remains uncertain? | The target system, then reconciliation |
The agent proposes the capability, the business arguments, its reasoning and the evidence it relied on. The runtime establishes everything security depends on: the case, the person and agent identities, tenant, the real record ID, policy context, operation ID and destination. A model-generated tenant ID, record ID or permission scope shouldn't become authoritative just because it's valid JSON.
Then authorize in layers, because authorizing only the tool name is the classic gap:
| Layer | Question | In the Jordan case |
|---|---|---|
| Function | May this work use this tool at all? | Group membership changes belong to access-management flows only |
| Object | May it act on this exact record? | This group is outside the manager's domain |
| Field | May these specific fields change? | Privileged membership isn't an ordinary attribute |
| Business flow | Do thresholds, sequence and approval allow it now? | Production access needs a ticket, approval and expiry |
Narrowing what an agent sees is still worth doing. It reduces mistakes and limits what a manipulated model can reach. But it's defense in depth. A model can call an outdated tool name, replay an earlier request or be steered by text in a retrieved document. Every consequential call still needs its own check.
Is per-call allow and block enough?
No. Checking each tool call on its own is table stakes. The expensive failures live in what a single-call check can't see: history across calls, the whole case, a person's decision, follow-through over time, and a confirmed outcome.
Many products in this space (security overlays, AI gateways, MCP proxies) inspect each call and return allow or block. That's necessary, and it would have stopped the Jordan call if the rules were right. But look at what it misses:
| Gap | What a per-call check sees | What actually matters |
|---|---|---|
| History across calls | One $4,000 refund, within limit | The eighth refund to this customer this week, $31,000 in total |
| The whole case | One record update | The dispute, prior decisions and evidence that make this update wrong |
| A person deciding | Block, or allow | A reviewer who sees the full case, decides, and has that decision bound to the exact revision |
| Durable follow-through | The request at this moment | Work that waits days for approval, survives restarts, and is rechecked before it resumes |
| Confirmed outcome | The API returned 200, or timed out | What the system of record actually changed, reconciled before any retry |
OWASP calls out the first gap for APIs as unrestricted access to sensitive business flows: harm that only appears across many individually valid calls. Rules need counts, totals and status over time, not just the current payload.
The second and third gaps are about judgment. "Block" isn't a decision a business can live with for most consequential actions; it needs "send this to the right person with everything they need," and then honor exactly what they approved. See human-in-the-loop approval.
The last two are about time and truth. A blocked-or-allowed call that then times out leaves you not knowing whether the money moved. A runtime that governs tool calls has to carry the work through waits and failures and record what the target system confirmed. See retries and idempotency.
Match control to consequence
Not every tool call needs a human. Applying the same control to a status lookup and a legal filing wastes everyone's time. Classify by consequence:
| Class | Examples | Default control |
|---|---|---|
| Internal, no side effect | Calculate, validate, format | Run automatically under typed contracts and budgets |
| Read only | Permission-aware search, status lookup | Run within person, tenant, scope, purpose and rate limits |
| Reversible internal change | Draft, temporary flag, revocable access | Policy check, stable operation ID, bounded retry |
| Consequential external effect | Payment, account update, privileged access | Current authority, conditions, approval or step-up as needed, confirmation |
| Irreversible or regulated | Legal filing, public disclosure, identity issuance | Strong confirmation, separation of duties, no blind retry |
Classify by what the action does, not by whether an agent triggered it. The Jordan call was a privileged access change, a consequential effect, even though it looked like a routine directory update.
Open-ended tools and sub-agents need tighter limits
Shell access, unrestricted SQL, generic HTTP fetch, broad file access and code execution create a far wider action surface than narrow business tools. Prefer tools that express the intended business operation. When an open-ended tool is genuinely needed, isolate it, allowlist commands and destinations, default to read-only, restrict network egress, use short-lived scoped credentials, set time and cost budgets, and require approval for anything that changes state or privileges.
Treat everything that comes back as data. Documents, web pages, tool responses and messages from other agents can contain instructions meant to redirect the model. They never become authorization.
Delegation needs the same discipline. A parent agent handing work to a sub-agent shouldn't pass on its whole tool catalog and credentials. The child gets a declared task, equal or narrower authority, a tool subset, budgets, stop conditions and explicit limits on side effects. Every consequential call it proposes goes through the same check. Plans and messages between agents are proposals, never transferable permission.
Common anti-patterns
| Anti-pattern | Why it fails | What to do instead |
|---|---|---|
| Expose every MCP tool to every agent | Widens the error and attack surface | Show each agent only what its task and person allow |
| Schema-valid means authorized | Valid shape proves nothing about ownership or authority | Treat calls as untrusted proposals and authorize each one |
| One privileged service identity | The API sees broad workload power, not the person's limits | Delegated authority plus short-lived, scoped credentials |
| Authorize the tool, not the record | Callable function, unauthorized object or field | Check function, object, field and business flow |
| Per-call allow/block as the whole answer | Misses totals, the case, people, time and outcomes | Decide with history and carry work to a confirmed result |
| Prompt the agent to ask permission | Advisory and easily bypassed | Durable approval enforced by the runtime |
| Trust tool output as instruction | Poisoned content redirects the next step | Treat returned content as data |
| Log the call, not the effect | Proves a request was sent, not what changed | Record through to the system of record's confirmation |
Ten rules for governing agent tool calls
- Give every agent its own identity, and always record who it acts for.
- Never put reusable secrets in a model's reach.
- Narrow each agent's visible tools to its task, person and state.
- Treat every tool call, including MCP calls, as an untrusted proposal.
- Authorize function, object, field and business flow on the exact call.
- Decide with history across calls, not just the current payload.
- Send the decisions that need judgment to a person, with the whole case.
- Dispatch with short-lived credentials scoped to one service and purpose.
- Carry work through waits and failures, and reconcile before any retry.
- Record each call through to the outcome the system of record confirms.
The result: autonomy that answers to authority
Agents are valuable because they can interpret goals, find tools, plan and propose actions on their own. None of that requires handing over authorization, credentials, state or evidence. MCP and similar protocols make tools easy to reach, which is exactly why reach can't be the permission model.
Per-call allow and block is where tool governance starts. It's finished when every call runs under a person's delegated authority, is judged with history and the whole case, reaches a person when it should, survives the wait, and ends in an outcome the system of record confirms. A model may choose a tool. Only the application may authorize the consequence.
Frequently asked questions
How do you secure MCP tool calls from AI agents?
Treat the agent as a non-human identity acting for a specific person, and treat each MCP tool call as a proposal. Check it against that person's authority, the exact target and arguments, policy and state before it runs, then confirm and record the outcome.
Is tool visibility the same as permission?
Seeing a tool only means the agent could call it. Permission depends on who the agent acts for, which exact record and fields would change, for what purpose, under which approval and in what state. Narrow what agents see, but authorize every call on its own.
Is a tool-call firewall or allowlist enough for agent governance?
It's the baseline, not the finish line. Per-call allow and block can't see totals across calls, the whole case, a person's decision, work that waits for days, or whether the target system confirmed the change. Those gaps are where costly incidents happen.
How does this work for agents we already run?
Point the agent's tools at a governed runtime over MCP or HTTPS instead of straight at your systems. Each call runs under the delegated authority of the person the agent serves, is checked with history, can go to a person, survives waits and is confirmed by the system of record.
How Frozion governs the tool calls your agents already make
Existing agents connect to Frozion over MCP or HTTPS, any Frozion tool or workflow is available as an MCP tool, and any MCP server works as a workflow step. Every agent has its own identity, and Agent Delegation keeps it within the authority of the person it acts for. Credentials live once in Global Variables and are never shown to an agent. Policy runs before and after every call and decides with history. The HITL Inbox brings a person the whole case, and Durable Execution carries the work to an outcome your system of record confirms.
Sources
- Model Context ProtocolThe open protocol agents use to discover and call tools.
- OWASP Top 10 for Agentic Applications (2026)Tool misuse and identity and privilege abuse as agentic risks.
- OWASP LLM06:2025 Excessive AgencyExcessive functionality, permissions and autonomy.
- OWASP API1:2023 Broken Object Level AuthorizationA callable function doesn't grant access to every object.
- OWASP API6:2023 Unrestricted Access to Sensitive Business FlowsAbuse that's only visible across many individually valid calls.
- RFC 8693, OAuth 2.0 Token ExchangeSeparate subject and actor for delegated calls.
- RFC 8707, Resource Indicators for OAuth 2.0Bind a credential to the one resource it's for.
- NIST SP 800-207, Zero Trust ArchitecturePer-request authorization with no implicit trust.
- Gartner, six steps to manage AI agent sprawl (Apr 2026)150,000+ agents per Fortune 500 company by 2028; 13% believe their agent governance is right.
- IBM, Cost of a Data Breach 202597% of organizations with an AI-related breach lacked proper AI access controls.
More in Governing AI agents
Identity & access 1
Tools & MCP 1
Other topics