> ## Documentation Index
> Fetch the complete documentation index at: https://docs.roark.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> Define your Roark agents, personas, flows, metrics, collectors, and alerts as YAML in git and deploy them with one apply

Config as Code lets you define your Roark resources - agents, personas, simulation flows, custom metrics, collectors, and alerts - as YAML files in your own git repository, then deploy them with a single apply. Your config repo is the source of truth: Roark reconciles the live project to match what you submitted, creating what's new, updating what changed, and removing what you deleted.

## Quickstart

Put each resource in a YAML file under a directory, then apply. Install the [CLI](/documentation/sdks/cli) and set `ROARK_API_BEARER_TOKEN` first (the key needs `config:apply`).

```yaml roark/agents/frontdesk.yaml theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
kind: agent
name: frontdesk
```

```bash theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
roark config diff ./roark    # preview the changes
roark config apply ./roark   # apply them
```

That's the whole loop. Add personas, flows, metrics, collectors, and alerts the same way; each kind has its own reference page below.

***

<Note>
  Config as Code manages **resource definitions**. It does not run simulations or place calls; you trigger those as usual once the resources exist (see [CI/CD](/documentation/simulation-testing/ci-cd) to apply config and start a run in one pipeline).
</Note>

You write only a human-readable `name` for each resource. Roark derives a stable identity (`configKey = <kind>/<name>`) and resolves cross-references by name, so there are no UUIDs in your files and no state file to keep in sync.

<Card title="Use the Roark CLI" icon="square-terminal" href="/documentation/sdks/cli">
  The easiest way to run Config as Code. `roark config diff ./roark` and `roark config apply ./roark` bundle your directory (resolving `file://` prompts) and submit it for you. See the CLI page for install, auth, and a CI example.
</Card>

***

## How it works

You submit the full desired set of resources to a single endpoint. Roark:

1. **Parses and validates** every resource against the schema.
2. **Diffs** the submitted set against the resources this project already manages via config.
3. **Reconciles**: creates new resources, updates changed ones, and (unless you opt out) deletes config-managed resources you removed from the submission.

There are two endpoints:

| Endpoint                | What it does                                                      |
| :---------------------- | :---------------------------------------------------------------- |
| `POST /v1/config/diff`  | **Dry run.** Returns the changes that *would* be made. No writes. |
| `POST /v1/config/apply` | **Applies** the changes and returns what happened.                |

Always run `diff` first to preview the changes, then `apply`.

***

## Prerequisites

* A Roark API key with the **`config:apply`** permission. Generate one from [API Keys](/documentation/getting-started/api-keys) and confirm it carries `config:apply`.
* A git repository to hold your config files (any layout; Roark reads the files you submit).
* The **Roark CLI** (recommended): `npm install -g @roarkanalytics/cli`, or run it on demand with `npx @roarkanalytics/cli`. The CLI builds the bundle from your config directory and drives `diff`/`apply` for you, so it's the easiest way to deploy. Raw HTTP and the SDKs work too.

<Note>
  The API key is scoped to a single project. Everything you apply lands in that project.
</Note>

***

## Repository layout

One file per resource, discriminated by `kind`. A conventional layout:

```
roark/
  agents/frontdesk.yaml
  personas/frustrated-caller.yaml
  flows/frustrated-rebooking.yaml     # improv flow
  flows/booking-scripted.yaml         # scripted-graph flow
  metrics/refund-policy-accuracy.yaml
  collectors/consent-on-frontdesk.yaml
  alerts/high-frustration.yaml        # threshold / event / simulation alert
  prompts/escalates-to-manager.md     # referenced by file://
```

Add this header to any resource file for editor autocomplete and validation:

```yaml theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
# yaml-language-server: $schema=https://roark.ai/roark-config.schema.json
```

***

## Resource kinds

One file per resource, discriminated by `kind`. Each kind has its own reference page with fields and examples:

<CardGroup cols={2}>
  <Card title="Agents" icon="headset" href="/documentation/config-as-code/agents">
    Voice agents and their phone endpoints.
  </Card>

  <Card title="Personas" icon="user" href="/documentation/config-as-code/personas">
    The simulated caller for a flow.
  </Card>

  <Card title="Flows" icon="waypoints" href="/documentation/config-as-code/flows">
    Simulation flows: improvised or scripted graphs.
  </Card>

  <Card title="Metrics" icon="ruler" href="/documentation/config-as-code/metrics">
    Custom LLM-judged metric definitions.
  </Card>

  <Card title="Collectors" icon="list-checks" href="/documentation/config-as-code/collectors">
    Which metrics get collected on which conversations.
  </Card>

  <Card title="Simulation plans" icon="flask-conical" href="/documentation/config-as-code/simulation-plans">
    Saved, repeatable simulation runs: agents, flows and the metrics that grade them.
  </Card>

  <Card title="Alerts" icon="bell" href="/documentation/config-as-code/alerts">
    Alerts (monitors): threshold, event, and simulation triggers.
  </Card>
</CardGroup>

