Lakshya

LLM Systems Engineering · Chapter 9 of 20

AgentCore in practice — the contract, the code, the limits

What your container must actually do, how it is deployed and configured, and the numbers to know before you commit.

7 min read1 diagramAll 20 chapters

AgentCore reached general availability on 13 October 2025, and the older product it replaces — now called Bedrock Agents Classic — closes to new customers on 30 July 2026 with a documented migration path. So this is the successor product, not an add-on, and material written before late 2025 describes something else.

The contract your code has to satisfy

WHAT “WORKS WITH ANY FRAMEWORK” ACTUALLY MEANS — FOUR WAYS TO BE CALLED, NOT A LIBRARY PROTOCOLPORTPATHFORMATHOW A QUOTA ERROR ARRIVES HTTP8080/invocations POST · /ping GETJSON, or a streamed replyHTTP 402MCP8000/mcpJSON-RPCJSON-RPC −32003, HTTP 200A2A — agent to agent9000/JSON-RPC 2.0HTTP 429AG-UI — agent to interface8080/invocations or /wsstreamed / WebSocketa different stream code THAT LAST COLUMN IS ONE ERROR, FOUR SHAPES. The same ServiceQuotaExceededException. A shared client cannot handle “the protocol contract” uniformly — write per-transport handling. AND THE HTTP CASE IN DETAIL · bind 0.0.0.0:8080 — and build for ARM64 — the chip family Apple Silicon and AWS Graviton use, and the opposite of Azure’s requirement· /ping answers Healthy or HealthyBusy — the second keeps a session alive while work happens in the background· errors are native HTTP status codes, not a wrapped envelope: 400, 401, 402, 403, 404, 409, 424, 429, 500 The documented trap: do not refresh the last-update timestamp on every ping. It defeats the idle timeout, so sessions never expire and you silently exhaust your session quota instead.
The agnosticism is real but shallow. AgentCore never inspects what is inside your handler — only that the container answers the right paths on the right port.

For the common HTTP case, the SDK wrapper implements /ping and /invocations for you, so the whole contract collapses to one decorated function:

pythonbedrock-agentcore SDK · docs.aws.amazon.com/bedrock-agentcore — runtime-get-started-cli
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from strands import Agent

app = BedrockAgentCoreApp()
agent = Agent()

@app.entrypoint
def invoke(payload):
    user_message = payload.get("prompt", "Hello")
    result = agent(user_message)
    return {"result": result.message}

if __name__ == "__main__":
    app.run()

That agent() call is the whole point. It could equally be a LangGraph .invoke(), a CrewAI .kickoff(), or a hand-written loop. AgentCore does not care — which is exactly why “it supports my framework” is a weaker claim than it sounds, and true of all three providers.

Deploying it

The current documented path is the agentcore CLI, which uses AWS CDK — the Cloud Development Kit, which turns code into AWS templates — underneath, and supports two build types: a zip file to storage, needing no Docker, or a container image — and only ARM64 images will run.

shellthe npm/CDK path current docs point to
npm install -g @aws/agentcore

agentcore create --name MyAgent --framework Strands --model-provider Bedrock
#   writes agentcore/agentcore.json   (configuration)
#          agentcore/aws-targets.json (account and region)
#          app/MyAgent/main.py        (the entrypoint above)

agentcore dev       # local server on :8080, mimics the runtime contract
agentcore deploy    # synthesises and applies CloudFormation via CDK

Then invoke it from your own code like any other AWS service:

pythonboto3
import boto3, uuid, json

client = boto3.client("bedrock-agentcore")

response = client.invoke_agent_runtime(
    agentRuntimeArn = "arn:aws:bedrock-agentcore:...:runtime/MyAgent",
    runtimeSessionId = str(uuid.uuid4()),   # the session boundary — see below
    payload = json.dumps({"prompt": "summarise this ticket"}),
)

Note the tooling churn, because it tells you something.

Material published only months ago shows a separate Python bedrock-agentcore-starter-toolkit with agentcore configure and launch commands. Both exist; the npm and CDK path is what current documentation points to.

