Agentic AI AcademyAgentic AI Academy
AgentCore Runtime/Lesson 1 of 6

The Runtime Object Model

Runtimes, versions, endpoints, sessions, and two planes

Beginner 13 minBuilder
What you'll be able to do
  • Explain the four-layer Runtime object model: agent runtime resource, versions, endpoints (aliases), and sessions
  • Describe how versions are created (V1 auto-created, each update mints a new immutable snapshot) and how that enables rollback
  • Identify how the DEFAULT endpoint tracks the latest version and how a custom endpoint is selected at invoke time via the `qualifier` parameter
  • Distinguish the control plane (`bedrock-agentcore-control`: Create/Update/Get/List AgentRuntime[Endpoint]) from the data plane (`bedrock-agentcore`: InvokeAgentRuntime)
  • Manage a caller-supplied `runtimeSessionId` to bind related invocations to one interaction context
  • Choose the correct boto3 client name and IAM action for each operation against a runtime
At a glance

Before you write a line of agent code, you need a map of what AgentCore Runtime actually creates on your behalf. This lesson lays out the Runtime object model — the agent runtime resource, immutable versions, endpoints (aliases) that you address via a `qualifier`, and per-conversation sessions — and draws the hard line between the control plane (manage resources) and the data plane (invoke them), each with its own endpoint, API set, and boto3 client.

  1. 1The mental model: a hosting primitive, not a framework
  2. 2The agent runtime resource: your containerized app
  3. 3Versions: immutable snapshots that make rollback free
  4. 4Endpoints (aliases): DEFAULT, custom, and the qualifier
  5. 5Sessions: the per-conversation interaction context
  6. 6Two planes: control (manage) vs data (invoke)

The mental model: a hosting primitive, not a framework

AgentCore Runtime is the hosting primitive of the platform. You write an agent in any framework — Strands, LangGraph, CrewAI — or none at all, wrap it so it exposes a small standardized wire contract (HTTP / MCP / A2A / AG-UI), package it as an ARM64 container (or a direct-code zip), and hand it to AWS. AWS then runs it in a managed, serverless environment where every user session gets its own dedicated microVM with isolated CPU, memory, and filesystem.

The critical thing to internalize before writing code: when you "deploy an agent," you are not deploying one thing. You are creating a small graph of related resources — a runtime, one or more versions, one or more endpoints — and at request time you create sessions against an endpoint. Get this object model wrong and you will struggle to reason about rollbacks, zero-downtime updates, and why an invoke is hitting the code you didn't expect.

Sessions can live up to 8 hours, support streaming and async/background work, and are invoked through the InvokeAgentRuntime data-plane API using an agent runtime ARN plus a caller-supplied runtimeSessionId. We will unpack every term in that sentence below.

Key insight

Why this lesson is conceptual-first

AgentCore Runtime is closer to a managed deployment target (think: a versioned, alias-addressable service) than to a single Lambda function. The deployment tooling hides most of these resources behind one command, so engineers often discover the object model only when something breaks — a rollback, a stuck update, an invoke pinned to the wrong version. Learn the nouns now; the verbs (CLI, SDK) land far more cleanly afterward.

The agent runtime resource: your containerized app

The top of the object model is the AgentCore Runtime — the agent runtime resource. This is the containerized app that hosts your agent or tool. You create it on the control plane with CreateAgentRuntime, and it is versioned from birth.

Every runtime is addressed by an agent runtime ARN, which looks like this:

text
arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/MyAgent-XXXX

That ARN is the handle you pass to the data plane every time you invoke the agent. The resource itself holds no live conversation state — it is the definition of the deployable unit. The actual configuration (which container image, which protocol, which network mode) lives one level down, in versions.

A single AWS account can hold up to 1,000 agent runtimes as of writing (adjustable) — verify the live quotas page before you design around any limit.

Note

Resource vs. running code

The agent runtime resource is metadata: a name, an ARN, and a pointer to its versions and endpoints. It does not consume compute until you invoke it and a session spins up a microVM. Creating a runtime is a control-plane act; running it is a data-plane act.

Versions: immutable snapshots that make rollback free

A version is an immutable configuration snapshot — it captures the container image, the protocol mode, and the network configuration at a single point in time. Versions are the unit of "what code/config is actually running."

Two rules drive everything:

  1. CreateAgentRuntime auto-creates Version 1 (V1). You never create V1 explicitly — it appears the moment the runtime is created.
  2. Every UpdateAgentRuntime creates a new version. Updates never mutate an existing version in place. Push a new image and you get V2; push again and you get V3. Old versions remain intact.

