

# Create a policy
<a name="policy-create-policies"></a>

Policy in Amazon Bedrock AgentCore uses Cedar as its authorization language to control access to tools and resources. This guide explains how to understand Cedar policies and write authorization requirements in natural language that can be automatically converted to Cedar. Natural language policy generation requires a deployed AgentCore Gateway and policy engine.

Cedar is a formal policy language that provides precise, verifiable access control. When working with AgentCore Gateway authorization:
+  **Understand Cedar policies** - Read and interpret existing Cedar policies to understand access control rules
+  **Write in natural language** - Express authorization requirements using clear, precise natural language
+  **Convert to Cedar** - Use policy authoring service to automatically generate Cedar policies from natural language
+  **Verify policies** - Review generated Cedar policies to ensure they match your requirements

You don’t need to memorize Cedar syntax. Focus on understanding policy structure and writing precise natural language requirements.

**Topics**
+ [

# Understanding Cedar policies
](policy-understanding-cedar.md)
+ [

# Policy scope
](policy-scope.md)
+ [

# Policy conditions
](policy-conditions.md)
+ [

# Authorization flow
](policy-authorization-flow.md)
+ [

# Schema constraints
](policy-schema-constraints.md)
+ [

# Limitations
](policy-limitations-section.md)
+ [

# Common policy patterns
](policy-common-patterns.md)
+ [

# Time-based policy support
](policy-time-based.md)

# Understanding Cedar policies
<a name="policy-understanding-cedar"></a>

Policy in AgentCore uses Cedar policies to control access to AgentCore Gateway tools. This section explains Cedar policy structure, evaluation semantics, and key concepts.

