stateless permissions are not enough for agents
An agent can have permission for every individual tool call and still make an unsafe sequence of them. The useful next boundary is stateful authorization.
Here is a perfectly ordinary agent failure in a fintech system.
The agent reads a customer profile. It fetches a portfolio. It gets a market price. It places a trade. Every call uses a legitimate identity. Every tool is on the allowlist. Every request passes the usual authorization check.
And the trade is still wrong.
Maybe the quote was from two minutes ago. Maybe the customer profile was read in a different session. Maybe the agent retried and placed the same order twice. Maybe it made a hundred small trades, all below the per-trade approval threshold, until the aggregate exposure became a very exciting incident channel.
The individual calls were allowed. The trajectory was not.
That distinction is where agent security is getting interesting. We have spent decades asking whether a principal may call an API. Agents force a second question: is this call valid after everything this agent has already done?
permissions answer a smaller question
Traditional IAM is not broken. It is just answering the question it was built for.
Can this service account call execute_trade? Can this user read a customer record? Can this workload invoke this model? Those are necessary checks, and I would be thrilled if more agent systems did them properly before inventing the next layer.
But an agent does not execute one predetermined request. It chooses a sequence of tools and arguments while it works. It can retry, branch, search, call another model, and come back to the same tool with a different justification. Its output is a path through a system, not a single RPC.
Static permission sees each step as a photograph. Production incidents happen in the movie.
This is also why a prompt is the wrong place for a hard invariant. “Always check the latest price before trading” is a good instruction. It is not an enforcement point. Under pressure from an ambiguous task, a surprising tool result, or a malicious document, the agent may simply do something else. The model is allowed to be clever. The control plane should not have to be.
what stateful authorization actually means
AWS recently introduced temporal policies for AgentCore Gateway. The name is a bit more dramatic than it needs to be, but the primitive is useful: retain the relevant history for a session, and evaluate the next action against that history.
That creates a few policy types which are much closer to how teams already think about risk:
- Sequence: do not execute a trade until the agent has loaded the right customer profile and portfolio in the right order.
- Freshness: do not act on a price unless a matching quote was retrieved recently enough.
- Integrity: only use an identifier or amount that came from an approved upstream tool response, not a random string the model assembled after reading a web page.
- Cumulative exposure: cap the total value, data volume, or cost across the session, not only per call.
- Consumed approvals: treat approval as a token for one action, not a magic permission slip that works forever.
- Trust decay: require a new check when the underlying fact is old, the session has crossed a boundary, or the requested action has become more consequential.
None of this is uniquely AI-shaped. We have done versions of it in payment flows, workflow engines, idempotency systems, and databases for years. The difference is that agents make it a first-class runtime concern because the software choosing the sequence is probabilistic.
The clever bit is not “AI policy.” It is moving some distributed-systems discipline to the place where the agent crosses into real tools.
approvals should be spent, not remembered
The approval example is worth lingering on because it catches a common mistake.
Imagine an operator approves a $30,000 trade. A stateless implementation may record approved=true in session context and consider its job done. The agent can now make a second $30,000 trade, a third one, or perhaps helpfully retry the first after a timeout. The approval was technically present. The intention was obviously not.
A stateful policy can say something more honest: this approval authorizes exactly one matching action; when that action succeeds, consume the approval. A new material action needs a new approval.
This is not hostile to autonomy. It is how you give an agent room to work without quietly granting it an unlimited version of a limited decision.
The same thinking applies to sensitive data. “The agent may export up to 100 records” is only useful if the platform remembers the first 99. Otherwise the agent has a 100-record limit on every request, which is a very optimistic interpretation of the word limit.
a gateway is where the rules can be real
Policies inside agent code are helpful, but they are not a boundary. The same component that decides to call a tool should not be the only component deciding whether the call is acceptable.
Put the enforcement point between agents and tools. A gateway can authenticate the caller, mint narrow credentials, evaluate policy, forward the request, and record the outcome. It also gives security and platform teams one place to apply limits consistently when several agents, MCP servers, and model providers are involved.
That does not mean every company needs a giant agent-control-plane programme before the first useful workflow. It means that once an agent can touch production data or perform a meaningful action, bypassing the enforcement point should be difficult by design.
The boring controls still matter:
- give each agent and environment a distinct identity;
- scope credentials to a task and expire them quickly;
- put a rate limit and concurrency limit around the gateway;
- attach an owner, risk tier, and audit trail to every tool;
- record policy inputs, the decision, and the resulting action in the same trace;
- make deny decisions explainable enough for an engineer to fix the workflow rather than disable the policy.
Rate limits are not a substitute for authorization. They are a blast-radius control. A runaway retry loop, a prompt-injected browser agent, and an unexpectedly expensive reasoning path all look different, but each becomes less catastrophic when a session cannot consume an unbounded number of calls, tokens, connections, or dollars.
state is not magic safety
There is a very predictable marketing slide hiding here: add temporal policy, receive safe agents. No.
Stateful authorization only protects the invariants that someone expressed correctly and connected to trustworthy events. If the session boundary is wrong, the agent can get a fresh budget by starting a new session. If an untrusted tool can write “approved” events, approval consumption is theatre. If the policy cannot distinguish a stale quote for Apple from a fresh quote for another instrument, it is just a complicated way to permit mistakes.
State creates its own engineering work: correlation IDs, durable event order, idempotency, clock choices, retention rules, recovery after partial failure, and a clear definition of which events count. Welcome back to distributed systems. We saved you a pager.
That is still progress. A policy outside the prompt and outside the agent loop gives teams a place to state a non-negotiable rule and prove whether it was enforced. It turns “the agent should have known better” into a testable property.
treat policies like production code
If I were introducing this next week, I would keep the first version aggressively small.
Pick one workflow with a clear session boundary. Define two or three invariants that would have prevented a real failure mode. Route only the risky tools through a gateway. Start in observe mode if the policy engine allows it, then compare intended decisions with actual traffic before enforcing.
Test the policies with traces, not just happy-path unit tests. Feed them out-of-order calls, duplicated requests, expired facts, forged correlation IDs, missing approval events, and a session that exhausts its budget one tiny action at a time. The test suite should look less like a permissions matrix and more like an incident retrospective.
And log enough context to answer the only questions that matter at 2am: what did the agent try to do, what had it already done, which rule decided the outcome, and how can we reproduce that decision?
the next boundary is boring on purpose
Better models will make agents more capable. Better prompts will make them look more careful. Neither gives a platform team a deterministic answer when an agent has taken the first nine reasonable steps and is about to take the tenth disastrous one.
The useful work is less glamorous: define trajectories, persist the right facts, restrict credentials, budget the session, consume approvals, and deny invalid transitions at the gateway.
In other words, make authorization stateful.
That is not a grand new theory of agent safety. It is a permission system that has finally noticed agents have memory, time, and consequences.
references
- AWS: Securing AI agents with temporal policies in Amazon Bedrock AgentCore
- AWS: Control agent behaviors and cost beyond a single action
- AWS: Configure rate limits for AI traffic on AgentCore gateway
- AWS: Govern AI agent tool access with Amazon Bedrock AgentCore Gateway
To test my projects, I use Railway. If you want $20 USD to get started, use this link.