Because old versions are never destroyed by an update, rollback is just pointing an endpoint back at an earlier version — no rebuild, no redeploy. This is the entire payoff of the immutable-snapshot design.

python
import boto3
control = boto3.client("bedrock-agentcore-control")   # CONTROL plane

# Inspect the version history of a runtime
resp = control.list_agent_runtime_versions(
    agentRuntimeId="MyAgent-XXXX"
)
# Iterate the returned summaries; confirm the exact response key/field
# names against the live boto3 / API reference for your SDK version.
for v in resp.get("agentRuntimes", []):
    print(v.get("agentRuntimeVersion"), v.get("status"))

An account can hold up to 1,000 versions per agent as of writing (verify live). In practice you will never approach that — but you should expect the list to grow with every deploy, which is exactly what makes a rollback possible.

Tip

Treat a deploy as 'mint a version, then re-point'

Mentally separate the two acts. Shipping new code mints a new immutable version. Promoting that code is a separate decision: which endpoint should now point at it. Keeping those two ideas distinct is what lets you stage a version, test it on a custom endpoint, and only then move DEFAULT — or roll back by re-pointing without touching the image.

Endpoints (aliases): DEFAULT, custom, and the qualifier

An endpoint (an alias) is an addressable access point that points to a specific version. Each endpoint has its own ARN. Endpoints are the indirection layer that lets you change what runs without changing what callers address.

Two flavors:

  • DEFAULT — auto-created with the runtime and always tracks the latest version. If you do nothing special, your invokes hit DEFAULT, and DEFAULT follows your most recent update.
  • Custom endpoints — created with CreateAgentRuntimeEndpoint. You wire these to a chosen version yourself, which is how you build patterns like a pinned prod alias and a moving staging alias.

At invoke time you select which endpoint to hit with the qualifier parameter on InvokeAgentRuntime. Omitting it (or passing "DEFAULT") targets the DEFAULT endpoint:

python
resp = data.invoke_agent_runtime(
    agentRuntimeArn="arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/MyAgent-XXXX",
    runtimeSessionId=session_id,
    payload=json.dumps({"prompt": "Tell me a joke"}).encode(),
    qualifier="DEFAULT",   # or a custom endpoint name to pin a version
)

Endpoints move through lifecycle states: CREATING, CREATE_FAILED, READY, UPDATING, and UPDATE_FAILED. When you re-point an endpoint to a new version it transitions through UPDATING back to READY, and crucially updates are zero-downtime — in-flight traffic keeps flowing while the swap happens. An account can hold up to 10 endpoints per agent as of writing (verify live).

Example

Blue/green with two aliases

Keep DEFAULT tracking latest for fast iteration, and a custom prod endpoint pinned to a known-good version. Ship a new version (it auto-flows to DEFAULT), exercise it through DEFAULT or a canary endpoint, then re-point prod to that version. If it misbehaves, re-point prod back to the prior version — a zero-downtime rollback with no rebuild, because every version is still there.

Watch out

DEFAULT moves under you

Because DEFAULT always tracks the latest version, an UpdateAgentRuntime instantly changes what DEFAULT serves. If callers invoke without a qualifier, they are implicitly riding the bleeding edge. For anything you want stable, invoke against a custom endpoint pinned to an explicit version rather than relying on DEFAULT.

Sessions: the per-conversation interaction context

A session is an interaction context — the unit that holds the back-and-forth of one conversation (or one agent task) and runs in its own dedicated microVM. Sessions are identified by a caller-supplied runtimeSessionId, or one is generated on the first invoke if you don't pass it.

The runtimeSessionId is how AgentCore knows that two invokes belong to the same conversation: reuse the same ID across related calls and they share the same microVM (and its in-memory context). Use a fresh ID and you get a fresh microVM. The commonly cited rule is that the ID must be at least 33 characters (a UUID is 36, so str(uuid.uuid4()) is a safe default) — confirm the exact minimum in the live API reference before relying on it:

python
import json, uuid, boto3
data = boto3.client("bedrock-agentcore")              # DATA plane
session_id = str(uuid.uuid4())                        # >= 33 chars; reuse for one conversation

resp = data.invoke_agent_runtime(
    agentRuntimeArn="arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/MyAgent-XXXX",
    runtimeSessionId=session_id,
    payload=json.dumps({"prompt": "What's the weather?"}).encode(),
    qualifier="DEFAULT",
)
print(json.loads("".join(c.decode("utf-8") for c in resp.get("response", []))))

