EQTY LabDocs

Viper Configuration

Find where Viper keeps its settings and keys, change its settings, and override them with environment variables.

View as Markdown

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/:

PathContents
config.tomlYour 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:..."
SettingWhat it does
llm_gateway_api_urlThe gateway address Viper sends signed requests to. If you give only a host, Viper assumes /v1.
guardian_urlNo 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_varsNames 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.

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.

VariableEffect
VIPER_CONFIGPath to the configuration file to use instead of ~/.config/viper/config.toml.
VIPER_GATEWAY_URLOverrides llm_gateway_api_url. If no configuration file exists yet, Viper creates one from this value instead of prompting.
GUARDIAN_API_KEYAn ak_... API key used by viper did register and viper agent register for headless enrollment. Keep it out of config.toml.
VIPER_PROVISIONING_TOKENA ggr1. registration token used by viper did register and viper agent register, in place of --provisioning-token.
VIPER_AGENT_IDAn 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_URNThe 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_PINThe 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_URLNo 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.

VariableSandboxMeaning
DAYTONA_SANDBOX_SNAPSHOTDaytonaSnapshot the sandbox was started from
DAYTONA_SANDBOX_IDDaytonaSandbox instance
DAYTONA_ORGANIZATION_IDDaytonaDaytona organization that owns the sandbox
E2B_SANDBOXE2BSandbox indicator set by the runtime
E2B_TEMPLATE_IDE2BTemplate the sandbox was created from
E2B_SANDBOX_IDE2BSandbox instance
OPENSHELL_SANDBOXOpenShellSandbox indicator set by the runtime; OpenShell sets no sandbox ID

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