---
title: "Viper Configuration"
description: "Find where Viper keeps its settings and keys, change its settings, and override them with environment variables."
source: "Guardian Platform"
---
Viper writes its configuration the first time you run it, and most users never edit it by hand: `viper did add` and `viper did assign` keep it up to date. This page covers what is in it, when you would change it, and how to set it from the environment on servers and in containers.

## Where configuration lives

Viper keeps everything in `~/.config/viper/`:

| Path          | Contents                                                              |
| ------------- | --------------------------------------------------------------------- |
| `config.toml` | Your settings: gateway address, key assignments, captured variables   |
| `keys/`       | Signing keys, readable only by your user account                      |
| `vcs/`        | Credentials the Guardian Platform issued when you registered each key |
| `blobs/`      | Local copies of the configuration records Viper attaches to requests  |
| `logs/`       | One log file per Viper session                                        |
| `mitm/`       | The local root certificate used by `--egress-capture`                 |

To use a different file, set `VIPER_CONFIG` or pass `--config <path>` to any command. Keys, logs, and the other directories then live beside that file.

## Settings in config.toml

```toml
llm_gateway_api_url = "https://gateway.example.com/v1"
# Replaces the default list, so keep the sandbox variables if you add your own.
env_vars = [
  "DAYTONA_SANDBOX_SNAPSHOT",
  "DAYTONA_SANDBOX_ID",
  "DAYTONA_ORGANIZATION_ID",
  "E2B_SANDBOX",
  "E2B_TEMPLATE_ID",
  "E2B_SANDBOX_ID",
  "OPENSHELL_SANDBOX",
  "CI_PIPELINE_ID",
]

[default_dids]
claude = "did:key:z6Mk..."
codex = "did:key:z6Mk..."

[agents.support-bot]
did = "did:key:z6Mk..."
agent_id = "urn:uuid:..."
project_urn = "urn:uuid:..."
```

| Setting               | What it does                                                                                                                                                                                   |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `llm_gateway_api_url` | The gateway address Viper sends signed requests to. If you give only a host, Viper assumes `/v1`.                                                                                              |
| `guardian_url`        | No longer used. Earlier versions pointed browser sign-in at Guardian; registration now needs a token or API key. The first-run prompt still writes it, and you can delete it.                  |
| `[default_dids]`      | Which key each app signs with, one entry per app (`claude`, `codex`, `opencode`, `openclaw`, `proxy`). Each app must use a different key. Prefer `viper did assign` over editing this by hand. |
| `[agents.<name>]`     | Each named agent's key, its `agent_id` once registered, and a `project_urn` if it is in several projects. Prefer `viper agent add`, `register` and `project` over editing these by hand.       |
| `env_vars`            | Names of environment variables to record with each request. Only variables that are actually set are recorded. If you omit this setting, Viper uses the sandbox list below.                    |

<Alert variant="warning" title="Caution">
  Values captured through `env_vars` are recorded exactly as they appear and kept in the Guardian
  Platform's audit data. Never list a variable that holds a secret.
</Alert>

Setting `env_vars` replaces the default list. If you add your own names and still want sandbox provenance, include the sandbox variables too.

## Environment overrides

Environment variables take precedence over `config.toml` every time Viper starts.

| Variable                   | Effect                                                                                                                                                                       |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `VIPER_CONFIG`             | Path to the configuration file to use instead of `~/.config/viper/config.toml`.                                                                                              |
| `VIPER_GATEWAY_URL`        | Overrides `llm_gateway_api_url`. If no configuration file exists yet, Viper creates one from this value instead of prompting.                                                |
| `GUARDIAN_API_KEY`         | An `ak_...` API key used by `viper did register` and `viper agent register` for headless enrollment. Keep it out of `config.toml`.                                           |
| `VIPER_PROVISIONING_TOKEN` | A `ggr1.` registration token used by `viper did register` and `viper agent register`, in place of `--provisioning-token`.                                                    |
| `VIPER_AGENT_ID`           | An existing agent ID for `viper did register` or `viper agent register` to join with an API key, in place of `--agent-id`. Each replica of the agent adds its own key to it. |
| `VIPER_PROJECT_URN`        | The project for `viper agent register` to save under the agent, in place of `--project-urn`. Only an agent in more than one project needs it.                                |
| `VIPER_YUBIKEY_PIN`        | The PIN for a YubiKey-backed key. `viper did add` and `viper agent add` require it; when signing without it, Viper asks for the PIN in the terminal.                         |
| `VIPER_GUARDIAN_URL`       | No longer used, like `guardian_url`. Viper still checks that it is a valid URL, so unset it rather than leaving a bad value.                                                 |

In CI and containers, setting `VIPER_GATEWAY_URL` is usually all the configuration you need, apart from the keys themselves.

## Sandbox provenance (Daytona, E2B and OpenShell)

When your agent runs inside a Daytona, E2B or OpenShell sandbox, Viper records the sandbox's identifying variables with every request. The Guardian Platform stores them with the exchange, and gateway policies can use them, for example to allow requests only from a known sandbox template.

