---
title: "AgentCore Runtime: Where an Agent Actually Runs"
description: "An agent that thinks, calls a tool, waits, and thinks again is the wrong shape for a Lambda and the wrong thing to leave on a laptop. Amazon Bedrock AgentCore Runtime is the managed answer — a per-session microVM behind an HTTP contract. Here is what that contract actually demands, and what running an agent server-side looks like in the metrics."
canonical_url: "https://artificialcuriositylabs.ai/posts/agentcore-runtime-where-agent-runs/"
md_url: "https://artificialcuriositylabs.ai/posts/agentcore-runtime-where-agent-runs.md"
published_at: "2026-07-14T00:00:00.000Z"
tags:
  - "agents"
  - "agentcore"
  - "bedrock"
  - "runtime"
---

An agent loop is a bad fit for the two kinds of compute it is easiest to reach for. It thinks, calls a tool, waits on the result, thinks again — a session that can run for minutes and holds state the whole way. A Lambda caps out at fifteen minutes and forgets everything between calls. A process on your laptop is not an endpoint anyone else can invoke. The gap between "I have a working agent script" and "I have an agent other systems can call, that survives a long task" is exactly what AgentCore Runtime fills: a managed, per-session microVM that hosts your agent server-side and hands you an API to invoke it.

To see what that actually means, I deployed a real agent to it — a two-tier support-triage bot where Claude Haiku 4.5 classifies each ticket and answers the simple ones, and Claude Sonnet 4.6 handles the escalations. The interesting part was not the agent. It was learning what Runtime expects from the thing you hand it, and confirming — from the metrics, not the logs — what running server-side looks like.

## Runtime runs a server, not your function

This is the one idea that reframes everything else. Runtime does not call your agent function directly. It executes your entrypoint file — effectively `python main.py` — and expects that process to start a long-lived HTTP server on `0.0.0.0:8080` exposing two paths:

- `GET /ping` — a health check. It must answer `200` within **30 seconds** of startup, or the platform declares the container unhealthy.
- `POST /invocations` — the request path. Runtime forwards the caller's payload here; whatever your handler returns becomes the HTTP response.

A request flows like this:

```
platform ──POST /invocations──▶ your server (:8080)
                                    │  routes to your handler
                                    ▼
                                handler runs, returns
                                    │
                                    ▼
                        server sends the HTTP response back
```

There is a naming trap worth calling out. "Entrypoint" means two different things here. The **process entrypoint** is the command that starts the server. The **`@app.entrypoint` decorator** is a Python annotation marking which function handles `/invocations`. Only the first starts the server — you can write a flawless `@app.entrypoint` handler and still serve nothing, because no server was ever started to route to it. The `bedrock-agentcore` SDK gives you the server; you just have to actually start it:

```python
from bedrock_agentcore.runtime import BedrockAgentCoreApp
app = BedrockAgentCoreApp()

@app.entrypoint
async def invoke(payload, context):
    ticket = payload.get("prompt") or ""
    yield json.dumps(triage(ticket))   # Haiku classify → Haiku|Sonnet answer

if __name__ == "__main__":
    app.run()   # ← starts the HTTP server on :8080
```

Once you hold "it is a web server" in your head, the platform's behavior stops being surprising. Dependencies have to be present because the server imports them at startup. Startup work has to be light because startup is time-boxed at 30 seconds. The server has to bind `0.0.0.0`, not `127.0.0.1`, because the health check reaches it from outside the container. None of these are arbitrary — they all fall out of "Runtime is hosting a server for you."

## What running server-side looks like

Deployed, the agent is an endpoint. I invoke it with an API call and a session id; each session gets its own isolated microVM. The evidence that it is genuinely running server-side — and behaving the way the two-tier design intends — is in the CloudWatch metrics Runtime publishes to the `AWS/Bedrock-AgentCore` namespace: across my test invocations, 7 invocations, 7 sessions, 0 errors, and durations between 5.5 and 7.6 seconds.

That latency spread is the design showing up in telemetry. The fast end is simple tickets that Haiku classifies and answers alone; the slow end is tickets Haiku escalated to Sonnet. I never see the model tiers in the request — I see them in the shape of the duration metric. That is the payoff of running inside a platform that instruments the loop for you: the routing decision I coded is legible in the operational data without any extra work.

## Logs lie; metrics don't

The sharpest lesson came from a failure. An early version of my entrypoint, when the process started, ran the agent logic directly and printed the result — instead of starting the server. When Runtime launched it, the logic *ran*: it called Haiku, escalated to Sonnet, produced a correct answer, and printed it to stdout, which landed in CloudWatch logs. The logs showed a complete, correct response. Every invocation still returned a 502, because the process printed its answer and exited without ever starting a server.

The agent was working and broken at the same time. Reading the logs, I would have sworn it worked. The metrics said otherwise: `Errors` incremented, no successful `Invocations`. CloudWatch captures stdout, so a clean-looking log line proves your *code* ran — not that the *platform* got a response. When you are debugging a hosted agent, the logs tell you what your code did; the metrics tell you what the platform saw. Trust the second.

## The managed path is the pattern

I first deployed the hard way — packaging the zip and calling `CreateAgentRuntime` directly — specifically to see what the platform requires underneath. It requires more than the quickstart implies: dependencies vendored into the zip for ARM64 (a `requirements.txt` is not installed for you), no stale `__pycache__` bytecode, imports kept light enough to clear the 30-second startup window, and the explicit `0.0.0.0` bind. Every one of those is a packaging chore, not agent logic — and the `agentcore` CLI absorbs all of them. Deploying the same agent with `agentcore deploy` worked on the first attempt, because the CLI vendors the dependencies, sets the flag that makes the server bind correctly, wires the entrypoint command, and provisions the runtime as a CloudFormation stack. The raw path is worth understanding once, to know what the platform actually demands; the CLI is the pattern you should actually deploy with.

## What's missing

I have proven the agent runs server-side and I have the metrics to show it. The claim I have not tested is the cost model. Runtime bills per second and says it does not charge for the time an agent spends waiting on I/O — which, for an agent that is mostly blocked on a model response, should be most of its wall-clock life. My two-tier agent spends the bulk of each invocation waiting on Haiku and then Sonnet. Whether that idle time is genuinely free, and how per-second billing lands for a workload that is mostly waiting, is the measurement I want to make next and have not.

## So what

Runtime answers a specific question: where does the agent loop actually execute, once it outgrows a laptop and a Lambda is the wrong shape? The answer is a managed server-side microVM — and the price of that is a contract. Your agent is a web server now: it starts fast, binds where the platform can reach it, and answers over HTTP. Deploy with the CLI and the contract is mostly handled for you. Either way, when something looks wrong, read the metrics before the logs — the logs will happily show you a perfect answer the caller never received.

---

*Part of a series working through Amazon Bedrock AgentCore by building on it. Start with [The AgentCore Map](https://artificialcuriositylabs.ai/posts/the-agentcore-map) for the full picture — Runtime is the "where does the loop run" organ in that map. See also [Two Ways to Authorize an Agent Tool](https://artificialcuriositylabs.ai/posts/authorizing-agent-tools-iam-vs-oauth), [Who May Call What](https://artificialcuriositylabs.ai/posts/per-user-authorization-cedar), and [Two Things I Almost Called AgentCore Gaps](https://artificialcuriositylabs.ai/posts/where-agentcore-sits).*
