Environment variables
This page is for operators who run their own OttoTester instance. On a hosted OttoTester, configuration is managed for you — you can skip this.
.env.example at the repo root is the source of truth. It lists every variable with a documented default and a comment explaining it. Copy it to .env and fill in real values. The groups below are an overview, not a replacement for that file.
LLM provider
Section titled “LLM provider”OttoTester’s agents call an LLM. You set the provider and model:
OPENAI_API_KEY/ANTHROPIC_API_KEY/GOOGLE_GENERATIVE_AI_API_KEY— the provider key. Set the one your model needs.DEFAULT_MODEL— the global model, as aprovider:modelspec (for exampleanthropic:claude-3-5-sonnet).<AGENT>_MODEL— per-agent models (PLANNER_MODEL,GENERATOR_MODEL,HEALER_MODEL, and so on). Setup fills in each agent’s line with the model suggested for that agent, when your key offers it. Most agents without a line useDEFAULT_MODEL..env.examplenotes the two that borrow another agent’s model instead. Running setup again with a new key rewrites these lines.
Each day, OttoTester asks every provider you set a key for which models that key can use. With an OttoCloud account, it asks OttoCloud too. You can see these as the “model list” jobs on the Scheduled Jobs screen, and run any of them now. A job fails, and keeps the last list it had, when it can’t reach its provider. For OpenRouter, the list is your account’s own, so models your OpenRouter settings block are not offered. A model that appears on a list before OttoTester has a price for it shows on the Pricing page as unpriced, and you can pick it once it has a price.
The model picker under Global Admin > AI Models > Assignments offers only models from those lists. A supplier with no key offers none, and neither does one that turned down its key. The “Where models come from” card on Global Admin > AI Models > Model catalog lists the suppliers this install is set up for and says if one turned down its key. An agent still set to a model that’s no longer available shows “No longer available”, and a run stops before calling it, with a message naming the agent.
Database and auth
Section titled “Database and auth”MONGODB_URI— the MongoDB connection string.MASTER_KEY— encrypts stored credentials. The server won’t start without it. Back it up — if it’s lost, every encrypted credential is unrecoverable.BETTER_AUTH_SECRET/BETTER_AUTH_URL— session signing, and the URL the auth flow returns users to.TERMS_URL/PRIVACY_URL— your own terms and privacy pages. When either is set, signup asks people to agree to it before they can create an account. Leave both blank to ask nothing. Each must be a full http or https address, or the server won’t start.
EMAIL_PROVIDER— how email leaves your copy:none,smtp(your own mail server) orses. A new install ships withnone.EMAIL_FROM— who email appears to come from. Signup shows this sender, so people know which address to look for.
With EMAIL_PROVIDER=none, OttoTester still works without a mail server:
- New users don’t have to verify their address. After signing up they go straight in.
- Inviting someone gives you a link to send them yourself. Pending invitations have a Copy link button.
- Email options are hidden from notification settings, and the Email PDF buttons are hidden from reports. Saved email choices are kept for when email is turned on.
- The forgot-password screen tells people to ask whoever runs OttoTester.
To let someone back in, run the reset command where OttoTester runs. It prints a reset link that works once and expires in 1 hour, and records it in the audit log. It works whether email is on or off.
If you started OttoTester with pnpm dev, run this from the OttoTester folder while it is running:
pnpm reset-password-link person@example.comIf you run the production image, run this inside its backend container:
node dist/scripts/resetPasswordLink.js person@example.comFrontend and docs
Section titled “Frontend and docs”VITE_API_URL/VITE_WS_URL— where the frontend reaches the backend. Optional, and normally left unset: the frontend then uses its own address (/apiand/ws). Set them only to point the frontend at a backend running somewhere else.VITE_DOCS_BASE_URL— the docs origin the in-app help panel fetches from. Leave it unset to use the build-mode default.
Browser
Section titled “Browser”VITE_BROWSER_TYPE(chromium/firefox/webkit),VITE_BROWSER_HEADLESS, and theVITE_BROWSER_VIEWPORT_*size variables — the default browser configuration for Playwright runs.
Agent budgets
Section titled “Agent budgets”MAX_AGENT_ITERATIONS/MAX_PLANNER_ITERATIONS— caps on how long an agent loops before it stops. They protect a run from consuming unbounded LLM cost.
Updates
Section titled “Updates”Once a day, an install running a release reads GitHub’s public list of OttoTester releases. It sends nothing about your install. When a newer release is out, each Global Admin gets one notice, and the Build panel on the Global Admin page links to the release notes for it and shows the command that installs it. The panel’s Check for updates button checks at once.
RELEASE_CHECK_ENABLED— on unless you turn it off. Set it tofalseto make no request at all, from the very first start. Unset ortruemeans on, and any other value means off. Score sharing (TELEMETRY_ENABLED) does not affect it.
Related
Section titled “Related”- Reference → Settings, API tokens