| Variable                   | Sandbox   | Meaning                                                            |
| -------------------------- | --------- | ------------------------------------------------------------------ |
| `DAYTONA_SANDBOX_SNAPSHOT` | Daytona   | Snapshot the sandbox was started from                              |
| `DAYTONA_SANDBOX_ID`       | Daytona   | Sandbox instance                                                   |
| `DAYTONA_ORGANIZATION_ID`  | Daytona   | Daytona organization that owns the sandbox                         |
| `E2B_SANDBOX`              | E2B       | Sandbox indicator set by the runtime                               |
| `E2B_TEMPLATE_ID`          | E2B       | Template the sandbox was created from                              |
| `E2B_SANDBOX_ID`           | E2B       | Sandbox instance                                                   |
| `OPENSHELL_SANDBOX`        | OpenShell | Sandbox indicator set by the runtime; OpenShell sets no sandbox ID |

<Alert variant="warning" title="Caution">
  These values are claims, not proof. They are ordinary environment variables, so anyone can set
  them outside a sandbox and appear sandboxed. No sandbox runtime vouches for them. Treat them as
  useful context for audit and policy, not as evidence that a request really came from a sandbox.
</Alert>

## Project credentials

Once an agent is associated with a project in the **Agent Catalog**, the gateway can usually find its project membership on its own. A named agent that belongs to more than one project has to say which project its requests are for. Name the project when you register the agent, or set or clear it later without registering again:

```bash
GUARDIAN_API_KEY=ak_… viper agent register support-bot --project-urn urn:uuid:7f0e6f3a-0000-4000-8000-000000000000
viper agent project support-bot urn:uuid:7f0e6f3a-0000-4000-8000-000000000000
viper agent project support-bot --clear
```

A running `viper proxy` keeps the projects it loaded when it started, so restart it after a change.

For an app such as Claude Code or Codex, choose the project per app instead, because each app signs with its own key. The same setting tells Viper to present any project membership credential files you hold for the app:

```toml
[project_presentations.codex]
credential_files = ["memberships/project-a.json"]
project_urn = "urn:uuid:7f0e6f3a-0000-4000-8000-000000000000"
```

Relative paths resolve from `~/.config/viper/`. A membership credential may name the app's key or the agent it is registered as. Viper learns the agent from the credential the gateway issued when you registered the key. If Viper says it doesn't know which agent the key belongs to, run the command it names: `viper did register --app <app>` when no credential was saved for the key, or `viper did renew --app <app>` to replace one that names no agent; if Viper still says so after renewing, your gateway doesn't name the agent in it yet, and the membership must name the key. A running Viper session or `viper proxy` keeps the agent it loaded when it started, even across its own automatic renewal, so restart it after renewing. `project_urn` picks the project when more than one membership could match; it does not prove membership by itself. Keep `config.toml` and credential files readable only by your user account.

## Key storage and signers

Choose a signer when you create a key with `viper did add --signer-type <type>`.

**Software key (default).** Viper generates an Ed25519 key and stores it in `~/.config/viper/keys/`, readable only by your user account. It needs no extra hardware and suits CI, containers, and most laptops. Anyone who can read the key file can sign as the agent, so protect the directory as you would an SSH key.

**YubiKey (`yubikey`).** The private key stays on a YubiKey and never leaves it. Viper uses a P-256 key in the device's PIV signing slot (slot `9c` unless you pass `--yubikey-slot`), and `--yubikey-serial` selects a device when more than one is connected. The slot must already hold a key before you run `viper did add`; a new or reset YubiKey does not. Ask your security team for your organization's provisioning steps. Set `VIPER_YUBIKEY_PIN` to the device PIN in the environment before running any Viper command that signs, as Viper reads the PIN only from that variable or an interactive prompt.

**vComp Notary (`vcomp-notary`).** Viper delegates every signature to a vComp Notary service, so no private key is stored on the machine running the agent. Pass the notary's address with `--notary-endpoint`.

To create a YubiKey-backed key for Claude Code, set `VIPER_YUBIKEY_PIN`; `viper did add` stops without it. YubiKey keys are `secp256r1` only:

```bash
VIPER_YUBIKEY_PIN=… viper did add --signer-type yubikey --assign claude
```

```console
assigned `did:key:zDna…` to `claude`
did:key:zDna…
```

To create a key for Codex that a vComp Notary signs with, name the notary's endpoint. It defaults to `http://127.0.0.1:8066` and must be a plain `http` address with no path. The notary always signs with `secp256r1`, so `--key-type` is refused:

```bash
viper did add --signer-type vcomp-notary --notary-endpoint http://127.0.0.1:8066 --assign codex
```

`viper agent add <name>` takes the same signer flags. To check which signer backs each key:

```bash
viper did list
```

```console
 App     DID            Type       Signer Type
 claude  did:key:zDna…  secp256r1  YubiKey
 codex   did:key:zDnb…  secp256r1  VComp Notary
```

## Related

- [Install Viper](./install-viper.mdx) — the first run that writes this configuration, and creating keys
- [Register Agents](./register-agents.mdx) — enroll the keys Viper holds
- [Agent Onboarding](./agent-onboarding.mdx#choose-an-environment) — keep a configuration directory per deployment
- [Run Agents](./run-agents.mdx) — the commands that read these settings
- [Agent Configuration](./agent-configuration.mdx) — how recorded environment variables appear in an agent's state
- [Associated Agents](./associated-agents.mdx) — associate an agent so the gateway can find its project membership