---
title: "Immutable versions & rollback"
description: "Ship agent configuration as immutable versions, promote to production with confirmation, and roll back with a pointer move."
---

An **agent** is a logical identity scoped to an environment. Its configuration ships as **immutable, append-only versions**. Editing an agent does not mutate a version. It creates a new one. That immutability is what makes promotion and rollback safe and boring.

## How versioning works

- Every edit creates a new version. Version numbers increment per agent under a uniqueness guard, so history is one ordered sequence.
- A single **published pointer** marks the live version in each environment.
- **Earlier versions are kept.** A rollback moves the pointer to one of them.

## Promotion

Promoting publishes a version into a target environment. It creates or appends an immutable version there, moves the published pointer, and **does not copy secret values**. Configuration references secrets *by name*, and each environment resolves its own. A `production` promotion picks up production's secrets, not staging's.

Promotion into a **protected** environment requires an explicit `confirmProtected` acknowledgement, so promoting into it is a stated choice. An environment is protected when you mark it so. See [Protected production](/trust-control/environments#protected-production).

**Manage it in the dashboard**

Create agents, edit versions, promote between environments, and roll back from **Agents** in the dashboard. Agents are managed in the dashboard and through the API.

## Rollback is a pointer move

Because every version is retained, rolling back is not a rebuild or a restore-from-backup. It moves the published pointer to a previous version, and that version is still there to point at.

```text
v1  published ─┐
v2             │   promote v3 → pointer moves to v3
v3  published ─┘   incident → roll back → pointer moves to v1
```

Every version between is still there. You can move the pointer forward again the same way.

## What a rollback restores

A version restores the configuration Anlyon holds. It does not restore the world outside. It
does not undo a request already dispatched. An upstream API may have changed its behaviour since, and
secrets resolve per environment by name, so production keeps using production's current credential.

Within Anlyon, how much it restores depends on what the version **pins**. A version's
`config.actions` maps an action name to an immutable [action version](/api-reference) id:

```json
{ "actions": { "refund": "acv_01JABCDEF" } }
```

Roll back to that version and `refund` runs the definition it named, not whatever the action has
since been edited to. A version that pins nothing restores the pointer and the prompt, and its
tools run at their current definitions.

**Pinning applies to agent-attributed calls**

An action invocation runs a pinned version when it is attributed to an agent, that is, when you
pass a `runId` whose run names one. A direct `actions.invoke()` with no run runs the action's
current definition, deliberately: it is the low-level path. Every invocation reports which
version actually executed as `actionVersionId`, so you never have to infer it.

### When the pin is read, and what happens if it cannot be resolved

Two things about the timing are worth stating plainly, because they decide what a rollback does to
work that is already running:

- **The pin is read at each invocation, from the agent's published version at that moment.** It is not
  frozen when the run started. A run is a thread of attribution, not a sealed execution context. So
  rolling an agent back mid-run takes effect on that run's *next* action call, and a call already
  in flight finishes on the definition it started with. If you need a run to be immune to a
  promotion happening underneath it, do not start it until the promotion has landed.
- **A pin that cannot be resolved fails the call.** If an agent version names an action version
  that no longer exists (an import, a repaired row, an action deleted and recreated), the
  invocation returns `409 ACTION_VERSION_PIN_UNRESOLVED` naming the agent, the action and the
  missing version. Anlyon does not substitute the action's current definition: silently running a
  different definition is exactly what pinning exists to prevent, and a warning in our logs is not
  an answer to "did my rollback take effect".

Pinning is opt-in. A version whose `config.actions` names nothing pins nothing, and its invocations
run each action's current definition. That is what every call does until you start pinning.

Deleting an action **archives** it rather than destroying it, so versions an agent pins stay
resolvable and the invocation history survives. The archived action keeps its name. Creating a new
action under that name in the same environment answers `409 CONFLICT`, so use a new name.

## Why this is the safe default

- A bad prompt or tool change in production is a **pointer move away** from the earlier definitions, not an emergency redeploy. The rollback does not undo an effect already dispatched.
- Promotion is recorded. The version it creates in the target environment carries who created it.
- Promotion does not copy secret values between environments, so it does not carry a staging credential into production.

## Related

- [Environments & the kill switch](/trust-control/environments): the isolation promotion moves between.
- [EU AI Act mapping](/trust-control/compliance): how immutable versions and records relate to the logging and traceability obligations.