One ownership rule you must not miss: AWS does NOT map sessions to users. As the AWS docs put it, "your client backend should maintain the relationship between users and their session IDs." Picking session IDs, reusing them for continuity, and enforcing per-user session caps is your responsibility — the platform only sees opaque IDs.

A session remains valid until the AgentCore Runtime ARN is deleted, but its microVM is ephemeral: it is torn down (and its memory sanitized) on idle timeout (default 15 min), at the max compute lifetime (default 8 hours), or on an explicit StopRuntimeSession. (Session isolation as a security boundary gets its own lesson; here, just hold the idea that a session = one interaction context keyed by runtimeSessionId.)

Watch out

Your backend owns the user-to-session mapping

Treat runtimeSessionId like a database key you mint and store. If you reuse one ID across two unrelated users, they share a microVM and its context — a correctness and privacy problem. Generate a unique ID per user-conversation, persist the user-to-session relationship in your own datastore, and echo the returned session ID back on follow-up calls.

Two planes: control (manage) vs data (invoke)

Every operation on a runtime lands on one of two planes, and they are genuinely separate — different endpoints, different API sets, different boto3 clients, and different IAM actions. Mixing them up is one of the most common early mistakes.

Control planemanage the resources. Region endpoint bedrock-agentcore-control.{region}.amazonaws.com. boto3 client name bedrock-agentcore-control. Operations include CreateAgentRuntime, UpdateAgentRuntime, CreateAgentRuntimeEndpoint, GetAgentRuntime, ListAgentRuntimes, and ListAgentRuntimeVersions.

Data planeinvoke the resources. Region endpoint bedrock-agentcore.{region}.amazonaws.com. boto3 client name bedrock-agentcore. The primary operation is InvokeAgentRuntime (others include InvokeAgentRuntimeCommand, InvokeAgentRuntimeWithWebSocketStream, and StopRuntimeSession). The SDK method is invoke_agent_runtime(...).

AspectControl planeData plane
PurposeCreate / update / inspect resourcesInvoke the running agent
Region endpointbedrock-agentcore-control.{region}.amazonaws.combedrock-agentcore.{region}.amazonaws.com
boto3 clientboto3.client("bedrock-agentcore-control")boto3.client("bedrock-agentcore")
Example opsCreateAgentRuntime, UpdateAgentRuntime, CreateAgentRuntimeEndpoint, Get/List…InvokeAgentRuntime, StopRuntimeSession
Governing IAM (SigV4 invoke)resource-management actionsbedrock-agentcore:InvokeAgentRuntime
python
import boto3

control = boto3.client("bedrock-agentcore-control")   # create / update / list
data    = boto3.client("bedrock-agentcore")            # invoke

# Control plane: list runtimes and inspect one
control.list_agent_runtimes()
control.get_agent_runtime(agentRuntimeId="MyAgent-XXXX")

# Data plane: invoke it (see the sessions section for the full call)
# data.invoke_agent_runtime(agentRuntimeArn=..., runtimeSessionId=..., payload=...)

For SigV4-authenticated invokes, the governing IAM action is bedrock-agentcore:InvokeAgentRuntime. (Delegated user-id invokes use a separate action, bedrock-agentcore:InvokeAgentRuntimeForUser — covered in the Identity lessons.)

Tip

The boto3 client name is the tell

If you are about to create, update, or list anything, you want boto3.client("bedrock-agentcore-control"). If you are about to invoke an agent, you want boto3.client("bedrock-agentcore"). Reaching for the wrong client surfaces as a missing-method or endpoint error — a fast signal you have crossed the plane boundary.

Watch out

OAuth-inbound runtimes can't use the AWS SDK to invoke

The data-plane example above uses SigV4. If your runtime is configured for OAuth (JWT) inbound auth instead, you cannot call InvokeAgentRuntime through the AWS SDK — you make a raw HTTPS request to the data-plane endpoint carrying the bearer token. The control-plane operations are unaffected.

Try it: Map a runtime's object model with the control and data planes

Goal: make the four-layer object model concrete by inspecting a real (or already-deployed sample) runtime with boto3, then reasoning about versions and endpoints. You do not need to deploy production code for this — pair it with whatever agent you have deployed, or use a teammate's sample runtime ARN.

