> For the complete documentation index, see [llms.txt](https://docs.kyvvu.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kyvvu.com/deployment/configuration.md).

# Configuration Reference

**What you'll learn:** All environment variables for the SDK, engine, and platform API.

***

## SDK / Engine configuration

Precedence (highest to lowest): explicit kwargs > environment variables > `.env` in cwd > built-in defaults.

### Authentication and identity

| Env var          | Default                      | Description                                                                             |
| ---------------- | ---------------------------- | --------------------------------------------------------------------------------------- |
| `KV_API_URL`     | `https://platform.kyvvu.com` | Base URL of the Kyvvu platform API.                                                     |
| `KV_API_KEY`     | --                           | Bearer API key (`KvKey-...`). Required for policy fetch.                                |
| `KV_AGENT_KEY`   | --                           | Stable agent identifier used to fetch policies.                                         |
| `KV_INSTANCE_ID` | auto-generated               | Identifier for this runner instance. A random suffix is appended to prevent collisions. |

### Log output

| Env var                | Default                         | Description                                                                                                                                       |
| ---------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `KV_LOG_LOCATION`      | `stdout`                        | WHERE logs go. URL → HTTP POST, file path → JSONL, `stdout` → terminal, `none`/empty → disabled.                                                  |
| `KV_LOG_FORMAT`        | `kv`                            | HOW logs are formatted: `kv` (Kyvvu batch API), `json`, or `otlp`.                                                                                |
| `KV_INCIDENT_LOCATION` | unset (inherit trace sink)      | WHERE incidents go. Same vocabulary as `KV_LOG_LOCATION`. Unset inherits the trace sink, using the `…/api/v1/incidents` path for the `kv` format. |
| `KV_INCIDENT_FORMAT`   | unset (inherit `KV_LOG_FORMAT`) | HOW incidents are formatted: `kv`, `json`, or `otlp` (a standalone `kyvvu.incident` span).                                                        |

### Behaviour

| Env var                | Default      | Description                                                                                     |
| ---------------------- | ------------ | ----------------------------------------------------------------------------------------------- |
| `KV_ENVIRONMENT`       | `production` | Forwarded to `EvalContext.environment`.                                                         |
| `KV_LOG_PAYLOADS`      | `full`       | `full` includes step input/output in logs. `metadata_only` redacts content but preserves shape. |
| `KV_TEMPLATE_LOCATION` | built-in     | Path to a custom YAML behaviour template.                                                       |

### Cache and limits

| Env var                     | Default | Description                                                                                                     |
| --------------------------- | ------- | --------------------------------------------------------------------------------------------------------------- |
| `KV_POLICY_TTL_SECONDS`     | `300`   | How long to cache fetched policies (seconds).                                                                   |
| `KV_HTTP_TIMEOUT_SECONDS`   | `10`    | Per-request HTTP timeout.                                                                                       |
| `KV_TASK_MAX_AGE_SECONDS`   | `3600`  | Abandoned-task eviction threshold for `sweep_stale_tasks()`.                                                    |
| `KV_SWEEP_ENABLED`          | `true`  | Whether the background sweeper thread starts automatically. Set `false` to call `sweep_stale_tasks()` manually. |
| `KV_SWEEP_INTERVAL_SECONDS` | `300`   | How often the background sweeper runs (seconds).                                                                |
| `KV_SWEEP_FLUSH_ON_EVICT`   | `true`  | Whether to attempt a batch log post for evicted tasks before discarding their buffers.                          |

### Resilience (opt-in)

| Env var                           | Default          | Description                                                                                                                                                                            |
| --------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `KV_POLICY_FAIL_MODE`             | `open`           | `open` = allow all when no policies loaded. `closed` = block all `step_execution` behaviors when no policies are available.                                                            |
| `KV_POLICY_CACHE_PATH`            | empty (disabled) | File path for on-disk policy cache. Written after each successful fetch; loaded on cold start if the API is unreachable.                                                               |
| `KV_POLICY_CACHE_MAX_AGE_SECONDS` | `86400`          | Maximum age (seconds) of the disk cache before a staleness warning is emitted. The cache is still used when stale.                                                                     |
| `KV_POLICY_HMAC_SECRET`           | empty (disabled) | Shared secret for HMAC-SHA256 verification of policy fetch responses. Must be set on both the engine and API for signing to activate.                                                  |
| `KV_REGISTRATION_TTL`             | empty (infinite) | How long a cached agent registration is valid before re-registering. Accepts `30m`, `24h`, `7d`, or raw seconds. Empty = cache never expires (re-registration only on payload change). |

### Logging

| Env var        | Default | Description                                                                                      |
| -------------- | ------- | ------------------------------------------------------------------------------------------------ |
| `KV_LOG_LEVEL` | `INFO`  | Log level for `kyvvu` / `kyvvu_engine` Python loggers. Set to `DEBUG` for per-evaluation traces. |

***

## Policy-bundle integrity (HMAC)

`KV_POLICY_HMAC_SECRET` adds integrity and authenticity protection to the policy-distribution channel. When set, the API signs every policy-fetch response with HMAC-SHA256 (header `X-Kyvvu-Policy-Signature`, computed over the JSON body) and the engine verifies that signature before trusting the policies. It is defense-in-depth on top of TLS: TLS protects the connection, while the HMAC binds each policy bundle to a shared secret that a passive proxy or compromised intermediary cannot forge.

Set `KV_POLICY_HMAC_SECRET` to the **same value** on the API and on every verifying engine. Generate a secret with:

```bash
python3 -c "import secrets; print(secrets.token_urlsafe(48))"
```

### Rollout order

1. **Set the API first.** Engines that do not yet have the secret simply skip verification, so enabling it on the API is non-breaking.
2. **Then set the engines.** Each engine begins verifying once the secret is present on both sides.

An engine configured with a **mismatched** secret rejects every fetch and keeps serving its previously cached policies. On a cold start with no cache, an engine running `KV_POLICY_FAIL_MODE=closed` blocks all `step_execution` behaviors until the secret is aligned.

### Rotation caveat

With a single shared secret, rotation is **not** zero-downtime. During rotation the API and the engines briefly hold different secrets; fetches are rejected and policies stop updating (the last cached bundle is still enforced) until both sides are aligned again. Plan rotations for a window where a short policy-update pause is acceptable.

### Scope caveat

This is a **self-hosted / full-stack** feature: a single shared secret is only appropriate when one operator controls both the API and the engine. It is not intended for hosted / multi-tenant verification. Per-API-key / asymmetric scoping for multi-tenant deployments is tracked in issue #278.

***

## Email (password reset)

Password reset emails are sent via SMTP. In development, no SMTP configuration is needed — the reset URL is logged to the API console instead.

| Env var            | Default                 | Description                                                                 |
| ------------------ | ----------------------- | --------------------------------------------------------------------------- |
| `KV_SMTP_HOST`     | empty                   | SMTP server hostname. When empty, reset URLs are logged instead of emailed. |
| `KV_SMTP_PORT`     | `587`                   | SMTP server port (TLS).                                                     |
| `KV_SMTP_USER`     | empty                   | SMTP authentication username.                                               |
| `KV_SMTP_PASSWORD` | empty                   | SMTP authentication password.                                               |
| `KV_SMTP_FROM`     | `noreply@kyvvu.com`     | Sender email address.                                                       |
| `KV_WEB_URL`       | `http://localhost:3000` | Dashboard URL used in reset email links.                                    |

### Production setup (AWS SES)

SES is provisioned via Terraform:

```bash
cd infra/terraform
terraform apply          # creates SES domain, DKIM, SMTP user
terraform output ses_smtp_password   # copy this (sensitive)
terraform output ses_smtp_username   # copy this
```

Then set in the EC2 `.env` file:

```bash
KV_SMTP_HOST=email-smtp.eu-central-1.amazonaws.com
KV_SMTP_PORT=587
KV_SMTP_USER=<ses_smtp_username output>
KV_SMTP_PASSWORD=<ses_smtp_password output>
KV_SMTP_FROM=noreply@kyvvu.com
KV_WEB_URL=https://platform.kyvvu.com
```

Note: New SES accounts start in sandbox mode. Request production access via AWS Console → SES → Account dashboard.

***

## Next steps

* [Self-Hosted Setup](https://github.com/Kyvvu/platform/tree/main/docs/deployment/self-hosted.md) — deployment guide
* [Architecture](/core-concepts/architecture.md) — how components use these settings


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kyvvu.com/deployment/configuration.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
