Environment and Auth
How AXP injects experiment environment variables and secrets, reads harness environment variables, and stores platform API credentials.
AXP has two separate environment surfaces:
- Experiment environment variables are declared in experiment YAML and injected into variant containers — literal config, or secret values referenced from your organization's secret store.
- CLI and harness environment variables configure AXP itself, such as model-provider credentials or platform API credentials.
Experiment environment variables
Declare env vars with environment_variables — a list of {name, value}, global to the experiment (and also available on a setup object):
schema_version: 2
id: github-example
name: "GitHub example"
environment_variables:
- { name: LOG_LEVEL, value: debug } # literal config — lives in the YAML
- { name: GITHUB_TOKEN, value: "axp://secrets/prod-gh" } # secret — referenced from the org store
agents: [claude]
prompts: ["…"]
tests:
application: [{ name: noop, script: "true" }]
limits: { max_turns: 1, max_time_seconds: 120, max_cost_usd: 1 }A value is either a literal (non-secret config, written in the YAML) or a store reference axp://secrets/<slug> resolved from your organization's secret store. The axp:// prefix is reserved: a literal must not begin with it, and any axp://… that isn't a valid axp://secrets/<slug> is rejected at validate time — so a typo can't silently become a literal.
environment_variables is injected by both axp local run and axp run (platform). Earlier releases rejected secret-bearing experiments on the platform; that restriction is gone. A referenced slug that exists in neither the org store nor a local override fails fast at preflight, before any container starts.
The org secret store
Secret values live in a per-org store, encrypted at rest, and are referenced, never pasted into experiments. Manage them with the CLI:
axp secrets set prod-gh # prompts for the value (never echoed), or reads stdin when piped
axp secrets set prod-gh --description "Prod GitHub token"
axp secrets list # slug + description + audit metadata — never values
axp secrets rm prod-gh # idempotentEach secret is identified by a kebab-case slug (referenced as axp://secrets/<slug>), not an env-var name — the env var a value lands in is chosen per experiment by the name you bind it to. So one org can hold a prod and a staging token that both inject as GITHUB_TOKEN in different experiments.
Agents connected to the AXP MCP server can manage the same store with secrets_set, secrets_list, and secrets_rm. These tools use the current MCP org context, accept the same slugs and optional descriptions, and return only slug + audit metadata.
A stored value never comes back out of a read. axp secrets list, secrets_list, secrets_set, and the UI return slugs and metadata only; there is deliberately no command that prints a value, to keep secrets out of logs, terminal scrollback, and screen-shares. Values are released only to inject into a run you are about to execute, and only to members of the org — a non-member who tries to resolve a secret is denied. (Org membership is the trust boundary in V0: any member can use any of the org's secrets in their experiments.)
Only names your experiment references are read from local sources. If .env or an --env-file contains unrelated variables, AXP ignores them.
Resolution and precedence
-
Platform (
axp run): dispatch resolves eachaxp://secrets/<slug>reference server-side from the org store and injects literals as-is. There is no.envin a platform sandbox — the YAML (and the store behind its refs) is the whole story. -
Local (
axp local run): the CLI resolves references against the org store and injects into the local sandbox, but local sources override the YAML for a matchingname, from lowest to highest precedence:./.env, automatically discovered relative to the current working directory.- Each
--env-file PATH, in command-line order. Later files override earlier files. - Host environment variables.
--env NAME=VALUEor--env NAME.
All four sit above the YAML, so a .env entry for GITHUB_TOKEN overrides whatever the YAML binds to GITHUB_TOKEN — a convenient escape hatch to point one variable at a throwaway value locally without touching the YAML or the store. Local override values are always literal: a .env value of axp://secrets/x is injected verbatim, never re-resolved as a reference.
axp local run experiment.yaml \
--env-file local.env \
--env GITHUB_TOKEN \
--env LOG_LEVEL=traceFor --env NAME=VALUE, AXP uses the value exactly as provided. For bare --env NAME, AXP reads NAME from the host environment while parsing CLI flags; if the host variable is not set, parsing fails.
When ./.env supplies the final value for at least one referenced name, AXP prints a notice:
axp: loaded secrets from /path/to/.envExplicit --env-file paths do not print that auto-load notice.
Valid names and reserved names
An environment_variables name (and a deprecated secrets entry) must match:
^[A-Z_][A-Z0-9_]*$Use uppercase ASCII letters, digits, and underscores; the first character must be an uppercase letter or underscore. Lowercase, Unicode, hyphenated, and empty names are rejected, as are duplicate names within a list. (Store slugs are separate — they are kebab-case, e.g. prod-gh.)
These names are reserved by the harness and cannot be used:
ANTHROPIC_API_KEYANTHROPIC_BASE_URLOPENAI_API_KEYOPENAI_BASE_URLCURSOR_API_KEYMODELMAX_TURNSIS_SANDBOXTRACEPARENT- any name starting with
AXP_ - any name starting with
CLAUDE_CODE_ - any name starting with
CODEX_ - any name starting with
CURSOR_ - any name starting with
OTEL_
Deprecated: secrets
The older secrets: field — a list of host env-var names resolved from local sources (.env / --env-file / host / --env) — still parses as a deprecated alias for backward compatibility, and was local-only. Prefer environment_variables, which unifies literal config and store-backed secrets and runs on the platform path too.
Forwarding secrets to MCP servers
Experiments that expose MCP servers to the agent can route an environment_variables entry into those servers as stdio env entries or HTTP/SSE headers, referenced by name (${NAME} placeholders for headers). Only names/placeholders appear in the YAML; the resolved value (literal or store-backed) is wired in at runtime. See MCP servers for the full schema and validation rules.
Resolved secret values are written verbatim into the ACP session/new JSON-RPC frame, which is recorded in agent-events.jsonl before any redaction. Any debug bundle generated for an experiment that forwards secrets to MCP servers will contain those values — treat such bundles as sensitive.
Model credentials
axp run (the platform path) supplies model access for you — you do not set a model key. Host model credentials apply to local runs. axp local run requires a credential for each selected agent in your host environment:
agent: claudeusesANTHROPIC_API_KEY.agent: codexusesOPENAI_API_KEY.agent: cursorusesCURSOR_API_KEY.
export ANTHROPIC_API_KEY=...
axp local run experiment.yamlexport OPENAI_API_KEY=...
axp local run codex-experiment.yamlexport CURSOR_API_KEY=...
axp local run cursor-experiment.yamlThese names are harness-managed and reserved, so do not put them in environment_variables. AXP reads them from the host, ./.env, --env-file, or --env, then injects only the selected agent's credential into the variant container.
ANTHROPIC_BASE_URL and OPENAI_BASE_URL are also reserved by AXP. Do not put them in environment_variables.
AXP-provided model access
axp run always uses platform-supplied model access. For a local run, add --managed-model-access when you want AXP to supply model credentials instead of providing your own Anthropic, OpenAI, or Cursor API key. It supports agent: claude, agent: codex, and agent: cursor variants.
axp local run --managed-model-access experiment.yamlSign in first with axp auth login, or set AXP_API_KEY if you are running in CI.
Use --api-base-url <URL> only when the AXP team gives you a non-default platform URL, such as a preview environment:
axp local run --managed-model-access --api-base-url https://preview.example.com experiment.yaml--api-base-url is only valid when using AXP-provided model access.
agent: cursor variants are routed through the model proxy's /cursor subpath, which forwards to Cursor's backend with the AXP-held key, so they work under --managed-model-access alongside claude and codex.
Platform credentials
AXP stores platform API credentials at:
~/.fiveonefour/axp/credentials.tomlThe file stores the API key plus the email and active org returned by the platform WhoAmI RPC. AXP writes the file with 0600 permissions and re-applies that mode when saving over an existing file.
AXP_API_KEY overrides the saved API key when the CLI loads credentials:
AXP_API_KEY=... axp auth whoamiThe environment override does not rewrite the saved API key in credentials.toml; it only affects that process. The saved active org is still used as the preferred org when the override key has access to it.
Platform URL
The CLI connects to the AXP platform out of the box — you do not need to configure anything. If the AXP team gives you a different platform URL, set AXP_PLATFORM_URL:
AXP_PLATFORM_URL=https://platform.example.com axp auth whoamiAXP_PLATFORM_URL starts with AXP_, so it is reserved and cannot be declared as an experiment secret.
Auth commands
Log in with the AXP MCP connector:
axp auth connect --code axpcli_...The cli_auth.start MCP tool creates the one-time code and returns the full command. The
code can only be used once and expires quickly.
Log in with an API key:
axp auth loginThe CLI prompts for an API key, verifies it with the platform WhoAmI RPC, lets you select an organization when the account has multiple organizations, then saves credentials to ~/.fiveonefour/axp/credentials.toml.
Pass the key non-interactively with:
axp auth login --token ...Show the identity resolved by the platform API:
axp auth whoamiUse JSON output for scripts:
axp auth whoami --jsonList organizations visible to the current API key and show which one is active:
axp auth orgs
axp auth orgs --list --jsonSwitch the active CLI organization:
axp auth orgs --switch org_...Platform commands such as axp upload, axp send-debug, axp download, and axp query use the active CLI org by default. For a one-off platform command without changing the saved active org, pass --org org_... to that command.
Log out locally:
axp auth logoutlogout removes ~/.fiveonefour/axp/credentials.toml. It does not revoke the API key on the platform.