Promotion between environments
Copy a definition, resolve every name it references in the target, or write nothing.
An agent definition references connections, providers and secrets by name. Which
is exactly what makes it promotable: a connection called orders in dev is called
orders in prod, pointing at a different URL with a different credential.
PLANE_API_KEY=$PLANE_ORG_KEY npx plane promote support-bot --to prod
npx plane promote support-bot --to prod --map connection:orders=orders-prod --dry-run// The same code path as the write, writing nothing.
await client.agents.promote({ agentId, to: "prod", dryRun: true })
await client.agents.promote({
agentId,
to: "prod",
mapping: { connections: { orders: "orders-prod" } }
})The CLI always runs a dry run first and prints the resolution, so a failure is legible in CI output without anybody reading JSON:
support-bot v7 → prod: cannot promote
connection orders MISSING in prod
provider anthropic → anthropic-prod MISSING in prodFailure is total and enumerated. PromotionUnresolvedError lists every missing
name at once — connections, providers and secrets — and nothing is written. The
operation fails in CI instead of on the first production turn.
Promoting an identical definition twice creates one version, so it is safe on every green build.
An API key cannot promote
A key is an environment — that is what a key is — and promotion crosses two. It
needs a cross-environment principal: a signed-in user with control in both, or an
organization-scoped credential. This is the one operation whose authorization is two
questions rather than one.
--map kind:from=to is repeatable and kind is connection, provider or secret.
The common case needs no mapping at all; it exists for the organization that suffixed
everything.