---
title: "Bootstrap Control State"
url: "https://docs.caracal.run/examples/control-bootstrap/"
markdown_url: "https://docs.caracal.run/markdown/examples/control-bootstrap.md"
description: "Keep an agent environment in sync with a declared plan through a scoped Control API automation key."
page_type: "workflow"
concepts: []
requires: []
---

# Bootstrap Control State

Canonical URL: https://docs.caracal.run/examples/control-bootstrap/
Markdown URL: https://docs.caracal.run/markdown/examples/control-bootstrap.md
Description: Keep an agent environment in sync with a declared plan through a scoped Control API automation key.
Page type: workflow
Concepts: none
Requires: none

---

Control Bootstrap is the canonical Control API automation example under `examples/controlBootstrap`. A small CI/CD-style pipeline keeps one agent's environment — application, provider, resource, and policy — matching a declared plan, without adding product-management verbs to the runtime CLI.

## What it demonstrates

| Area | Behavior |
| --- | --- |
| Automation surface | Calls `/v1/control/invoke` instead of using a root admin token. |
| Identity model | Uses scoped, short-lived control keys created in Console, one scope tier per pipeline stage. |
| Reconciliation | `apply` creates missing objects, patches drifted ones, and publishes a new policy version on content drift. |
| CI gating | `verify` is a read-only drift check that exits non-zero when the zone does not match the plan. |
| Safety model | Uses replay protection, rate limits, scoped control permissions, and audit. |

The plan describes the PiperNet reporter agent's environment: the agent application, the `provider://pipernet-mandate` provider, the `resource://pipernet` resource wired to it, and the baseline policy that allows `read`.

## Console setup

1. Start the runtime and open Console:

   ```bash
   caracal up
   caracal status --ready
   caracal console
   ```

2. Create or select the target zone.
3. Create a control key with only the scopes the stage needs: read/write on app, provider, resource, and policy for `apply`; read for `verify`; read/delete for `teardown`.
4. Save the one-time `client_id` and `client_secret`. STS resolves the zone from the bound control key.

## Run the pipeline

```bash
cd examples/controlBootstrap
cp env.example .env
$EDITOR .env
. .env
npm run apply
npm run verify
```

`apply` is idempotent: rerunning it against an in-sync zone changes nothing, and rerunning it against a drifted zone converges the drift. Run teardown when you want to remove the environment:

```bash
npm run teardown
```

## Files to study

| File | Purpose |
| --- | --- |
| `controlClient.mjs` | Exchanges client credentials at STS and calls the Control API. |
| `plan.mjs` | Declares the desired environment, drift checks, scope tiers, and env-driven config. |
| `apply.mjs` | Reconciles the live zone with the plan. |
| `verify.mjs` | Read-only drift gate for CI. |
| `teardown.mjs` | Removes the environment in reverse dependency order. |

## Test

```bash
cd examples/controlBootstrap
npm test
```

The tests use a fake zone and mock transport and do not call a live Caracal stack.

## Next step

Continue to [Check Provider Readiness](/examples/provider-preflight/) before sending traffic through a provider-backed Gateway resource.