The deployment tooling changed inside thirteen months of GA. That is not a criticism — it is the expected state of a one-year-old category — but it means you should check the current quickstart rather than trusting a tutorial, including this one.

Sessions, and the numbers that decide your design

Every session runs in its own microVM, not a shared container. That is the isolation you are paying for, and it is why the limits below are per-session rather than per-service.

DimensionValueWhy it matters
Idle timeout15 min, configurableWhen a session is reclaimed
Max session lifetime8 hoursThe real answer to “can it run a long task”
Synchronous request15 minutes, hardAnything longer must be async or streamed
Streaming connection60 minutes—
Asynchronous job8 hoursThe ceiling to quote in a design review
Hardware2 vCPU / 8 GB, fixedNot configurable. A hard ceiling, not a default
Payload100 MB (10 MB per stream chunk, 64 KB per WebSocket frame)—
Session storage1 GB—

And watch the quota trajectory rather than the quota. InvokeAgentRuntime went from 25 requests per second at launch, to 200, to 1,000 within a year; concurrent sessions went from 1,000 to 5,000 in the largest regions. A service whose limits triple twice in twelve months was under-provisioned for real traffic at launch, which is worth knowing before you plan against today's number.

The rest of the suite, briefly

  • Memory — short-term events retained 7 to 365 days, plus long-term records produced by strategies you attach: semantic, user-preference, summarisation, episodic. A background process extracts from the short-term stream into a namespace you define. Maximum six strategies per memory resource.
  • Gateway — turns your existing functions and web APIs and existing tool servers into one endpoint an agent can call. It speaks MCP, the Model Context Protocol — the emerging standard for how an application offers tools to a model. Its genuinely useful feature is that it handles authentication in both directions: it checks who is calling in, and it signs in to the backend service on that caller's behalf on the way out.
  • Identity — every agent is a workload identity, with three token functions covering machine-to-machine and two on-behalf-of-user paths. Three-legged OAuth is the recommended pattern for acting as a user, because it forces explicit consent and scoped delegation rather than the agent inheriting broad access.
  • Browser and Code Interpreter — sandboxed, ephemeral environments, billed like Runtime. These exist because “give the model a computer” is a recurring pattern that is expensive and risky to build from raw containers. That is the value, not novelty.
  • Observability — built on OpenTelemetry, the open standard for traces and metrics, feeding CloudWatch. Strands, LangChain and CrewAI already emit it in the agreed format, so those work with almost no extra code of your own.

One design note worth taking from the changelog: as of July 2026 spans can go to a per-agent CloudWatch log group rather than a shared one. That change exists because the shared-log-group design did not survive contact with enterprise access control — if several teams' agents write to one log group, you cannot scope permissions or encryption per team. Worth designing for on day one.

Check yourself

What must an AgentCore container actually do?Bind 0.0.0.0:8080, be built for ARM64, answer POST /invocations with JSON or a streamed reply, and answer GET /ping with Healthy or HealthyBusy.
What is the documented ping trap?Refreshing the last-update timestamp on every ping. It defeats the idle timeout, so sessions never expire and you silently exhaust your session quota.
How does one quota error surface across the four protocols?Four different ways — HTTP 402, JSON-RPC −32003 inside an HTTP 200, HTTP 429, and a different stream code. One client cannot handle all four the same way.
What is the longest a task can run?8 hours asynchronous. Synchronous requests are capped at 15 minutes, streaming connections at 60.
What is the hardware ceiling?2 vCPU and 8 GB per session, fixed — not a default you can raise.
What does the quota history tell you?Invoke rate went 25 → 200 → 1,000 TPS inside a year. A service whose limits triple twice in twelve months was under-provisioned at launch — plan against the trajectory, not today's number.
Why did per-agent log groups appear in 2026?Because a shared log group makes it impossible to scope permissions or encryption per team. Design for it from the start.
← Managed agent runtimes — what you are actually buyingRunning an open-weight model yourself →