dev, staging, prod, or whatever your pipeline actually looks like — that scopes traces, evaluations, guardrails, incidents, and metrics so you can look at one stage of your pipeline without the others in the way. It’s a first-class row in the project, not a free-text tag: it has a slug, a display name, a rank (for ordering), a production flag, and an optional monthly event quota field (see Monthly quota below).
1
Switch environments from the project header
Every project page has an environment switcher next to the project name. It defaults to All environments — pick one to scope the current page’s data to just that environment.
2
Manage environments
Go to Settings → Environments to create, rename, reorder, or delete environments, and to mark one as production.
3
Filter the API directly (optional)
Every endpoint the switcher drives also accepts an
environment query parameter directly — see Filtering the API below.The three defaults, and custom ones
Every project is seeded with three environments on creation:
These three are a starting set, not an enum. Slugs are free-form beyond them —
qa, uat, prod-eu, canary are all valid, as long as the slug is lowercase alphanumeric with hyphens (max 50 characters) and unique within the project. Create one from Settings → Environments → New environment, or POST /v1/projects/:id/environments.
Creating, renaming, reordering, or deleting an environment requires the environments:manage permission (owner/admin/editor); viewing the list only needs environments:read.
Deleting an environment
An environment can carry guardrail configs, alert rules, SLA policies, health thresholds, agent lifecycle gates, prompt deployments, and incidents. Deleting it does not silently orphan those — the delete is blocked with a409 naming exactly what’s still attached (e.g. "3 guardrail config(s), 1 alert rule(s)"), so you know what to move or delete first before the environment itself can go.
The switcher and the “omitted means all” rule
The environment switcher writes its selection into the URL as?env=<slug> — so a filtered link is shareable and survives a page reload. Clearing the selection (All environments) removes the param entirely rather than writing a default back into the URL.
This matters for the API too: omitting the environment parameter means all environments, on every endpoint that accepts it. This is deliberate — every existing integration and saved link that predates this feature keeps working unfiltered, exactly as before. You only see a single environment’s data when you (or the switcher) explicitly ask for one.
Filtering the API
Theenvironment query parameter is accepted on 16 read endpoints across traces, evaluations, guardrails, incidents, and metrics — the same set of pages the switcher covers. Pass a slug:
400:
Alias mapping and the ingest asymmetry
Theenvironment column in the underlying event store predates this feature — it’s been populated by the SDK’s free-text environment option (or OTel’s deployment.environment attribute) since long before environments were a project-level entity. That means historical data uses whatever string a client happened to send, most commonly production, development, staging, and test, not the seeded prod/staging/dev slugs.
To keep old and new data queryable together, a shared alias map normalizes the common cases both ways:
Filtering
?environment=prod matches rows stored as either prod or production — you never have to know or care which era a given row came from.
Ingest and reads handle an unrecognized value differently, on purpose:
- Reads reject.
?environment=qa-2on a project with noqa-2environment returns400. A read is a request for a specific view; failing loudly beats silently returning nothing or (worse) everything. - Ingest keeps and flags. A trace arriving with
environment: "load-test-3"that doesn’t match any known slug or alias is still stored — underload-test-3, unmodified — with a warning logged (throttled to once per project per hour, so a typo’d environment string on every span doesn’t flood the logs). Losing telemetry because of an unfamiliar environment string would be a far worse outcome than an imprecise dimension on an otherwise-good trace.
Monthly quota (not yet enforced)
Each environment has an optionalmonthlyEventQuota field, settable from the same create/edit form and returned by the API. Nothing currently enforces it — it does not throttle ingest or trigger an alert on its own. The field exists so environment-level quota enforcement, when it ships, doesn’t require a second schema change. Don’t rely on it as a working limit today; project-level quotas (see Billing) are the ones actually enforced.
Next steps
- Traces — the primary view the environment switcher scopes
- Guardrails and Alerts — can be scoped to a specific environment via the same
environmentIdrelation the delete-block check above walks - Environments guide — when to use environment filtering within one project versus separate projects entirely