Prereqs: an AWS account with an AgentCore Runtime already created, boto3 installed, and credentials with at least bedrock-agentcore:GetAgentRuntime, ListAgentRuntimes, ListAgentRuntimeVersions, and bedrock-agentcore:InvokeAgentRuntime. Set your region (one of the supported AgentCore regions — verify the live regions page).

  1. Stand up the two clients. In a Python shell or script, create both: control = boto3.client("bedrock-agentcore-control") and data = boto3.client("bedrock-agentcore"). Write a one-line comment on each explaining which plane it is and what it's for.

  2. Enumerate runtimes (control plane). Call control.list_agent_runtimes() and print each runtime's name and ARN. Confirm the ARN matches the shape arn:aws:bedrock-agentcore:<region>:<account>:runtime/<name>-XXXX.

  3. Inspect versions. For one runtime, call control.list_agent_runtime_versions(agentRuntimeId="<id>") and print each version with its status. If only V1 exists, note that CreateAgentRuntime auto-created it. (If you can, push a trivial config update through your deploy tool and re-run this — observe a NEW version appear while V1 is retained.)

  4. Find the endpoints and reason about DEFAULT. Inspect the runtime's endpoints (e.g. via control.get_agent_runtime(...) / the endpoint Get/List APIs in your SDK version). Identify the DEFAULT endpoint and write down which version it currently tracks. In a comment, predict what DEFAULT would track after one more update — and why.

  5. Invoke across a session (data plane). Generate session_id = str(uuid.uuid4()) (confirm it is >= 33 chars). Call data.invoke_agent_runtime(agentRuntimeArn=..., runtimeSessionId=session_id, payload=json.dumps({"prompt": "..."}).encode(), qualifier="DEFAULT"). Decode the streamed response. Then invoke a SECOND time reusing the same session_id and note that it shares context/microVM; invoke a THIRD time with a fresh UUID and note it does not.

  6. Reflect (write 4-5 sentences). (a) Which boto3 client did each step use, and why? (b) If a future update broke production, exactly which endpoint would you re-point, to which version, and why is that zero-downtime? (c) Where in YOUR system would you store the user-to-session-ID mapping, given that AWS does not? (d) When would you stop relying on DEFAULT and pin a custom endpoint via the qualifier instead?

Key takeaways

  1. 1An agent runtime resource is the containerized app, created via `CreateAgentRuntime` on the control plane and addressed by an agent runtime ARN like `arn:aws:bedrock-agentcore:<region>:<account>:runtime/<name>-XXXX`. It is versioned and holds no live conversation state.
  2. 2Versions are immutable config snapshots (image + protocol + network). `CreateAgentRuntime` auto-creates V1; every `UpdateAgentRuntime` mints a new version and never mutates an old one — which is what makes rollback a simple re-point.
  3. 3Endpoints (aliases) point to a specific version and each has its own ARN. The auto-created `DEFAULT` endpoint always tracks the latest version; custom endpoints (via `CreateAgentRuntimeEndpoint`) let you pin a version, and you choose one at invoke time with the `qualifier` parameter.
  4. 4Endpoints move through `CREATING` / `CREATE_FAILED` / `READY` / `UPDATING` / `UPDATE_FAILED`, and re-pointing an endpoint is zero-downtime.
  5. 5A session is one interaction context keyed by a caller-supplied `runtimeSessionId` (>= 33 chars; generated if omitted). Reuse the ID for one conversation; AWS does NOT map sessions to users — your backend owns that relationship.
  6. 6Two planes, two boto3 clients: control plane `bedrock-agentcore-control` (Create/Update/Get/List AgentRuntime[Endpoint]) for managing resources, and data plane `bedrock-agentcore` (`InvokeAgentRuntime`) for invoking them.
  7. 7The SigV4 IAM action that governs invocation is `bedrock-agentcore:InvokeAgentRuntime`; quotas (1,000 runtimes/account, 1,000 versions/agent, 10 endpoints/agent) are volatile — verify the live limits page.

Quiz

Lock in what you learned

Check your understanding

0 / 4 answered

1.You deploy an agent, then push three code changes over a week, each via UpdateAgentRuntime. A change in the third update breaks production. What does the object model let you do, and why?

2.Your client backend invokes a runtime without passing a qualifier. What gets executed, and what is the risk?

3.Two unrelated end users hit your agent and you reuse the same runtimeSessionId for both. What happens, and whose responsibility was it to prevent it?

4.You want to list a runtime's version history from Python, then invoke the agent. Which boto3 clients do you use, in order?

Go deeper

Hand-picked sources to keep learning