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

# Variables & Secrets

> Parameterize runbooks with variables, secrets, and template syntax.

## Overview

Variables make runbooks reusable. Define them once, and reference them in step values with `{{variableName}}` syntax. Values can come from interactive prompts, environment variables, context files, secrets, or static values.

## Variable sources

Variables are defined in the runbook with a `source` that determines how their value is resolved:

| Source       | Description                                    | Example use case                       |
| ------------ | ---------------------------------------------- | -------------------------------------- |
| `prompt`     | Asks the user at execution time (CLI only)     | Login credentials, one-time values     |
| `fixed`      | Hardcoded static value                         | Base URLs, constants                   |
| `context`    | AI extracts from the `--context` markdown file | Values described in documentation      |
| `env`        | Read from an environment variable              | `AWS_REGION`, `APP_URL`                |
| `expression` | Evaluate a template expression                 | `{{Date.now()}}`, computed values      |
| `data`       | Read from a data file                          | Row-specific values in batch workflows |

### Examples

```yaml theme={null}
variables:
  email:
    source: prompt
    description: "Login email address"
    required: true
  baseUrl:
    source: fixed
    value: "https://staging.example.com"
  region:
    source: env
    envKey: "AWS_REGION"
  timestamp:
    source: expression
    expression: "{{Date.now()}}"
  appName:
    source: context
    description: "Application name from context"
```

## Resolution priority

At execution time, variables are resolved in this order. The first match wins:

| Priority | Source         | Description                                          |
| :------: | -------------- | ---------------------------------------------------- |
|     1    | **secrets**    | Values from `--secrets` flag or SDK `secrets` option |
|     2    | **data**       | Values from data files                               |
|     3    | **context**    | AI extraction from `--context` markdown              |
|     4    | **env**        | Environment variables                                |
|     5    | **expression** | Template expression evaluation                       |
|     6    | **fixed**      | Static value from the definition                     |
|     7    | **prompt**     | Interactive prompt (CLI only)                        |

This means secrets always take precedence. If you pass a value via `--secrets`, it overrides any other source.

## Secrets handling

Secrets are sensitive values that should never appear in logs or reports. There are two ways to provide them:

### Via `--secrets` flag

Create a JSON file with key-value pairs:

```json theme={null}
{
  "password": "s3cret!",
  "apiToken": "tok_abc123"
}
```

```bash theme={null}
npx @refrainai/cli execute -- \
  --runbook ./flow.yaml \
  --secrets ./secrets.json
```

All values in the secrets file are automatically treated as sensitive and masked in all output.

### Via `sensitive: true` flag

Mark individual variables as sensitive in the runbook:

```yaml theme={null}
variables:
  password:
    source: prompt
    description: "Login password"
    sensitive: true
```

## Context-based resolution

When a variable has `source: context`, AI reads the `--context` markdown file and extracts the value based on the variable's description. This is useful when values are documented but not hardcoded:

```yaml theme={null}
variables:
  adminUrl:
    source: context
    description: "Admin dashboard URL"
```

```markdown theme={null}
# App context

The admin dashboard is at https://admin.example.com/dashboard
```

AI will resolve `adminUrl` to `https://admin.example.com/dashboard`.

## Template syntax

Reference variables in any string field using double curly braces:

```yaml theme={null}
steps:
  - ordinal: 0
    description: "Navigate to {{baseUrl}}"
    action:
      type: navigate
      url: "{{baseUrl}}/login"
  - ordinal: 1
    description: "Enter email"
    action:
      type: input
      value: "{{email}}"
      selector:
        role: textbox
        ariaLabel: "Email"
```

Templates support:

* Simple references: `{{variableName}}`
* Dot notation for captured objects: `{{captured.field}}`
* Nesting up to 3 levels deep

## Best practices

* **Use `prompt` for credentials** — Never hardcode passwords in runbooks
* **Use `env` for environment-specific values** — Base URLs, API endpoints, regions
* **Use `context` for documented values** — Keep `context.md` as the source of truth
* **Mark sensitive values** — Use `sensitive: true` or `--secrets` to ensure masking
* **Keep secrets out of version control** — Add `secrets.json` to `.gitignore`

## What's next

<CardGroup cols={2}>
  <Card title="YAML Variables reference" icon="code" href="/yaml/variables">
    Full variable schema and field reference.
  </Card>

  <Card title="Execute a runbook" icon="play" href="/guides/execute-runbook">
    Use variables in runbook execution.
  </Card>
</CardGroup>
