---
title: "Iterate Policy Safely"
url: "https://docs.caracal.run/v1.0/examples/policy-iterate/"
markdown_url: "https://docs.caracal.run/markdown/v1.0/examples/policy-iterate.md"
description: "Diagnose a denied request, simulate a candidate policy-set version, regression-check expected decisions, and activate only when every gate passes."
page_type: "workflow"
concepts: []
requires: []
---

# Iterate Policy Safely

Canonical URL: https://docs.caracal.run/v1.0/examples/policy-iterate/
Markdown URL: https://docs.caracal.run/markdown/v1.0/examples/policy-iterate.md
Description: Diagnose a denied request, simulate a candidate policy-set version, regression-check expected decisions, and activate only when every gate passes.
Page type: workflow
Concepts: none
Requires: none

---

Policy Iterate is an audit-driven policy rollout loop in the [Caracal examples repository](https://github.com/Garudex-Labs/examples) under `policyIterate/`. It tests a candidate policy change against the exact redaction-safe audit input of a real denial - and proves the change does not alter other decisions - before activation.

## When to use it

Use it when a real request was denied and the fix must be proven safe before rollout: the candidate has to repair that denial and keep every regression case's decision. Do not use it as a substitute for the [policy authoring contract](/v1.0/guides/author-policy/) or [activation workflow](/v1.0/guides/activate-policy-set/); it automates their verification loop.

## Prerequisites

* A denied request ID with an explainable audit trace.
* A staged immutable policy-set version and current active version recorded for rollback.
* Regression cases covering nearby allow and deny behavior.

## Loop

1. **Diagnose** - a request is denied and you capture its audit `request_id`. The audit explain endpoint reconstructs the denied `policy_input` along with the diagnostics and determining policies.
2. **Simulate** - you edit the policy data, stage a candidate policy-set version, and the example replays the denied input against it through the same policy engine that serves live traffic.
3. **Regress** - the example replays your expected-decision cases against the same candidate, so loosening a policy for one caller cannot silently change decisions for everyone else.
4. **Decide** - activation is gated on evidence: the candidate allows the denied input, the rollout contract validates, simulation produced no warnings, and every regression case keeps its expected decision.
5. **Activate** - with `ACTIVATE=true` and a clean verdict, the example activates the version and polls activation status until the STS runtime reports it loaded.

## Run the iteration

```bash
git clone https://github.com/Garudex-Labs/examples.git caracal-examples
cd caracal-examples/policyIterate
CARACAL_API_URL=http://127.0.0.1:3000 \
CARACAL_ADMIN_TOKEN=<admin-token> \
CARACAL_ZONE_ID=<zone-id> \
DENIED_REQUEST_ID=<denied-request-id> \
POLICY_SET_ID=<policy-set-id> \
CANDIDATE_VERSION_ID=<staged-version-id> \
REGRESSION_FILE=./regressions.json \
npm run iterate
```

The run is a dry run by default: it narrates each phase on stderr, prints a JSON report on stdout, and exits `0` only when the verdict is clean. Re-run with `ACTIVATE=true` to roll out the version and wait for propagation.

`REGRESSION_FILE` is optional and points to a JSON array of `{ name, expect, input }` cases - see `regressions.example.json` in the example directory for the format.

## Claims note

Actor and subject claims are not written to audit, so reconstructed input does not contain them. For a claim-dependent denial, add the relevant `context.actor_claims` to a regression case built from the printed `policyInput` and iterate with that case instead.

## Test

```bash
cd caracal-examples/policyIterate
npm test
```

The tests inject the Admin API transport and do not call a live Caracal stack.

## Validate the iteration

Keep `ACTIVATE` unset first. Expect the candidate to repair the target denial while every regression retains its decision. Only then activate and wait for `loaded`; verify the first real exchange names the candidate manifest.

:::caution[Failure point: reconstructed input]
Audit reconstruction is redaction-safe and omits actor/subject claims. If a decision depends on implemented federated claims, supply them explicitly in a reviewed regression case; never guess them from a display name.
:::

## Next Step

Continue to [Launch Research Agent](/v1.0/examples/research-agent/) to see runtime credential injection for a plain CLI agent.
