Two agents, one limit, one refused.
All posts
5 min read
by

AI agent staging and production isolation: why the key must pick the environment

Keep an AI agent's staging key away from production data and side effects: bind the environment to the credential, remove every fallback, and test the boundary.

environmentsisolationagentsengineering

Staging and production isolation for an AI agent means an agent running with staging credentials cannot read production data or cause a production side effect, whatever it is told and whatever it finds. The model should not be able to cross that line by choosing a different argument.

Most setups get this almost right, and "almost" is where agents live. This post is the rule we build on, the failure mode it prevents, and a test you can run against your own stack.

Why agents make this worse

A human developer with a staging key and production access usually knows which one they are using. An agent does not know anything. It acts on what is in front of it. If a production identifier appears in a log it reads, it will try it. If a request accepts an environment parameter, sooner or later it will pass production. If a staging call fails, it may go looking for a credential that works, which is exactly what the agent in the PocketOS incident did.

So the boundary cannot depend on the caller behaving. It has to be a property of the credential.

The rule: the key is the environment

In Anlyon, every API key belongs to exactly one environment, and every request resolves its environment from the credential, not from anything in the request. There is no environment argument to get wrong. A request body that names one is rejected. A query parameter that disagrees with the key is refused.

Everything the agent can touch is scoped the same way: actions, secrets, invocations, approvals, policies, messages and queues, workflows, sessions, memory, files, agents, and their runs and spans. The same name can exist in both environments as two different resources. refund-order in staging and refund-order in production are different actions, pointing at different credentials, and resolving the staging one can never return the production one. This is logical isolation: rows in shared storage, filtered by an enforced column. It is not dedicated storage or compute.

That gives the property worth having: a staging key cannot reach production data, because it resolves its environment from the credential and there is no fallback that quietly promotes it.

Why "no fallback" is the rule that matters

The last clause is the one most systems miss.

The usual leak is not a missing check. It is a reasonable-looking default: environmentId ?? defaultEnvironment. Somewhere a code path, often a background one like a scheduler firing a job, does not receive the environment, falls through to the workspace default, and the default is production. Nothing errors. The work simply lands in the wrong place.

Background paths are where this hides, and the consequences all point the same way:

  1. Work created with a staging key runs against production.
  2. A listing without an environment filter lets a staging key see, and delete, production resources.
  3. Because the work lands in production, halting staging does not stop it. A kill switch that misses the thing you pressed it for is worse than none.

The principle: falling back to a default environment is only ever safe for a caller that never named one. An API key always names one. On any path authenticated by a key, a fallback is not a convenience. It is an isolation hole that fails open, towards production.

In Anlyon every resource carries its environment from creation, is filtered by it on every read and write, and passes it to anything that acts on your behalf, including schedules, workflows and fan-out. A caller that cannot resolve its environment fails loudly instead of guessing.

What "isolated" means here

Environments in Anlyon are enforced at the credential and on every row the key can reach. The storage is shared, and so is the compute. Signed deliveries name their environment inside the signature, so a staging delivery cannot be presented to your verifier as a production one. One thing is not scoped: the delivery-signing secret is workspace-wide, so its key material and its rotation are shared across environments.

Why this matters more once Anlyon makes the call

With Anlyon, your agent does not call Stripe with a key it holds. It invokes an action by name, and Anlyon makes the call with a credential from the vault. Because actions and secrets are both environment-scoped, the staging agent's refund-order resolves to the staging action, which references the staging secret, which is your Stripe test key. There is no production key anywhere on that path for it to find.

That is the difference from isolation you enforce by convention. A staging agent that holds only a staging Anlyon key has nothing to escalate with.

A test you can run

Isolation you have not tested is a belief. Here is the shape of a negative test, for Anlyon or anything else:

  1. Create the same named resource in staging and production with different contents: an action, a secret, a queue.
  2. With a staging key, try to read, list, invoke and delete the production one by every identifier you have: name, id, and any environment parameter the API accepts.
  3. Every attempt should fail as "not found", not "forbidden". A 403 tells the caller the resource exists.
  4. Create a schedule and a delayed message with the staging key. Halt staging. Confirm both stop. Then halt only production and confirm the staging ones still run.
  5. Grep your own code for ?? default wherever an environment or tenant is resolved.

Step 4 is the one most setups fail: background work is where a missing environment hides.

Checklist

  • One key per environment, minted separately. Never let a build or test use a production key.
  • Resolve the environment from the credential. Reject requests that try to name it.
  • No default-environment fallback on any authenticated path.
  • Keep production credentials only in the production vault, referenced by actions, never in the agent's process.
  • Test the boundary in both directions, including the halt.

Early Beta Access is free, with no credit card, and includes 3 environments. A new workspace starts with a protected environment named Production, and you can add staging beside it.

Start building → · Environments and the kill switch in the docs →

Free tier, no credit card. One command if you use Claude or Cursor.

$ claude mcp add anlyon -- npx -y @anlyonhq/mcp-server