<Note>
  For the full field reference of every kind, see the [Config DSL reference](https://roark.ai/roark-config.schema.json) schema.
</Note>

***

## Deploying

The easiest way to deploy is the **Roark CLI**. Point it at your config directory and it builds the bundle for you (reading every YAML file and inlining `file://` prompts), so there is no JSON body to assemble by hand.

<Tip>
  The [CLI](/documentation/sdks/cli) does the bundling for you: `roark config diff ./roark` and `roark config apply ./roark` take the directory directly, resolve `file://` prompt references, and submit the result. The raw requests below are what it sends.
</Tip>

<Steps>
  <Step title="Authenticate">
    Give the CLI the project API key that carries `config:apply`:

    ```bash theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    export ROARK_API_BEARER_TOKEN="<your-config-apply-key>"
    # or store it once: roark auth login
    ```
  </Step>

  <Step title="Preview the changes">
    ```bash theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    roark config diff ./roark
    ```

    The CLI reads every resource under `./roark`, builds the bundle, and prints one line per change (`+` create, `~` update, `-` delete) with a tally:

    ```text theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
      + collector/consent-on-frontdesk
      ~ agent/frontdesk

    1 to create, 1 to update, 0 to delete
    ```

    Resources already in sync are no-ops and aren't listed, so a project that fully matches your config prints `0 to create, 0 to update, 0 to delete`.
  </Step>

  <Step title="Apply">
    ```bash theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    roark config apply ./roark
    ```

    `apply` previews the same diff, asks you to confirm, then reconciles and reports what it did. Pass `--yes` to skip the prompt in CI, and `--no-prune` for an additive-only apply that never deletes.
  </Step>
</Steps>

### Using raw HTTP

If you'd rather call the API directly, bundle your resources into a single JSON body: `{ "resources": [...], "prune": true }`, where each entry is one resource in the same shape as its YAML. `POST` it to `/v1/config/diff` first, then `/v1/config/apply`.

```bash theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
curl -X POST https://api.roark.ai/v1/config/diff \
  -H "Authorization: Bearer $ROARK_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @bundle.json
```

The response lists each projected change with an `op` (`create`, `update`, or `delete`) plus a summary; in-sync resources are counted in `summary.noop` and omitted from `changes`:

```json theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
{
  "data": {
    "changes": [
      { "configKey": "collector/consent-on-frontdesk", "kind": "collector", "name": "consent-on-frontdesk", "op": "create" }
    ],
    "summary": { "create": 1, "update": 0, "delete": 0, "noop": 0 }
  }
}
```

`apply` takes the same body against `/v1/config/apply`; each change comes back with a `status` (`applied` or `failed`) and, on success, the resource `id`.

<Note>
  These endpoints are available in the [Node.js](/documentation/sdks/node-sdk) and [Python](/documentation/sdks/python-sdk) SDKs as `config.diff` and `config.apply`, taking the same bundle, and in the [CLI](/documentation/sdks/cli) as `roark config diff` and `roark config apply`, taking a directory.
</Note>

***

## Apply semantics

* **Identity is by name.** Re-submitting an unchanged resource updates it in place; it never creates a duplicate. Renaming a resource is a delete of the old name plus a create of the new one.
* **Cross-references resolve by name** within the same submission (a flow's `agents:`/`persona:`, a collector's `AGENT` filter). The referenced resource must be in the bundle or already config-managed in the project.
* **Prune deletes what you removed.** By default, config-managed resources absent from the submission are deleted so the project matches your repo exactly. To layer additive changes without deleting, send `"prune": false`.
* **Prompts are code.** Any prompt field takes an inline string or `file://relative/path.md`, resolved relative to your config root and inlined before you submit.
* **Idempotent.** Applying the same bundle twice converges to the same state. An unchanged resource is a no-op on the next `diff`/`apply`, not a rewrite, so a re-run of an in-sync project reports no changes.

<Warning>
  With `prune` enabled (the default), a resource you delete from your repo is deleted from Roark on the next apply. Submit the **full** desired set every time, or use `"prune": false` for additive-only applies.
</Warning>

***

## Config-managed resources in the UI

A resource created by config is **read-only in the dashboard** and carries a "managed by config" badge. To change it, edit your config and re-apply.

If you need to hand a resource back to manual UI editing, **detach** it (from the resource's menu in the dashboard). Detaching clears its config ownership:

* A later apply that still lists it will re-adopt it.
* A later apply that omits it will simply leave it alone (it is no longer config-managed, so prune won't touch it).

***

## Recommended workflow

1. Keep your `roark/` config in a git repo, reviewed via pull requests.
2. In CI, run `roark config diff ./roark` on every PR and post the output for review.
3. On merge to your main branch, run `roark config apply ./roark --yes`.

Both CI steps read the API key from `ROARK_API_BEARER_TOKEN` (store it as a secret with `config:apply`). This gives you versioned, reviewable, reproducible Roark resources with a full audit trail in git.

For a copy-pasteable GitHub Actions workflow that does exactly this, see [Using the CLI in CI](/documentation/sdks/cli#using-the-cli-in-ci).
