Temporal policies are a new class of stateful authorization rule in Amazon Bedrock AgentCore that decide whether an agent is allowed to take an action based on what the agent has already done, not just on the request in front of it. In Part 9 of this series we covered AgentOps: observability, lifecycle, and governance for production agents. Here we go one level deeper into the part of governance that actually enforces boundaries: how AgentCore stops an agent from doing the wrong thing even when every individual tool call looks perfectly legal, and how gateway rate limiting keeps a runaway agent from eating your model budget or your downstream APIs.

AI agents are becoming capable of completing increasingly complex tasks on their own. They can search enterprise data, call external APIs, interact with MCP tools, update applications, initiate transactions, and collaborate with other agents. That autonomy is exactly what makes them valuable, and it is exactly what makes them dangerous if the governance model has not caught up. The architectural question is no longer just “is this identity allowed to call this tool?” It is “given everything this agent has already done in this session, should it be allowed to do this next thing?” Temporal policies are AWS’s answer to that second, harder question, and they sit at the AgentCore Gateway, outside the agent’s reasoning loop, where the agent cannot talk its way past them.
Temporal Policies: What You’ll Learn
This guide explains temporal policies end to end: what they are, the six kinds of guardrail they enforce, why stateless authorization breaks for autonomous agents, and how they combine with AgentCore Gateway rate limiting to form a layered control plane. Temporal policies are the concept that turns agent security from a prompt-level hope into an infrastructure-enforced guarantee.
Why Traditional Authorization Fails AI Agents
Traditional authorization systems are almost all stateless. Each request arrives at a policy engine, the engine checks who the caller is and what resource they want, and it returns allow or deny. The next request gets the same treatment, with no memory of the previous one. This works beautifully for predictable applications where developers write the workflow and the authorization layer just guards each step.
For example, a conventional system answers narrow questions: can this identity call the lookup_customer tool? Can this identity call the transfer_funds tool? Can this identity invoke a particular model? Each question is answered on its own merits, and each answer is correct in isolation.
AI agents break this model because the agent, not the developer, decides the workflow at runtime. The agent decides which tool to call, what arguments to pass, in what order to call the tools, whether to retry a failed action, and when to move on to the next step. Every one of those individual tool calls might be perfectly authorized, while the overall sequence is unsafe.
Consider a banking agent. It retrieves Customer A’s account information. During reasoning, it hallucinates and produces Customer B’s account number. It then passes that incorrect number to a money-transfer tool. The transfer tool accepts the request because the identity is authorized to transfer funds. Both the lookup and the transfer actions are individually permitted. The catastrophe only becomes visible when you look at the relationship between them: a value appeared in the transfer call that never came out of the lookup.
This is the gap temporal policies are designed to close. The policy engine needs to see the agent’s trajectory, the sequence of actions and their inputs and outputs, and evaluate the current request against that history. Without that stateful view, you are guarding every door on the building but ignoring the corridor that connects them.
What Are Temporal Policies in AgentCore?
Temporal policies are stateful authorization rules in Amazon Bedrock AgentCore. Instead of evaluating only the current request, a temporal policy considers the agent’s previous actions within the session: the agent’s trajectory. The authorization decision becomes a different question entirely: based on what this agent has already done, should it be allowed to perform this action now?
These policies are evaluated at the AgentCore Gateway perimeter, which is the crucial architectural detail. The gateway sits outside the agent’s application code and outside the agent’s reasoning loop. When a request reaches the gateway, the policy engine can retrieve the relevant prior actions, inputs, and outputs from the session, evaluate the current request against that history, return a deterministic ALLOW or DENY decision, and log the decision with its full context for auditing.
Because enforcement happens outside the agent, the agent cannot bypass the policy through prompting, reasoning, hallucination, or an application-level bug. You cannot prompt-inject your way past a gateway that will not let the request through to the tool in the first place. This is the difference between telling an agent “please do not exceed the budget” in a system prompt and having an infrastructure layer that physically prevents the eleventh transaction from reaching the payment API.
The simplest way to picture it is two layers. The agent reasons and decides what it wants to do. Before that intent becomes an actual call to a model, a tool, or an MCP server, the gateway intercepts and asks the policy engine: is this next step consistent with the approved workflow given the history so far? If yes, the call proceeds. If no, the call is denied and the denial is recorded. The agent never even sees the tool that was blocked from its perspective, the call simply failed, and it can recover, escalate, or stop.
A minimal trajectory check looks like this in pseudocode: the gateway holds a structured view of every action, its arguments, and its result, and the policy is a pure function over that history:
# Illustrative: how the gateway evaluates a temporal policy
# against the session trajectory. Conceptual, not the real API.
def evaluate(policy, request, trajectory):
"""Return ('ALLOW', None) or ('DENY', reason)."""
for rule in policy.requires_trajectory.all_of:
prior = trajectory.last_match(
tool=rule.tool,
match_field=rule.get("match_field"),
max_age_seconds=rule.get("max_age_seconds"),
)
if prior is None:
return ("DENY", f"missing required prior action: {rule.tool}")
if rule.get("human_approval") and not prior.output.get("approved"):
return ("DENY", "no human approval recorded for this target")
return ("ALLOW", None)
# On every tool call the gateway runs:
decision, reason = evaluate(restart_policy, incoming_request, session_trajectory)
log_audit_decision(request=incoming_request, decision=decision, reason=reason)
if decision == "DENY":
return ToolBlockedError(reason) # agent sees a normal tool failure
proceed_to_target(incoming_request) # only reached on ALLOWThe important property is that evaluate is deterministic and side-effect-free. Given the same trajectory and the same request, it always returns the same decision, which is what makes the resulting logs auditable and the behavior predictable across thousands of sessions. Temporal policies inherit this determinism: they are rules, not model calls, so the policy engine itself never hallucinates a decision.
The Six Guardrails Temporal Policies Enforce
Once you accept that authorization for agents needs to be stateful, the obvious next question is: what kinds of rule can a stateful policy actually express? The answer in AgentCore covers six distinct guardrails, each of which maps to a real failure mode that stateless authorization cannot catch. We will walk through each one.
1. Tool-Call Sequencing
Many workflows have a correct order, and an agent that improvises the order is dangerous even when every step is individually permitted. Temporal policies can require an agent to follow an approved sequence of steps before a terminal action is allowed. For a money-movement workflow, the approved sequence might be: retrieve the customer profile, verify the account, review the transaction, request approval, then execute the transfer. If the agent attempts to execute the transfer before completing verification, the gateway denies the request. This matters most in regulated workflows where agents must follow a standard operating procedure and where skipping a step is a compliance violation, not just an inefficiency.
2. Data Integrity Between Tools
An agent might retrieve an account number from one tool but pass a different value to the next tool, because of a hallucination, a summarization error, or a formatting change. Temporal policies can require an input sent to the current tool to match an output received from a previous tool in the same trajectory. This is what would have caught the banking example earlier: the transfer tool’s input did not match anything the lookup tool actually produced, so the policy denies it. In practice this single guardrail does more for agent safety than almost anything else, because the most common agent failures are not malicious, they are the agent confidently inventing or mutating a value between steps.
3. Human Approval
Some actions are irreversible or consequential enough that they should never run without an explicit human sign-off recorded in the session. Temporal policies can block a sensitive action until the trajectory contains a human-approval event. Examples include transferring a large amount of money, deleting production resources, issuing a refund above a threshold, changing an access policy, or deploying software to production. This gives you deterministic human-in-the-loop control rather than depending on the agent to decide when approval is necessary, which it will reliably get wrong at the worst possible moment.
4. Cumulative Limits
A single transaction may sit comfortably below an approval threshold, but an agent could perform several smaller transactions that collectively exceed the approved amount. This is the classic salami attack, and it is especially relevant for agents because an agent optimizing for a goal will happily chunk a large action into many small ones if that seems easier. Temporal policies can evaluate cumulative activity across the whole session: each trade is below $10,000, the session’s cumulative trading limit is $50,000, so the sixth $10,000 trade is denied. The policy looks at overall exposure, not just the current request, which is the only way to catch death-by-a-thousand-cuts scenarios.
# Illustrative cumulative-limit evaluation across the trajectory.
def cumulative_within_limit(trajectory, limit):
"""Sum the amount field of every prior trade in the session."""
total = sum(
step.output.get("amount", 0)
for step in trajectory
if step.tool == "execute_trade"
)
return total <= limit
# Policy: any single trade <= $10k AND session total <= $50k.
session_total = sum_trade_amounts(trajectory)
if request.tool == "execute_trade":
if request.input["amount"] > 10_000:
return DENY("single trade exceeds per-request cap")
if session_total + request.input["amount"] > 50_000:
return DENY(
f"cumulative cap exceeded: {session_total} + "
f"{request.input['amount']} > 50000"
)
return ALLOWThe key insight is that the per-request cap and the cumulative cap are independent checks, and you need both. A per-request cap alone is trivially defeated by splitting; a cumulative cap alone does not stop one oversized request. Temporal policies let you express both as conditions on the same trajectory, evaluated atomically before the action reaches the target.
5. Data Freshness
An agent’s decision often depends on information that changes frequently: inventory levels, pricing, account balances, security status, market data. A temporal policy can require that the relevant lookup happened within an approved time window before the dependent action is allowed. If the information is too old, the agent must retrieve updated data before continuing. Without this, an agent can act on a stale snapshot from minutes ago and make a decision that was already wrong by the time it was made: a particular problem for anything involving money, stock, or security posture.
6. Mutually Exclusive Actions
Some actions should never coexist within the same workflow. An insurance agent, for instance, should not approve and reject the same claim during one session. A temporal policy can deny an action when the trajectory already contains a conflicting decision. This prevents the agent from talking itself into a contradiction, which LLM agents are distressingly good at when they get into a reasoning loop.
Together these six guardrails cover the large majority of real-world agent safety requirements, and none of them can be expressed in a stateless model. They all require the policy engine to remember what happened earlier in the session and to decide based on that memory.
Temporal Policies in Practice: A Restart-Approval Worked Example
To make this concrete, consider an AI agent that helps operations teams restart production applications. This is a realistic use of a stateful agent in a high-stakes environment, and it is exactly the kind of workflow where an unrestricted agent is a liability. The agent has access to four tools: get_application_status, check_active_users, request_approval, and restart_application.
Calling restart_application may be perfectly authorized for this agent’s identity. But unrestricted access to it would still be reckless, because whether a restart is safe depends entirely on what the agent checked beforehand. A temporal policy can encode that intent as rules: the application status must have been checked recently, active-user information must have been retrieved, no critical activity must be currently running, a human approval event must exist in the trajectory, and that approval must apply to the same application being restarted. If any condition is missing, AgentCore Gateway denies the restart request and records exactly which condition failed.
This pattern is especially relevant for production operations because it separates the agent’s ability to recommend an action from its authority to execute it. The agent can investigate, summarize, and propose a restart all day long. It cannot actually perform one until the full safety checklist is satisfied in the session history. Here is what the trajectory looks like as an illustrative pseudo-policy document (this is a conceptual shape, not the exact API syntax: the official references at the end of this article cover the real configuration):
// Illustrative temporal policy - conceptual shape, not exact API.
{
"policy": "restart_requires_full_safety_check",
"target_tool": "restart_application",
"decision": "DENY_UNLESS",
"requires_trajectory": {
"all_of": [
{ "tool": "get_application_status", "max_age_seconds": 120 },
{ "tool": "check_active_users", "max_age_seconds": 120 },
{ "tool": "request_approval", "match_field": "application_id" },
{ "human_approval": true, "for_target": "restart_application" }
]
}
}When the agent calls restart_application, the gateway retrieves the session trajectory, evaluates each all_of condition against the history, and returns a single deterministic decision. If the status check is 200 seconds old, the policy denies the call and the agent is forced to re-check before retrying. The agent did not choose to be safe; the infrastructure made unsafe execution impossible.
Contrast this with the prompt-only approach, where you would write something like “always check status and get approval before restarting” into the system prompt and hope the agent complies on the 10,000th request at 3am. Temporal policies turn that hope into a guarantee, and they turn the guarantee into an auditable log entry.
Here is the human-in-the-loop gate from the agent’s side, showing how the trajectory is built up before the terminal action is ever attempted. The agent calls request_approval first; only once an approved event lands in the session does it attempt the restart:
# Illustrative agent-side flow that satisfies the restart policy.
# The gateway enforces the rule; the agent just has to follow the path.
def restart_safely(app_id):
# 1. Fresh status (must be within the policy's max_age window)
status = call_tool("get_application_status", {"application_id": app_id})
if status.critical_activity_running:
return ("aborted", "critical activity in progress")
# 2. Fresh active-user count
users = call_tool("check_active_users", {"application_id": app_id})
if users.active > 0 and not status.draining:
return ("aborted", "users still active, not draining")
# 3. Record a human approval event in the trajectory
approval = call_tool("request_approval", {
"application_id": app_id,
"reason": f"restart {app_id}; {users.active} active users",
})
if not approval.approved:
return ("aborted", "human rejected the restart")
# 4. Only now will the gateway ALLOW restart_application
return call_tool("restart_application", {"application_id": app_id})Notice that nothing in the agent code enforces the order. The agent could legally call restart_application first, and a naive agent might try exactly that on a retry. The temporal policy is what makes the order mandatory: even if the agent skips step 3, the gateway denies step 4 and returns a failure the agent has to handle. The safety does not depend on the agent being well-behaved; it depends on the infrastructure refusing the unsafe call.
AgentCore Gateway Rate Limiting Explained
Alongside temporal policies, AWS introduced fine-grained rate limiting for the AgentCore Gateway. Where temporal policies control what an agent may do based on its history, rate limiting controls how much shared capacity the agent may consume. The gateway can throttle traffic sent to MCP tools, inference models, agents, and HTTP endpoints.
The supported controls cover the dimensions that actually matter for AI workloads: requests per second, requests per minute, tokens per minute, and connections per second. The inclusion of tokens per minute is important, because for LLM-powered systems the token is the unit of cost and capacity in a way that request counts alone do not capture. Two requests can consume wildly different amounts of model capacity depending on prompt and output length.
Limits can be scoped using a rich set of dimensions. You can apply limits per user identity, per IAM principal, per JWT claim, per target name, per tool name, and per model ID. That granularity lets you express policies that a flat rate limit never could. For example, an organization could configure basic users at 50 requests per minute, advanced users at 100 requests per minute, beta users with access to experimental models carrying separate limits, expensive models carrying lower token caps, and critical MCP tools carrying restricted request and connection limits, all in the same gateway.
An illustrative rate-limit configuration (again, conceptual shape for understanding, not exact syntax) looks like this:
// Illustrative AgentCore Gateway rate-limit config - conceptual.
{
"limits": [
{ "dimension": { "user_tier": "basic" }, "requests_per_minute": 50 },
{ "dimension": { "user_tier": "advanced" }, "requests_per_minute": 100 },
{ "dimension": { "model_id": "expensive-flagship" }, "tokens_per_minute": 50000 },
{ "dimension": { "tool_name": "process_payment" }, "connections_per_second": 2 }
]
}The value of this model is that cost and safety controls become first-class configuration rather than something bolted on per application. The same gateway that enforces your temporal policies also enforces your token budget, and both are visible to the operators who run the platform rather than hidden inside individual agent codebases.
On the operations side, limits are typically applied and inspected through the AgentCore Gateway control plane. An illustrative CLI shape for attaching a rate-limit policy to a target (the exact flags live in the official gateway documentation; this conveys the shape):
# Illustrative AgentCore Gateway CLI - conceptual shape.
# Attach a rate-limit policy to an MCP tool target.
agentcore gateway put-rate-limit
--target-name process_payment
--requests-per-minute 30
--connections-per-second 2
--tokens-per-minute 20000
--dimension "tool_name=process_payment"
# Inspect the limits currently enforced at the gateway.
agentcore gateway list-rate-limits --target-name process_paymentTreating limits as configuration means a platform team can tighten a token cap during an incident without redeploying any agent, and can roll out a new tier of beta users by editing a policy document rather than touching code. That operational leverage is a large part of why gateway-level controls beat per-agent rate limiting scattered across applications.
Why Rate Limiting Matters for Autonomous Agents
It is tempting to think of rate limiting as a generic API concern that has nothing to do with AI specifically. For agents, that framing undersells the problem. Rate limiting for agents is not just about protecting an API from a traffic spike; it is about containing a class of failure that is unique to autonomous systems.
AI agents can behave unpredictably when a tool fails. An agent may continuously retry an operation that keeps erroring, call several tools in parallel during a single task, or generate far more tokens than expected as it reasons its way through a hard problem. Without limits, that behavior can increase model costs dramatically, exhaust backend capacity, affect other users sharing the same infrastructure, overload MCP servers that were not sized for aggressive retry loops, create long-running connections that pool and leak, and turn a minor tool failure into a larger operational incident. A single agent stuck in a retry loop against an expensive model can burn through a day’s token budget in minutes.
Centralized gateway limits contain this behavior before it reaches downstream systems. When the gateway throttles the agent, the agent’s own error-handling logic kicks in: it backs off, it tries a different approach, or it reports failure to the user. That is a much better outcome than the agent silently hammering a backend until something breaks.
AWS is explicit that rate limiting should be treated as a traffic-management and quality-of-service mechanism, not as the only security boundary. Authentication, authorization, policy enforcement, AWS WAF, and observability all remain important parts of the overall architecture. Rate limiting is one layer in a defense-in-depth design, not a replacement for any of the others.
Temporal Policies vs Rate Limiting
Temporal policies and rate limiting address fundamentally different risks, and a production architecture needs both. The table below maps each capability to its primary purpose so you can reason about which layer catches which class of problem.
| Control | Primary purpose |
|---|---|
| Temporal policies | Decide whether an action is allowed based on what the agent has already done in the session |
| Request limits | Cap how frequently a user or agent may send requests to a target |
| Token limits | Control model consumption and help manage cost |
| Connection limits | Protect targets from too many simultaneous connections |
| IAM and AgentCore Identity | Authenticate identities and establish base access |
| AgentCore Policy | Enforce deterministic authorization rules |
Read the table as a stack, not a menu. IAM establishes who you are. AgentCore Policy decides what you may generally do. Temporal policies decide whether this specific next action is consistent with the workflow so far. Rate limits cap how hard you can push any target. A production architecture combines these layers instead of relying on only one control, because each layer catches a different failure mode.
Why Gateway-Layer Enforcement Changes Everything
The most important aspect of these capabilities is not what they enforce but where they enforce it. Location determines whether the control is a suggestion or a guarantee.
If governance exists only in the system prompt, the agent is responsible for interpreting and following it, and we already know that agents are unreliable rule-followers under pressure, especially when a goal seems within reach. If governance exists only in application code, every development team that builds an agent must implement and maintain the controls correctly, and the inevitable result is inconsistent enforcement across agents and drift over time.
AgentCore applies these controls at the gateway layer, creating a single centralized enforcement point for all traffic flowing to models, agents, MCP servers, knowledge bases, and other targets. That separation provides several advantages that are hard to replicate any other way. Policies remain independent of the selected model, so you can swap the underlying LLM without re-implementing your safety rules. Controls can be applied consistently across multiple agents built by different teams. Authorization decisions are deterministic rather than probabilistic, which is what auditors and regulators need to see. Agent behavior becomes easier to audit because every decision is logged with its trajectory context at a single choke point. Security logic is separated from agent reasoning, so the two can evolve independently. And governance can evolve without redesigning every agent, because the agents never knew about the rules in the first place.
This is the same lesson the industry learned with API gateways a decade ago: put the cross-cutting concerns at a shared perimeter, not in every service. AgentCore Gateway is that perimeter for agentic systems.
Designing Agent Governance: A Solution Architect’s Checklist
When you evaluate an enterprise agent architecture, the right questions are the ones that move the conversation from “can we build a working demo” to “can we operate a controlled production system.” The following checklist, drawn from how these capabilities are meant to be applied, gives you a structured way to do that assessment.
- Which actions can create financial, security, or operational impact?
- Must certain tools be called in a specific order?
- Which values must remain consistent between steps?
- When is human approval mandatory?
- What cumulative limits apply to a session?
- How recent must the supporting data be before a dependent action is allowed?
- What request, token, and connection limits are required per identity, tool, and model?
- Where are authorization decisions recorded and monitored?
- What happens when an agent repeatedly retries a failed tool: is it throttled, or does it loop forever?
- Are the controls enforced outside the agent itself, or do they rely on the agent’s cooperation?
If you can answer all ten with specific, defensible answers, your architecture is ready for production. If several answers are “we’ll put it in the prompt,” you have a demo, not a system.
Temporal Policies: Common Mistakes to Avoid
Even experienced platform teams get agent governance wrong when they first encounter these primitives. Here are the most common mistakes.
- Trusting the system prompt to enforce boundaries: prompts influence behavior; they do not guarantee it. Put irreversible-action rules in the gateway, not the prompt.
- Only limiting per-request and ignoring the trajectory: each call looks fine in isolation while the overall sequence is unsafe. Cumulative and sequencing rules catch what per-request limits miss.
- Forgetting the session-reset attack: an agent could start a fresh session to dodge a cumulative cap. Tie limits to a stable identity or principal, not just to the session.
- Treating rate limiting as your only security layer: it is traffic management, not authorization. Pair it with IAM, temporal policies, WAF, and observability in layers.
Temporal Policies: Best Practices
- Enforce governance outside the agent: at the gateway, never only in the prompt or the application code.
- Require a human-approval event in the trajectory for any irreversible or high-impact action.
- Make data-integrity checks between tools part of the policy, not a hope: deny when inputs do not match prior outputs.
- Combine temporal policies, rate limits, IAM, and WAF as layered controls rather than picking one.
- Log every authorization decision with its trajectory context so audits and incident reviews are actually possible.
Temporal Policies: Frequently Asked Questions
What are temporal policies in Amazon Bedrock AgentCore?
Temporal policies are stateful, trajectory-aware authorization rules. Instead of evaluating only the current request, they consider what the agent has already done in the session and decide whether the next action should be allowed given that history.
How do temporal policies differ from IAM or rate limiting?
IAM establishes identity and base access. Rate limiting controls how frequently an identity can call something. Temporal policies control whether an action is allowed based on the sequence and integrity of prior actions, which is a question neither IAM nor rate limiting can answer.
Do temporal policies slow down my agent?
The overhead is minimal because the check is a deterministic evaluation at the gateway perimeter, performed before the request reaches the target. For the safety it provides, the latency is almost always an acceptable tradeoff.
Can an agent bypass temporal policies by re-prompting itself?
No. Because enforcement happens outside the agent’s reasoning loop at the AgentCore Gateway, there is no prompt the agent can issue that changes the policy decision. The agent cannot reason its way around infrastructure.
Where are authorization decisions recorded?
At the gateway, with the full trajectory context that produced the decision. This makes temporal-policy denials auditable: you can reconstruct exactly why a given action was blocked, which is essential for regulated workloads.
Temporal Policies: Key Takeaways
The shift from stateless to stateful authorization is the real story behind these capabilities.
- Stateless authorization fails for agents because every call can be legal while the sequence is unsafe.
- Temporal policies are stateful rules evaluated at the AgentCore Gateway, outside the agent’s reasoning loop.
- The six guardrails (sequencing, data integrity, human approval, cumulative limits, freshness, mutual exclusivity) cover the real agent failure modes.
- Combine temporal policies with gateway rate limiting, IAM, and WAF in layers; no single control is sufficient.
Temporal policies on Amazon Bedrock AgentCore give you infrastructure-enforced governance for agentic systems: they make the agent’s complete sequence of actions controllable, not just its access to individual tools, and they pair with gateway rate limiting to keep cost and capacity in check as agents grow more autonomous.