Prepared Versions and Aliases: Promoting an Agent Safely

An agent has a mutable DRAFT you edit, immutable numbered versions you cut from it, and aliases your application points at — and PrepareAgent is the step that connects them.

Bedrock agents have a deliberately three-part lifecycle, and every deployment problem people hit with them comes from confusing the parts.

DRAFT, prepared, versioned

DRAFT is the single mutable working copy. Every UpdateAgent, every action group change, every knowledge base association edits DRAFT. There is exactly one per agent, and it is not runnable as-is.

PrepareAgent packages DRAFT for use. It validates the configuration, compiles the action group schemas into the prompt, and moves the agent's status from NOT_PREPARED to PREPARED. Until you call it, your changes exist but nothing can execute them. This is the single most common "my new action group is not being used" cause.

Versions are immutable, numbered snapshots (1, 2, 3…) taken from the prepared DRAFT. You cannot edit a version. Rolling back means pointing an alias at an older number, which is exactly the property you want.

Aliases are the deployment handle

An alias is a stable pointer to one version. InvokeAgent takes agentAliasId, never a version number, so your application code never changes when you promote. Every agent ships with the built-in test alias TSTALIASID, which always resolves to the current DRAFT — convenient for a fast edit-and-try loop, and completely wrong for production, because a colleague saving a change in the console instantly changes what your users get.

Calling CreateAgentAlias without a routingConfiguration creates a new version from DRAFT and points the alias at it in one step. Supplying a routingConfiguration points the alias at a version that already exists — that is how you roll forward and back. The routing configuration takes a single version; there is no weighted split between two versions, so canarying is something you do in your own application by sending a fraction of traffic to a second alias. An alias's routing entry can also carry a provisioned throughput ARN, which is how you give a production alias dedicated capacity while dev shares on-demand.

A safe promotion

  1. Edit DRAFT. PrepareAgent. Exercise it against TSTALIASID with tracing on.
  2. Run your evaluation set — the same fixed conversations every time, checking which tools were chosen, not just whether the prose reads well.
  3. Create a version by creating or updating an alias such as staging.
  4. Point prod at that version number with UpdateAgentAlias.
  5. Keep the previous version number written down. Rollback is one UpdateAgentAlias call.

Two more things to plan for. Versions capture the agent's own configuration; they do not freeze the world around it. A Lambda behind an action group can be redeployed underneath a pinned version, and a knowledge base can be re-ingested, so version your Lambda (use a Lambda alias in the executor ARN) if you want genuine immutability. And ordering matters on teardown: delete aliases before the agent, and expect a delete to be refused while something still references it.

Example

Example · python
cp = boto3.client("bedrock-agent")

# 1. Package the current DRAFT and poll until it is usable.
#    PrepareAgent returns immediately with status PREPARING.
cp.prepare_agent(agentId=AGENT_ID)
while cp.get_agent(agentId=AGENT_ID)["agent"]["agentStatus"] == "PREPARING":
    time.sleep(2)
assert cp.get_agent(agentId=AGENT_ID)["agent"]["agentStatus"] == "PREPARED"

# 2. Cut an immutable version and give staging a stable handle to it.
#    No routingConfiguration => a new version is created from DRAFT.
staging = cp.create_agent_alias(
    agentId=AGENT_ID,
    agentAliasName="staging",
    description="release 2026-08-26, adds policy-api action group",
)
new_version = staging["agentAlias"]["routingConfiguration"][0]["agentVersion"]
print("cut version", new_version)

# 3. Promote: repoint prod at that existing version. No code change downstream.
cp.update_agent_alias(
    agentId=AGENT_ID,
    agentAliasId=PROD_ALIAS_ID,
    agentAliasName="prod",
    routingConfiguration=[{"agentVersion": new_version}],
)

# 4. Rollback is the same call with the previous number
# cp.update_agent_alias(agentId=AGENT_ID, agentAliasId=PROD_ALIAS_ID,
#                       agentAliasName="prod",
#                       routingConfiguration=[{"agentVersion": "4"}])

# Never ship this to users - it tracks DRAFT and changes under you:
# rt.invoke_agent(agentId=AGENT_ID, agentAliasId="TSTALIASID", ...)

When to use it

  • Shipping a new action group to staging while production stays pinned to the version that has been soak-tested for a week.
  • Rolling back a regression in tool selection with a single UpdateAgentAlias call instead of re-editing the agent.
  • Attaching provisioned throughput to the production alias only, leaving development on on-demand capacity.

Discussion

  • Be the first to comment on this lesson.