AWS open-sourced Dogwood this week: a policy language extending Cedar to govern sequences of agent tool calls, not just individual requests. The reference interpreter is live under Apache 2.0, and AgentCore Policy — the control layer between model and MCP tool call — supports it today. Cedar authorizes one request at a time with no memory of prior actions. Agents operate in sequences.
Cedar's stateless design is intentional. The same request yields the same answer regardless of prior state, making automated reasoning and audit tractable. But Cedar can fence off a single action; it cannot describe a sequence. The constraints teams want live in sequences: get approval before acting, stay under a running total, stop contacting external parties after touching confidential data. These rules are unenforceable at the policy layer today.
| Property | Cedar | Dogwood |
|---|---|---|
| Enforcement scope | Single request | Sequence of tool-call requests |
| State model | Stateless — same request, same answer always | Reads agent event history (tool calls, outcomes, arguments) |
| Policy clause | when | when + when temporal |
| Automated reasoning (formal analysis) | Supported | Not available for temporal conditions |
| Migration cost | — | Existing Cedar policies valid unchanged |
| Core semantics | Deny-by-default; forbid overrides permit | Unchanged from Cedar |
Dogwood adds a `when temporal` clause to Cedar's `when`. A temporal condition reads the agent's event history — tool call requests, outcomes, input arguments, requesting principal. The action schema matches the agent's MCP tool manifest, one action per tool. The interpreter translates the temporal condition into a Cedar context field populated from the event log. Four operators cover the practical surface: `formerly` (did something happen in a window), `count_within` (how many times), `count_distinct_within` (how many distinct values), and `sum_within` (running total). A `bind` operator assigns an aggregate a name for comparison against the current request.
| Operator | What it evaluates | Example use case |
|---|---|---|
| `formerly` | Did a specific event occur within a time window? | Was approval granted before this action? |
| `count_within` | How many times did an event occur in a window? | Has this tool been called more than N times? |
| `count_distinct_within` | How many distinct values appeared in a window? | How many unique external parties were contacted? |
| `sum_within` | Running total of a numeric field in a window | Total dollar amount of transfer requests so far |
| `bind` | Assigns an aggregate result a name for use in comparison | bind totalSpent = sum_within(...); totalSpent < 5000 |
The most instructive detail is a concurrency trap. A rate limit expressed as a sum over response events fails against parallel tool calls: three $2,000 transfers arrive before any settles, the policy summing responses sees nothing in flight, and all three clear a $5,000 cap. Summing request events instead denies the third. One word separates working from broken. In multi-agent settings where calls interleave, the exposure multiplies.
Temporal conditions carry two explicit costs. Evaluation time scales with the event log length, not just the current request. More significantly, temporal conditions forfeit Cedar's automated reasoning — a policy using `when temporal` cannot be formally analyzed for completeness or contradiction. AWS built a separate language rather than extending Cedar because the two properties are in tension. Existing Cedar policies remain valid Dogwood policies with no migration required. Deny-by-default and forbid-overrides-permit semantics are unchanged.
The production requirements AWS lists amount to building a trusted event log. Timestamps must be verified, events authenticated, field and action names consistent across the trace, tenant histories isolated, decisions logged with full context. Tool-call histories carry sensitive data; retention matters. The reference interpreter is not for production — AWS frames it as exploration and testing while the language stabilizes.
The release aligns with the MCP 2026-07-28 specification, which added required method and tool-name headers to make agent traffic legible to HTTP infrastructure. The two solve adjacent halves of the same problem: MCP headers let a gateway see which tool an agent calls; Dogwood expresses what a sequence of calls is allowed to total. Both are prerequisites for running named-tool agents inside a compliance boundary.
The architect's takeaway: stateful policy enforcement at the gateway layer is now available without custom work, but the correctness burden shifts from the policy engine to the event log. That log is your problem to build.