Authoring temporal policies
You author a temporal policy in the Dogwood policy language and add it to a policy engine, the same way
you create any other policy for Policy in AgentCore. A temporal policy is a permit or forbid rule
whose session-aware conditions are placed in a temporal block; the principal, action, and resource
the rule applies to are written using the standard (principal, action, resource) scope, the same as any other policy. The following sections show how to create a temporal
policy and walk through common patterns you can express.
Create a temporal policy
You create a temporal policy with the create-policy operation, the same operation you use for other
policies, and attach it to a policy engine. A temporal policy’s statement goes under policy in the definition, rather than under cedar as for a
stateless Cedar policy.
The following example creates a temporal policy on a policy engine:
Example
This temporal policy depends on an authorized approve_claim request. Without a plain permit for that
prerequisite action, deny-by-default prevents the request from running and no response event is recorded.
Create a separate policy containing the following statement:
permit ( principal, action == AgentCore::Action::"InsuranceAPI___approve_claim", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" );
You can also create a temporal policy by describing it in natural language instead of writing the Dogwood statement yourself.
Event schema: fields you can reference
Conditions inside a temporal { } block use temporal event predicates to match specific events that
were recorded in the session so far (up to and including the action that is currently being authorized). A predicate names a time window, an action and event kind, and a
set of field constraints on the matched event. The create-policy example in the previous section used
one predicate, formerly within 1h AgentCore::Action::"InsuranceAPI___approve_claim"::response{
eventResource: resource, output.claimId: context.input.claimId }, which matches an approve_claim
response recorded within the last hour whose output.claimId equals the current request’s claimId.
To write a predicate, you need to know which events an action produces and which fields each event carries, because those are the fields a predicate can constrain and correlate against. This section describes that event schema.
Each action produces up to three kinds of event, named after the event kind in the predicate
(::request, ::response, ::error):
-
request— recorded for each authorized request. Carries the action’s input fields. -
response— recorded when the tool returns successfully. Carries the action’s input and output fields. -
error— recorded when the request is denied or the tool returns an error. Carries the action’s input fields. This event is history-only.
The temporal event schema defines these events for each action A. …inputs(A) and …outputs(A)
expand to the action’s declared input and output fields:
// Recorded for each authorized request. decision event <A>::request { ...inputs(A), eventPrincipal: principalType(A), eventResource: resourceType(A), requestId: String, pin sessionId: String = context.sessionId, } // Recorded when the tool returns successfully; carries inputs and outputs. event <A>::response { ...inputs(A), ...outputs(A), eventPrincipal: principalType(A), eventResource: resourceType(A), requestId: String, pin sessionId: String = context.sessionId, } // Recorded when the request is denied or the tool returns an error; history-only. event <A>::error { ...inputs(A), eventPrincipal: principalType(A), eventResource: resourceType(A), requestId: String, pin sessionId: String = context.sessionId, }
Within a predicate body, you can reference the following fields of the matched event:
| Field | Description |
|---|---|
|
|
An input field of the action. Available on |
|
|
An output field of the action. Available on |
|
|
The principal that made the recorded request. |
|
|
Always set this to |
To correlate a recorded event with the current request, compare one of these fields against a value
from the current request, such as context.input.<name>.
Example temporal policies
For examples of each pattern temporal policies express — requiring a prior approval, expiring a stale prerequisite, capping a count or a running total, cool-downs, mutual exclusion, chains, and reacting to a prior denial — see Temporal policy examples in Policy authoring guide. Each example there is written against the same reference gateway as the rest of the policy examples, states which plain permits to pair it with, and gives the decision for each request sequence in a session.