Oxy is configured primarily through environment variables. This page covers the full set of variables for production deployments.Documentation Index
Fetch the complete documentation index at: https://oxy.tech/docs/llms.txt
Use this file to discover all available pages before exploring further.
Set Required Variables
The variables you need depend on your deployment mode.Single-workspace mode (Multi-workspace mode (
oxy serve --local) — minimal setup:oxy serve) — required:GitHub App (multi-workspace only)
To enable importing repositories as workspaces, set up a GitHub App and configure these variables. See the GitHub App Setup guide for step-by-step instructions.
Enterprise Features (optional)
Required only when using Observability uses the existing
oxy serve --enterprise or oxy start --enterprise:OXY_DATABASE_URL Postgres connection by default.Full Variable Reference
Core
| Variable | Required | Default | Description |
|---|---|---|---|
OXY_DATABASE_URL | Required (multi-workspace) | — | PostgreSQL connection string |
OXY_STATE_DIR | No | ~/.local/share/oxy | Directory for workspaces and runtime data |
OXY_OWNER | No | — | Email address granted Owner role on login. Owners can promote other users to Admin. When unset, all users are admin (single-user default). |
OXY_API_URL | No | derived from request | Base URL of the API (set when frontend and backend are on different domains) |
Authentication
| Variable | Required | Description |
|---|---|---|
MAGIC_LINK_SECRET | For magic-link auth | Secret used to sign magic-link tokens |
GOOGLE_CLIENT_ID | For Google OAuth | OAuth 2.0 client ID from Google Cloud Console |
GOOGLE_CLIENT_SECRET | For Google OAuth | OAuth 2.0 client secret |
OKTA_CLIENT_ID | For Okta OAuth | Okta application client ID |
OKTA_CLIENT_SECRET | For Okta OAuth | Okta application client secret |
OKTA_DOMAIN | For Okta OAuth | Your Okta domain (e.g. company.okta.com) |
GitHub App
| Variable | Required | Description |
|---|---|---|
GITHUB_APP_ID | For GitHub import | Numeric App ID from the GitHub App settings page |
GITHUB_APP_SLUG | For GitHub import | App slug (appears in the app’s GitHub URL) |
GITHUB_APP_PRIVATE_KEY | For GitHub import | Full RSA private key PEM block |
GITHUB_CLIENT_ID | For GitHub import | OAuth Client ID from the app settings |
GITHUB_CLIENT_SECRET | For GitHub import | OAuth Client Secret from the app settings |
GITHUB_STATE_SECRET | For GitHub import | Random secret for HMAC-signing OAuth state and selection tokens |
Enterprise (Observability)
| Variable | Required | Description |
|---|---|---|
OXY_OBSERVABILITY_BACKEND | No | Storage backend: auto-detected (postgres if OXY_DATABASE_URL set, else duckdb) |
OXY_SERVICE_NAME | No | Service name for spans (default: oxy) |
OXY_OBSERVABILITY_LOG_LEVEL | No | Log level for observability layer (default: debug) |
Tuning
| Variable | Required | Default | Description |
|---|---|---|---|
OXY_WORKER_MAX_INFLIGHT | No | 16 | Max concurrent tasks executed by a single worker process. Caps wide fan-outs (loops, parallel delegations, consistency runs) so a 1000-iteration loop can’t stampede the database/LLM providers. Per-worker by design — the global ceiling scales with the number of worker processes. |
Task dispatch (matcher)
Workflow workers learn about new tasks via PostgresLISTEN/NOTIFY
— Oxy does not deploy a separate dispatch service. Each app instance
opens one dedicated Postgres connection for its listener (in
addition to the main connection pool); plan accordingly when sizing
your DB max_connections. Most deployments need no extra tuning.
Both authentication modes are supported:
- Password auth (
OXY_DATABASE_URL): the listener parses the URL once at startup and reuses the parsedConfigon every reconnect. - IAM auth (RDS,
OXY_DATABASE_AUTH_MODE=iam): the listener mints a fresh SigV4 token on every (re)connect via the samerds-db:connectIAM permission already required for the connection pool. No additional IAM policy beyond what the pool needs. There is no background token-refresh loop — the listener holds one connection at a time, and Postgres doesn’t re-auth mid-stream, so a token only matters at connect time.
SELECT 1)
keeps NAT / ELB / PgBouncer / RDS-side idle-timeout policies from
silently dropping the connection during quiet periods. Workers also
run a backstop poll every 10 seconds so a missed notification
turns into bounded latency, not lost work.
For monitoring, a 60-second self-NOTIFY health probe fires on
the oxy_health_probe channel from every app instance and is heard
by every listener (own instance + peers). Each receipt emits a
router.health_probe_received tracing event and updates an
in-memory last_probe_received_at timestamp. The intended alert
shape is absence of the event over a 3-minute window — that
catches the failure mode where the connection looks healthy
(keepalive succeeds) but the NOTIFY delivery path is silently
stuck. The router.notification.delivered trace event from the
task channel gives the same signal under load; the probe is what
covers naturally-quiet deployments. Repeated router.reconnect
warnings within a minute are an independent real signal.
A second background loop runs the stale-claim reaper every 30 s
to free tasks held by workers that died without cleanup (OOM,
panic, network partition). Combined with the default 60 s
visibility_timeout_secs on claims, a dead worker’s tasks reappear
in the queue within ~90 s. There is no env knob for these intervals
yet; they are tuned for healthy steady-state behaviour and rarely
need adjustment.