**Topics**
+ [

## Example policy
](#policy-example)
+ [

## Policy structure
](#policy-structure)
+ [

## Policy effects
](#policy-effects)
+ [

## Default deny
](#policy-default-deny)
+ [

## Authorization evaluation
](#policy-authorization-evaluation)
+ [

## Policy independence
](#policy-independence)
+ [

## Policy evaluation algorithm
](#policy-evaluation-algorithm)

## Example policy
<a name="policy-example"></a>

Consider a refund processing tool with these requirements:
+ Only the user "John" can process refunds
+ Refunds are limited to \$1500 or less

The Cedar policy that enforces these requirements:

```
permit(
  principal is AgentCore::OAuthUser,
  action == AgentCore::Action::"RefundTool__process_refund",
  resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:your-region:your-account-id:gateway/refund-gateway"
)
when {
  principal.hasTag("username") &&
  principal.getTag("username") == "John" &&
  context.input.amount < 500
};
```

This policy allows refund processing only when the user is "John" and the refund amount is less than \$1500.

## Policy structure
<a name="policy-structure"></a>

Cedar policies consist of three main components:

1.  **Effect** - Determines whether to allow or deny access ( `permit` or `forbid` )

1.  **Scope** - Specifies the principal, action, and resource the policy applies to

1.  **Condition** - Defines additional logic that must be satisfied ( `when` or `unless` ) and can refer to the tool parameters (through the context) and the OAuth token (through the tags)

## Policy effects
<a name="policy-effects"></a>

Cedar policies use two effects to control access:
+  `permit` - Allows the action to proceed
+  `forbid` - Denies the action

## Default deny
<a name="policy-default-deny"></a>

All actions are denied by default. If no policies match a request, Cedar returns DENY. You must explicitly write permit policies to allow actions.

## Authorization evaluation
<a name="policy-authorization-evaluation"></a>

Cedar uses a forbid-overrides-permit evaluation model:

1. Cedar evaluates all policies that apply to the request

1. If any forbid policy matches, the result is DENY

1. If at least one permit policy matches and no forbid policies does, the result is ALLOW

1. If no policies match, the result is DENY (default deny)

## Policy independence
<a name="policy-independence"></a>

Each Cedar policy evaluates independently. A policy’s evaluation depends only on:
+ The scope (principal, action, resource)
+ The context and tags

Policies do not reference or depend on other policies.

## Policy evaluation algorithm
<a name="policy-evaluation-algorithm"></a>

When a request is evaluated, the policy engine determines the authorization decision using the following algorithm:

1. If any `forbid` policy matches the request, the decision is DENY.

1. If no `forbid` policy matches the request and at least one `permit` policy matches, the decision is ALLOW.

1. If neither `forbid` nor `permit` policies match the request, the decision is DENY.

This evaluation model enforces a **default deny** posture.

A `forbid` policy can never result in an ALLOW decision. The `unless` clause on a `forbid` policy specifies conditions under which that `forbid` policy does not apply; it does **not** grant permission and does not override a matching `permit` policy.

# Policy scope
<a name="policy-scope"></a>

The scope defines what the policy applies to. Every Cedar policy specifies three components:

**Topics**
+ [

## Entities and namespaces
](#policy-entities-namespaces)
+ [

## Principal
](#policy-principal)
+ [

## Action
](#policy-action)
+ [

## Resource
](#policy-resource)

```
permit(
  principal is AgentCore::OAuthUser,    // WHO is making the request
  action == AgentCore::Action::"...",   // WHAT they want to do
  resource is AgentCore::Gateway::"..." // WHICH resource they want to access
)
```

## Entities and namespaces
<a name="policy-entities-namespaces"></a>

Cedar uses entities to represent principals, actions, and resources. All entities in AgentCore Gateway use the AgentCore namespace.

Entity format: `Namespace::EntityType::"identifier"` 

## Principal
<a name="policy-principal"></a>

The principal identifies the entity making the authorization request. The principal type depends on how your AgentCore Gateway is configured for authentication.

### OAuth User Principal
<a name="policy-principal-oauth"></a>

When using OAuth authorization, the principal is an `AgentCore::OAuthUser` :

```
principal is AgentCore::OAuthUser
```

Components:
+  `principal` - The entity making the authorization request
+  `AgentCore::OAuthUser` - Entity type representing OAuth-authenticated users
+  `is` - Type check operator (matches any OAuthUser entity)

Principals are OAuth-authenticated users. Each user has a unique ID from the JWT sub claim.

### IAM Entity Principal
<a name="policy-principal-iam"></a>

When using AWS\$1IAM authorization, the principal is an `AgentCore::IamEntity` :

```
principal is AgentCore::IamEntity
```

Components:
+  `principal` - The entity making the authorization request
+  `AgentCore::IamEntity` - Entity type representing IAM-authenticated callers
+  `is` - Type check operator (matches any IamEntity)

IAM principals have an `id` attribute containing the caller’s IAM ARN. You can use pattern matching on this attribute to implement account-based or role-based access control.

## Action
<a name="policy-action"></a>

The action specifies the operation being requested:

```
action == AgentCore::Action::"RefundTool__process_refund"
```

Components:
+  `action` - The operation being requested
+  `AgentCore::Action::"RefundTool__process_refund"` - Specific action entity
+  `==` - Exact match operator (only this specific action)

Actions represent tool calls in the MCP AgentCore Gateway. Each tool has a corresponding action entity.

### Multiple actions
<a name="policy-action-wildcards"></a>

Cedar does **not** support wildcard actions. Each action must be referenced explicitly using the exact action identifier ( `AgentCore::Action::"ToolName__operation"` ). To group multiple tools under a single rule, use a **Gateway Target** (an Action Group) and write policies against that target.

For example, to allow access only to tools whose names start with Read, you can create a Gateway Target called ReadToolsTarget that includes each such tool, and then write a policy like:

```
permit(
  principal,
  action in AgentCore::Action::"ReadToolsTarget",
  resource == AgentCore::Gateway::"<gateway-arn>"
);
```

This will permit all tools included in that target depending on the policy’s effect.

## Resource
<a name="policy-resource"></a>

The resource identifies the target of the request:

```
resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/refund-gateway"
```

Components:
+  `resource` - The target of the request
+  `AgentCore::Gateway` - Entity type representing gateway instances
+  `==` - Exact match operator (matches this specific AgentCore Gateway)

The AgentCore Gateway is the MCP server that routes tool calls.

### Resource specificity requirements
<a name="policy-resource-specificity"></a>

When specifying one or more specific actions, you must use specific AgentCore Gateway ARNs:

```
// Required: Specific Gateway ARN for specific action(s)
resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/refund-gateway"
```

This applies to:
+ Single action: `action == AgentCore::Action::"ToolName"` 
+ Multiple specific actions: `action in [AgentCore::Action::"Tool1", AgentCore::Action::"Tool2"]` 

Use type checks only when matching any action:

```
// For policies covering any action (not specific tools)
resource is AgentCore::Gateway
```

Examples:

```
// Blocks all actions
forbid(principal, action, resource);

// Allow any CallTool action
permit(principal, action in AgentCore::Action::"CallTool", resource is AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/refund-gateway");
```

Specific AgentCore Gateway ARNs provide:
+ Security isolation between AgentCore Gateway instances
+ Separation of production and development environments
+ Fine-grained access control per AgentCore Gateway

# Policy conditions
<a name="policy-conditions"></a>

Conditions add fine-grained logic to policies using `when` and `unless` clauses:

```
when {
  principal.hasTag("username") &&
  principal.getTag("username") == "refund-agent" &&
  context.input.amount < 500
}
```

## Condition types
<a name="policy-condition-types"></a>
+  `when { …​ }` - Policy applies only if the condition is true
+  `unless { …​ }` - Policy applies only if the condition is false

## Tool arguments
<a name="policy-tool-arguments"></a>

 `context.input` contains the arguments passed to the tool call:

```
context.input.amount < 500
```

When a user calls `RefundTool__process_refund` with arguments like:

```
{
  "orderId": "12345",
  "amount": 450,
  "reason": "Defective product"
}
```

The policy can access these values:
+  `context.input.orderId` → "12345"
+  `context.input.amount` → 450
+  `context.input.reason` → "Defective product"

Policies can make decisions based on specific tool call parameters.

## Principal attributes
<a name="policy-principal-attributes"></a>

Principal attributes differ based on the authentication type configured for your AgentCore Gateway.

### OAuth claims (tags)
<a name="policy-oauth-claims"></a>

For OAuth-authenticated gateways, JWT claims from the OAuth token are stored as tags on the OAuthUser entity. Example JWT claims:

```
{
  "sub": "user-123",
  "username": "refund-agent",
  "scope": "refund:write admin:read",
  "role": "admin"
}
```

These claims become tags on the principal entity. Check if a tag exists:

```
principal.hasTag("username")
```

Get a tag value:

```
principal.getTag("username") == "refund-agent"
```

Pattern matching:

```
principal.getTag("scope") like "*refund:write*"
```

### IAM entity attributes
<a name="policy-iam-attributes"></a>

For IAM-authenticated gateways, the principal has an `id` attribute containing the caller’s IAM ARN. IAM principals do not support tags.

The `principal.id` attribute contains the full IAM ARN in one of these formats:
+  **IAM user:** `arn:aws:iam::123456789012:user/username` 
+  **IAM role (assumed):** `arn:aws:sts::123456789012:assumed-role/role-name/session-name` 
+  **IAM role:** `arn:aws:iam::123456789012:role/role-name` 

Use the `like` operator with wildcards to match patterns in the IAM ARN:

```
// Match specific AWS account
principal.id like "*:123456789012:*"

// Match specific IAM role
principal.id like "arn:aws:iam::*:role/AdminRole"

// Match any role in a specific account
principal.id like "arn:aws:iam::123456789012:role/*"

// Match assumed role sessions
principal.id like "arn:aws:sts::*:assumed-role/ServiceRole/*"
```

## Logical operators
<a name="policy-logical-operators"></a>

Combine multiple conditions using logical operators:
+  `&&` - AND (all conditions must be true)
+  `||` - OR (at least one condition must be true)
+  `!` - NOT (negates a condition)

Example:

```
principal.hasTag("username") &&              // User must have username tag
principal.getTag("username") == "refund-agent" &&  // Username must be "refund-agent"
context.input.amount < 500                   // Amount must be less than $500
```

# Authorization flow
<a name="policy-authorization-flow"></a>

Amazon Bedrock AgentCore Gateway evaluates Cedar policies against incoming requests. This section explains how authorization information flows from the request to policy evaluation.

## Request processing
<a name="policy-request-processing"></a>

Amazon Bedrock AgentCore Gateway processes two key pieces of information from each request:

1.  **JWT Token** - Contains OAuth claims about the user:

   ```
   {
     "sub": "12345678-1234-1234-1234-123456789012",
     "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_Vg2efaoGO",
     "username": "refund-agent",
     "scope": "aws.cognito.signin.user.admin refund:write",
     "role": "admin",
     "department": "finance"
   }
   ```

1.  **MCP Tool Call Request** - The actual tool invocation:

   ```
   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "tools/call",
     "params": {
       "name": "RefundTool__process_refund",
       "arguments": {
         "orderId": "12345",
         "amount": 450,
         "reason": "Defective product"
       }
     }
   }
   ```

## Cedar authorization request
<a name="policy-cedar-authorization-request"></a>

The Gateway extracts information from both sources and constructs a Cedar authorization request.

 **Complete Authorization Request:** 

```
{
  "principal": "AgentCore::OAuthUser::\"12345678-1234-1234-1234-123456789012\"",
  "action": "AgentCore::Action::\"RefundTool__process_refund\"",
  "resource": "AgentCore::Gateway::\"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/refund-gateway\"",
  "context": {
    "input": {
      "orderId": "12345",
      "amount": 450,
      "reason": "Defective product"
    }
  }
}
```

 **Components:** 

Principal  
Created from the JWT token’s sub claim:  

```
AgentCore::OAuthUser::"12345678-1234-1234-1234-123456789012"
```

Action  
Extracted from the tool name:  

```
AgentCore::Action::"RefundTool__process_refund"
```

Resource  
The Gateway instance:  

```
AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/refund-gateway"
```

Context  
Contains the tool arguments:  

```
{
  "input": {
    "orderId": "12345",
    "amount": 450,
    "reason": "Defective product"
  }
}
```

 **Entity Store** - The JWT claims are stored as tags on the OAuthUser entity:

```
{
  "uid": {
    "type": "AgentCore::OAuthUser",
    "id": "12345678-1234-1234-1234-123456789012"
  },
  "attrs": {
    "id": "12345678-1234-1234-1234-123456789012"
  },
  "tags": {
    "username": "refund-agent",
    "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_Vg2efaoGO",
    "scope": "aws.cognito.signin.user.admin refund:write",
    "role": "admin",
    "department": "finance"
  }
}
```

## Policy evaluation
<a name="policy-evaluation"></a>

Cedar evaluates:

1.  **Principal check:** Is the principal an OAuthUser? ✓ (matches)

1.  **Action check:** Is the action RefundTool\$1\$1process\$1refund? ✓ (matches)

1.  **Resource check:** Is the resource the refund gateway? ✓ (matches)

1.  **Condition checks:** 
   + Does principal have username tag? ✓ (yes, from JWT)
   + Is username = "refund-agent"? ✓ (yes)
   + Is context.input.amount < 500? ✓ (450 < 500)

 **Result:** ALLOW - All checks pass, the refund is authorized.

# Schema constraints
<a name="policy-schema-constraints"></a>

Policies for Amazon Bedrock AgentCore Gateway must validate against a specific Cedar schema that is automatically generated from the Gateway’s MCP tool manifest. This schema defines what’s possible in your policies.

**Topics**
+ [

## Principal Types
](#policy-principal-type)
+ [

## Resource Type
](#policy-resource-type)
+ [

## Actions
](#policy-actions)
+ [

## Context
](#policy-context)
+ [

## What You Cannot Do
](#policy-limitations)

## Principal Types
<a name="policy-principal-type"></a>

The principal type depends on the authentication method configured for your AgentCore Gateway:

 `AgentCore::OAuthUser`   
+ Used for OAuth-authenticated gateways
+ Has an `id` attribute (from JWT sub claim)
+ Supports tags for OAuth claims (username, scope, role, etc.)

 `AgentCore::IamEntity`   
+ Used for IAM-authenticated gateways (AWS\$1IAM authorizer)
+ Has an `id` attribute containing the caller’s IAM ARN
+ Does not support tags; use pattern matching on `principal.id` for access control

## Resource Type
<a name="policy-resource-type"></a>
+ Must be `AgentCore::Gateway` 
+ Represents the MCP Gateway instance
+ Can be matched by type ( `is` ) or specific ARN ( `==` )
+ Must use specific ARNs to refer to specific actions

## Actions
<a name="policy-actions"></a>
+ Each MCP tool becomes an action: `AgentCore::Action::"ToolName"` 
+ All tool actions inherit from CallTool → Mcp hierarchy
+ Example: `Action::"RefundTool__process_refund"` is a CallTool

## Context
<a name="policy-context"></a>
+ Only available context is `context.input` 
+ Contains the tool’s input parameters as defined in the MCP manifest
+ Each tool has a typed input structure (e.g., RefundTool\$1\$1\$1process\$1refundInput)
+ Parameter types are automatically mapped from JSON Schema to Cedar types:
  + string → String
  + integer → Long
  + boolean → Bool
  + number → Decimal

## What You Cannot Do
<a name="policy-limitations"></a>
+ Cannot reference entity types outside AgentCore namespace
+ Cannot access context fields other than `context.input` 
+ Cannot use custom attributes on OAuthUser (use tags instead)
+ Cannot define new entity types in policies

# Limitations
<a name="policy-limitations-section"></a>

Cedar policies and the current Amazon Bedrock AgentCore Gateway implementation have certain limitations that affect policy authoring and functionality.

## Cedar language limitations
<a name="policy-cedar-limitations"></a>

The following limitations are inherent to the Cedar policy language:
+  **No floating-point numbers** - Cedar does not support float types. Use Decimal for fractional values (limited to 4 decimal places)
+  **No regular expressions** - Pattern matching is limited to the like operator with \$1 wildcards

## Current implementation limitations
<a name="policy-implementation-limitations"></a>

The following limitations are specific to the current Amazon Bedrock AgentCore Gateway implementation:
+  **Custom claims in NL2Cedar** - to use custom claims with NL2Cedar, provide the custom claims in the prompt
+  **Limited decimal precision** - Decimal values are limited to 4 decimal places and a specific range
+  **Cedar schema size** - supported schemas size under 200 kb
+  **Max Policies per Engine** - 1000
+  **Max Policy Engines per account** - 1000

These implementation limitations may be addressed in future releases.

# Common policy patterns
<a name="policy-common-patterns"></a>

These examples demonstrate frequently used Cedar policy patterns. The patterns work with both OAuth and IAM authentication—select the appropriate principal type for your AgentCore Gateway configuration. For details on principal attributes, see [Principal attributes](policy-conditions.md#policy-principal-attributes).

These patterns apply regardless of authentication type.

## Emergency shutdown
<a name="policy-emergency-shutdown"></a>

Disable all tool calls across the entire Gateway:

```
forbid(
  principal,
  action,
  resource
);
```

 **Use case:** Emergency shutdown, maintenance mode, or incident response.

 **Effect:** Overrides all permit policies due to forbid-wins semantics.

## Disable specific tool
<a name="policy-disable-specific-tool"></a>

Disable a specific tool while keeping others operational:

```
forbid(
  principal,
  action == AgentCore::Action::"RefundTool__process_refund",
  resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/refund-gateway"
);
```

 **Use case:** Temporarily disable a problematic tool without affecting other functionality.

## Block user access
<a name="policy-block-user-access"></a>

Prevent specific users or accounts from performing any actions:

### OAuth: Block specific user
<a name="policy-oauth-block-user"></a>

Block a user by matching their username tag:

```
forbid(
  principal is AgentCore::OAuthUser,
  action,
  resource
)
when {
  principal.hasTag("username") &&
  principal.getTag("username") == "suspended-user"
};
```

 **Use case:** Immediately revoke access for a compromised or suspended user account.

### IAM: Block specific account
<a name="policy-iam-block-account"></a>

Block callers from a specific AWS account:

```
forbid(
  principal is AgentCore::IamEntity,
  action,
  resource
)
when {
  principal.id like "*:444455556666:*"
};
```

 **Use case:** Block test or unauthorized accounts from accessing production tools.

## Role-based access control
<a name="policy-role-based-patterns"></a>

Restrict access based on roles. OAuth uses role tags; IAM uses role ARN patterns.

### OAuth: Using role tags
<a name="policy-oauth-role-based"></a>

Permit access only to users with specific roles:

```
permit(
  principal is AgentCore::OAuthUser,
  action == AgentCore::Action::"AdminAPI__delete_resource",
  resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/admin"
)
when {
  principal.hasTag("role") &&
  (principal.getTag("role") == "admin" || principal.getTag("role") == "manager")
};
```

 **Use case:** Allow administrative operations only for users with admin or manager roles.

### IAM: Using IAM role ARNs
<a name="policy-iam-role-based"></a>

Permit access only to callers using specific IAM roles:

```
permit(
  principal is AgentCore::IamEntity,
  action == AgentCore::Action::"AdminAPI__delete_resource",
  resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/admin"
)
when {
  principal.id like "arn:aws:iam::*:role/AdminRole"
};
```

 **Use case:** Allow administrative operations only for callers using the AdminRole IAM role.

 **Variations:** 

```
// Match assumed role sessions
principal.id like "arn:aws:sts::*:assumed-role/AdminRole/*"

// Match any role in a specific account
principal.id like "arn:aws:iam::123456789012:role/*"
```

## Data type operations
<a name="policy-data-type-operations"></a>

Cedar supports various data types in conditions. These examples use OAuth principals ( `AgentCore::OAuthUser` ). For IAM-authenticated gateways, use `AgentCore::IamEntity` instead - the input validation logic remains identical.

### Integers (Long)
<a name="policy-integers"></a>

```
// Check if passenger count is exactly 2
permit(
  principal is AgentCore::OAuthUser,
  action == AgentCore::Action::"TravelAPI__search_flights",
  resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/travel"
)
when {
  context.input.passengers == 2
};
```

### Strings
<a name="policy-strings"></a>

```
// Check if payment method is credit card
permit(
  principal is AgentCore::OAuthUser,
  action == AgentCore::Action::"PaymentAPI__process_payment",
  resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/payment"
)
when {
  context.input.paymentMethod == "credit-card"
};
```

### Lists (Sets)
<a name="policy-lists"></a>

```
// Check if country is in allowed list
permit(
  principal is AgentCore::OAuthUser,
  action == AgentCore::Action::"ShippingAPI__calculate_rate",
  resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/shipping"
)
when {
  ["US", "CA", "MX"].contains(context.input.country)
};
```

### Checking for Optional Fields
<a name="policy-optional-fields"></a>

```
// Require optional field to be present
permit(
  principal is AgentCore::OAuthUser,
  action == AgentCore::Action::"OrderAPI__create_order",
  resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/order"
)
when {
  context.input has shippingAddress
};
```

# Time-based policy support
<a name="policy-time-based"></a>

Policy in AgentCore supports time-based restrictions in Cedar policies through the `context.system.now` datetime value. This enables you to enforce policies based on specific dates, times, or time ranges.

**Topics**
+ [

## How it works
](#policy-time-based-how)
+ [

## Absolute date and time range restrictions
](#policy-time-absolute)
+ [

## Daily recurring time restrictions
](#policy-time-daily)
+ [

## Combined date and time restrictions
](#policy-time-combined)
+ [

## Timezone handling
](#policy-time-timezone)
+ [

## Using natural language to generate time-based policies
](#policy-time-natural-language)

## How it works
<a name="policy-time-based-how"></a>

During policy evaluation, the current UTC timestamp is provided as part of evaluation context:

```
// Current datetime in UTC
context.system.now
```

You can use Cedar’s datetime functions to create time-based conditions:
+  `datetime("YYYY-MM-DDTHH:MM:SSZ")` — Create a datetime value
+  `duration("Xh")` — Create a duration (hours, minutes, seconds)
+  `.toTime()` — Extract time of day from datetime
+ Comparison operators: `<` , `⇐` , `>` , `>=` , `==` 

## Absolute date and time range restrictions
<a name="policy-time-absolute"></a>

Enforce policies within specific calendar periods.

### Example: Promotional period policy
<a name="policy-time-absolute-example"></a>

```
permit(
  principal,
  action == AgentCore::Action::"RefundToolTarget___refund",
  resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/my-gateway"
)
when {
  context.system.now >= datetime("2025-01-01T00:00:00Z") &&
  context.system.now < datetime("2025-01-31T23:59:59Z")
};
```

 **Use case:** Allow refunds only during January 2025.

## Daily recurring time restrictions
<a name="policy-time-daily"></a>

Enforce policies based on time of day that recur daily.

### Example: Business hours policy
<a name="policy-time-daily-example"></a>

```
permit(
  principal,
  action == AgentCore::Action::"RefundToolTarget___refund",
  resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/my-gateway"
)
when {
  duration("9h") <= context.system.now.toTime() &&
  context.system.now.toTime() <= duration("17h")
};
```

 **Use case:** Allow refunds only during business hours (9 AM–5 PM UTC daily).

## Combined date and time restrictions
<a name="policy-time-combined"></a>

Combine absolute dates with daily time restrictions.

### Example: Limited-time promotion with daily hours
<a name="policy-time-combined-example"></a>

```
permit(
  principal,
  action == AgentCore::Action::"DiscountToolTarget___apply_discount",
  resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/my-gateway"
)
when {
  // Valid dates: Feb 1-28, 2025
  context.system.now >= datetime("2025-02-01T00:00:00Z") &&
  context.system.now < datetime("2025-03-01T00:00:00Z") &&
  // Valid hours: 9am-9pm UTC daily
  duration("9h") <= context.system.now.toTime() &&
  context.system.now.toTime() <= duration("21h")
};
```

 **Use case:** Allow discount tool only during February 2025, between 9 AM and 9 PM UTC daily.

## Timezone handling
<a name="policy-time-timezone"></a>

All datetime values must be in UTC. The Policy Engine does not support timezone conversions or timezone-aware policies.

When specifying times in your policies, always use UTC. If your business operates in a different timezone, convert your local times to UTC before creating the policy.

## Using natural language to generate time-based policies
<a name="policy-time-natural-language"></a>

The policy authoring service can generate time-based policies from natural language descriptions.

### Example: Generate business hours policy
<a name="policy-time-nl-example"></a>

```
aws bedrock-agentcore-control start-policy-generation \
  --policy-engine-id MyEngine-abc123 \
  --name BusinessHoursOnly \
  --content '{
    "rawText": "Allow refunds only during business hours 9am to 5pm UTC"
  }' \
  --resource '{
    "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/MyGateway-xyz789"
  }'
```

Generated policy:

```
permit(
  principal,
  action == AgentCore::Action::"RefundToolTarget___refund",
  resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/MyGateway-xyz789"
)
when {
  duration("9h") <= context.system.now.toTime() &&
  context.system.now.toTime() <= duration("17h")
};
```

### Best practices for natural language
<a name="policy-time-nl-best-practices"></a>
+  **Be explicit about times** — Use "9am to 5pm UTC" instead of "business hours"
+  **Always specify UTC** — Include "UTC" to avoid ambiguity
+  **Use ISO format for dates** — Use "2025-01-01" instead of "January 1st"
+  **Provide specific time ranges** — Avoid vague terms like "daytime" or "after hours"

Good examples of natural language prompts:

```
"Allow refunds only between 9am and 5pm UTC"
"Allow payments except between 2am and 4am UTC daily"
"Allow discounts only from 2025-02-01 to 2025-02-28"
"Permit high-value transactions between 8am and 8pm UTC"
```