pikopod.yaml from the working directory unless --config says otherwise. --config is accepted by every command. Run pikopod init to scaffold one.
Unknown keys are startup errors, not silent no-ops. A typo’d or removed knob must never let you believe something is configured. If pikopod starts, every key you wrote is a key it understands.
A minimal working file
Top-level keys
upstreams
Each named upstream has a route on the agent and a target it forwards to. The target alone decides posture: a real provider means watch mode, a vendor sandbox means staging mode, the internal sandbox means scenario mode.
Health checks and KYC document uploads are the usual reasons for
record.exclude: the first is noise, the second must never reach disk in any form. A pattern that does not compile is a configuration error, exit 2. See What never reaches disk at all.
Upstream names may only contain letters, digits, _ and -, because the name becomes a file path component under data_dir.
listen and tokens
0.0.0.0 is a way to lose data, so pikopod refuses to start rather than let it happen. Supply the token via PIKOPOD_TOKEN or token_file, never on the command line. The environment wins over the file.
When a token is set, every request to either server must carry it in the X-Pikopod-Token header. Tokenless agent listeners additionally reject requests carrying a foreign Host header, which blocks DNS rebinding from a browser on the same machine.
tls
data_dir
sampling
rate thins what recordings persist, never what pikopod learns from. Every record still feeds the learner and the differ; the rate only gates the disk write. Error responses, drift-bearing records and pre-warmup traffic are always kept. 0 keeps guaranteed classes only, and is distinguishable from unset (1.0).
retention
0 (default) keeps size-based rotation only.
scenario from-drift and reproduce read the event log, so fingerprints older than the window can no longer be pinned. Every incident row therefore carries reproducible until <time> and an export: hint. See Incident bundles.
slack
Alert behaviour itself is a fixed contract, not a set of keys. See Alerts.
warmup
min_samples responses across at least min_hours, then freezes a reference. Both are overridable for evaluation. Lowering them shortens the blind window and raises false positives. min_hours: 0 is explicitly distinguishable from unset. See Warmup and baselines.
spec_watch
spec_source. Fetches are ETag-gated and the pin never advances on its own; accepting a declared change is an explicit pikopod import <name> --update.
refine
prefer_spec flips type-conflict precedence back to spec-wins; the default is traffic-wins once the sustain gates clear. Inspect the result with pikopod agent contract <sandbox>. See Contract.
behaviour
llm
provider to the provider the key belongs to (openai, anthropic or openrouter), and the key in api_key or in PIKOPOD_LLM_KEY. The provider’s own standard key variable is also honoured, so an existing environment keeps working.
When a key is stored in pikopod.yaml, the file must be mode 0600. Environment-provided keys do not make the file secret.
The key is optional. Exactly three things use it: plain-English scenario authoring (scenario create), pikopod fix, and importing from a documentation URL as the last resort after the deterministic rungs fail. Everything else works with no key at all.
quotas
Sandbox resource limits are fixed rather than configured:
Exceeding them returns
413 or 507 rather than degrading silently. Reset a sandbox’s state with pikopod sandbox reset <name>.
Sandboxes
Sandboxes are not apikopod.yaml key. They are registered by pikopod import and stored in <data_dir>/sandboxes.json with their id, seed, spec source, origin, linked upstream, webhook URL and recordings mode. See Importing and Precedence.
The init template
pikopod init writes this file with mode 0600 and refuses to overwrite an existing one:
Validation errors
Every configuration error names the key, the reason and the fix, and exits2. The ones you are most likely to meet:
pikopod doctor checks the file, the data directory, the salt, the ports and every upstream’s reachability in one pass. See Troubleshooting.