Cookbooks

Enforce: Policy Configuration

Author, dry-run, and deploy enforcement policies with Compose

Goal

Author an enforcement policy in Compose — describe it in plain language, review the Cedar it compiles to, dry-run it against real traffic, and deploy. By the end you'll be able to:

  • Compose a policy from plain language and read the Cedar it emits
  • Dry-run a policy before it touches a single request
  • Deploy with Authorize & deploy, leaning on Run dry test first since a Gateway deploy enables enforcement immediately
  • Reach for the right Cedar pattern for common scenarios

Prerequisites

Time Estimate

15 minutes


How policies work

A Checkpoint policy is a Cedar policy with an allow-by-default, carve-out posture: every deployed bundle starts by permitting all traffic, and each rule you add is a forbid that carves out a stricter verdict (BLOCK, CHALLENGE, REDIRECT, INSTRUCT) for the requests it matches. Cedar is forbid-overrides — when multiple rules match, the restriction wins. There's no priority list to maintain; you just write rules for the traffic you want to restrict. See the Policies reference for the full model.


Steps

Open Compose

  1. Log into your Checkpoint dashboard
  2. Select your project
  3. Go to Policy → Compose (/policy/compose)

Describe the rule in plain language

Type what you want in the composer and press ⌘⏎ to compile. For example:

Block unverified agents from checkout, but let Claude and ChatGPT browse the catalog.

Compose parses the intent, emits Cedar, and flags any assumptions it had to make so you can confirm them.

Review the Cedar

Compose shows the generated rules as editable sentence chips alongside the raw Cedar — what you see is what runs. The example above compiles to something like:

@id("block-unverified-on-checkout")
@verdict("BLOCK")
forbid ( principal, action, resource )
when { resource.path like "/checkout*" }
unless { principal.delegation == "verified"
         || principal.name == "Claude" || principal.name == "ChatGPT" };

Hand-edit the Cedar directly in the pane if you need to fine-tune it.

Run a dry test

Click Run dry test. Checkpoint replays the policy against representative agents (or your last 7 days of traffic) through the real engine — dry run · no traffic affected — and shows the verdict and the reason for each request. Confirm the rules do what you intended before deploying.

Deploy

Once you've reviewed the dry-run and confirmed Compose's assumptions, click Authorize & deploy. This enables enforcement immediately (there's no separate "observe" deploy for a Cedar policy), and the policy is enforcing on the gateway within about a minute, with the surface showing an ● Enforcing on the gateway badge.

Roll out safely by leaning on Run dry test before you deploy: it replays the policy against representative agents (or your last 7 days of traffic) through the real engine with no traffic affected, and reports the verdict and reason per request. Rehearse until the matched set looks right, then deploy.

If you enforce with a middleware SDK instead of the Gateway, you have a genuine observe mode there: set enforcementMode: 'observe' on withCheckpoint to classify and report every request without blocking any of it, then flip to 'enforce' once you're confident. See Enforce vs. observe.

Test the deployed policy

With the policy enforcing, verify the HTTP behavior with curl:

# An unverified agent hitting checkout — should be blocked
curl -I -H "User-Agent: Mozilla/5.0 (compatible; GPTBot/1.0)" \
  https://your-domain.com/checkout
# Expected: 403 Forbidden

# A normal visitor — should pass through
curl -I https://your-domain.com/
# Expected: 200 OK

Review decisions

Open the policy from the Policy list: its detail page's Decision log link jumps to this policy's filtered activity for the live allow / block / challenge log. Or use Dashboard Analytics for aggregate policy activity across the project.


Common patterns

Describe these in plain language in Compose; the Cedar below is what it emits. See the Policies reference for the full catalog, including the basic block/redirect patterns already shown in the Review the Cedar step above.

Require consent for an agent on a path — unless it already has the scopes ("Challenge ChatGPT on /account unless it has settings access"):

@id("challenge-chatgpt-on-account")
@verdict("CHALLENGE")
@scopes("settings:read settings:write")
forbid ( principal, action, resource )
when { (resource.path == "/account" || resource.path like "/account/*") && principal.name == "ChatGPT" }
unless { context.granted_scopes.contains("settings:read") && context.granted_scopes.contains("settings:write") };

Add an approval-quorum annotation for a sensitive action ("Require two approvers for transfers"; only enforced today by the MCP Gateway, and only for a rule it can match):

@verdict("CHALLENGE")
@quorum("2")
@approvers("did:web:acme:approvers:alice did:web:acme:approvers:bob")
forbid ( principal, action, resource )
when { resource.path == "/transfer" };

@quorum and @approvers are read by the MCP Gateway's approval-quorum step-up, which matches a request by its Cedar action / resource entity, not resource.path, so this resource.path-scoped rule never triggers it there. On the HTTP edge Gateway and the Next.js, Express, and .NET SDK middleware, the rule still fires as a plain CHALLENGE: the caller gets an ordinary consent/step-up challenge, not a verified 2-of-N approval. Scope the when { … } to the action/resource facts of the tool call you want to gate if you need real quorum enforcement.

Match a single agent with principal.name == "X"; match a set with an OR-disjunction (principal.name == "X" || principal.name == "Y"). Cedar's in operator is for entity hierarchies, not string sets.


Best practices

  • Dry-run before you deploy. Authorize & deploy enables enforcement immediately on the Gateway (there's no separate observe deploy there), so lean on Run dry test against representative agents or real traffic until the verdicts look right. Deploying via a middleware SDK, use enforcementMode: 'observe' for a genuine staged rollout.
  • Dry-run every change. Run the dry test before each deploy — it replays against the real engine with no traffic affected.
  • Redeploy to apply edits. Saving a draft (or editing on the detail page) doesn't change what's live — the gateway keeps enforcing the last deployed version until you Authorize & deploy again.
  • Keep rules targeted. Because policies are allow-by-default, write narrow forbid rules for exactly the traffic you want to restrict rather than broad ones you then have to carve exceptions out of.
  • Exempt verified agents with an unless { principal.delegation == "verified" } carve-out so agents that prove identity aren't caught by a restriction.

Troubleshooting

SymptomCauseFix
Changes aren't taking effectSaved as a draft but not redeployedAuthorize & deploy — a draft doesn't change the live policy
Still enforcing the old rulesThe gateway caches the deployed policy (~1 min)Wait a minute, or purge the cache from the policy detail page
Everything is being blockedA forbid rule is too broadNarrow the when {…} conditions; remember traffic is allowed by default
Wrong verdict on a requestA different rule matched (forbid-overrides)Run dry test — it shows which rule matched and why
A verified agent is blockedNo delegation carve-outAdd unless { principal.delegation == "verified" }

What You Learned

  • How to author a policy in Compose from plain language and review the Cedar it emits
  • How to dry-run a policy against real traffic before deploying
  • How to roll out safely with dry-run before deploying (and with enforcementMode: 'observe' on middleware SDKs)
  • Common Cedar patterns for real-world enforcement

Next Steps

GoalAction
Set up detection firstGateway or Middleware
Authorize AI agentsGovern Overview
Monitor trafficDashboard Analytics