Skip to content

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.

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 a provider:model spec (for example anthropic: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 use DEFAULT_MODEL. .env.example notes 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.

  • 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) or ses. A new install ships with none.
  • 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.com

If you run the production image, run this inside its backend container:

node dist/scripts/resetPasswordLink.js person@example.com
  • VITE_API_URL / VITE_WS_URL — where the frontend reaches the backend. Optional, and normally left unset: the frontend then uses its own address (/api and /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.
  • VITE_BROWSER_TYPE (chromium / firefox / webkit), VITE_BROWSER_HEADLESS, and the VITE_BROWSER_VIEWPORT_* size variables — the default browser configuration for Playwright runs.
  • 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.

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 to false to make no request at all, from the very first start. Unset or true means on, and any other value means off. Score sharing (TELEMETRY_ENABLED) does not affect it.