DevOps
AWS Bedrock AgentCore Guide: Runtime, Gateway, Memory, Policy
October 202612 min read

AWS Bedrock AgentCore is a set of modular services for running AI agents in production: the harness and Runtime for executing the agent loop, Memory for context, Gateway and Identity for tool access, plus Code Interpreter, Browser, Observability, Evaluations and Policy. Each service can be used on its own or together, with any framework and any foundation model.
The harness is a managed agent loop: you declare the model, system prompt and tools in configuration and AgentCore runs the orchestration for you. Runtime hosts your own agent code, written in a framework such as OpenAI Agents SDK, LangGraph, Strands or Google ADK. Start with the harness and move to Runtime when you need orchestration logic the configuration cannot express.
Yes. Wrap the agent in BedrockAgentCoreApp from the bedrock-agentcore Python SDK, register an async entrypoint that calls Runner.run, and deploy with the AgentCore CLI using the OpenAIAgents framework option. The SDK implements the HTTP contract of POST /invocations and GET /ping on port 8080.
By default a session stops after 15 minutes of inactivity or after a maximum lifetime of 8 hours on microVMs, and Runtime Instances support sessions of up to 14 days. Each session runs in its own microVM, and in-memory or local disk state is lost when it stops unless you configure session storage. Use AgentCore Memory or your own database for anything that must outlive the session.
No. Asia Pacific (Jakarta), ap-southeast-3, is not listed in the AgentCore region table. Asia Pacific (Singapore) supports nearly every AgentCore service, including the harness, Runtime, Memory, Gateway and Policy, so it is the usual choice for teams in Indonesia.

Key Takeaway
AWS Bedrock AgentCore is a set of separately usable agent services: the harness and Runtime run the loop, Memory stores context, Gateway and Identity expose tools, Policy enforces Cedar rules outside the prompt. Any framework, including OpenAI Agents SDK, deploys to Runtime. AgentCore is not offered in Jakarta, so Indonesian teams typically deploy to Singapore.
Consider a distributor in Surabaya that already runs its ERP integrations on AWS: Lambda functions in front of the purchasing module, Cognito for the internal portal, CloudWatch for everything. The team has a working procurement assistant built with the OpenAI Agents SDK on a developer laptop, and the question is where it should run in production without building session isolation, tool authentication and audit logging from scratch. AWS Bedrock AgentCore is the answer AWS offers, and the first thing to understand is that it is not one product but a set of modular services that can be adopted one at a time.
This guide explains what each AgentCore service does, when the managed harness is enough and when you deploy your own code to Runtime, how to ship a framework-agnostic agent with the AgentCore CLI, how sessions, Gateway and Policy behave, and what region availability means for a team in Indonesia. Every limit and flag below comes from the AWS developer guide, the AWS Machine Learning blog and the CLI reference as of October 2026.
AWS describes AgentCore as an agentic platform whose services work together or independently, with any open-source framework and any foundation model. That independence is the important design choice. You can run an agent on Runtime and keep your own memory store, or use only Gateway to expose existing APIs as MCP tools to an agent that runs somewhere else. The nine services most teams evaluate first are these.
| Service | What it does | Reach for it when |
|---|---|---|
| Harness | A managed agent loop: model, system prompt and tools declared in configuration, each session in an isolated microVM with filesystem and shell access | You want a working agent without writing orchestration code |
| Runtime | Serverless hosting for your own agent code, with per-session microVM isolation and HTTP, MCP, A2A and AG-UI protocol contracts | You already have an agent in LangGraph, Strands, Google ADK or OpenAI Agents SDK |
| Memory | Short-term turn history per session plus long-term records extracted by strategies such as semantic, user preference, summary and episodic | Context must survive the end of a session |
| Gateway | Turns OpenAPI specs, Smithy models and Lambda functions into MCP tools and fronts existing MCP servers | Your tools are internal APIs that should not be called with raw credentials |
| Identity | Inbound and outbound authentication for agents, working with existing IdPs such as Cognito, Okta, Entra ID and Auth0 | The agent acts on behalf of a signed-in user |
| Code Interpreter and Browser | A sandbox for Python, JavaScript and TypeScript, and a managed cloud browser that works with Playwright and Browser Use | The agent must calculate, transform files or operate a web UI |
| Observability | Step-level traces and metrics in CloudWatch, emitted in OpenTelemetry-compatible format | Always, from the first deploy |
| Evaluations | Scores sessions, traces and spans from Strands or LangGraph agents instrumented with OpenTelemetry or OpenInference | You need a quality signal before and after a release |
| Policy | A policy engine attached to Gateway that evaluates every tool call against Cedar-compatible rules before it runs | Some tool calls carry money, approvals or customer data |
The developer guide also lists newer services that sit around this core: Payments for x402 and Machine Payments Protocol transactions, Optimization for prompt and tool-description A/B tests, and a Registry that catalogues agents, MCP servers and skills. They are useful later; none of them is required to put a first agent into production. Pricing is consumption-based with no upfront commitment, and Runtime compute is billed at USD 0.0895 per vCPU-hour and USD 0.00945 per GB-hour of active consumption according to the harness GA announcement.
The harness reached general availability on 18 June 2026, and it changes the first decision. With the harness you do not write an agent at all. You declare the model, the system prompt and the tools, and AgentCore runs the reasoning loop, tool execution, memory and response generation. The CLI scaffolds a harness project by default; the tools section is the part worth reading closely.
# Harness path: the agent is configuration, AgentCore runs the loop.
npm install -g @aws/agentcore
agentcore create # wizard: choose "Harness"
agentcore deploy
agentcore invoke --prompt "Summarise yesterday's open purchase requisitions"
# The tools block of the harness config. Each entry is a managed
# capability or an endpoint; there is no orchestration code to write.
"tools": [
{ "type": "agentcore_browser" },
{ "type": "agentcore_code_interpreter" },
{ "type": "remote_mcp",
"config": { "remoteMcp": { "url": "https://mcp.example.co.id/mcp" } } },
{ "type": "agentcore_gateway",
"config": { "agentCoreGateway": { "arn": "arn:aws:bedrock-agentcore:..." } } }
]The harness supports Amazon Bedrock models, the OpenAI API directly, Google Gemini and LiteLLM-compatible providers. Its documented defaults matter because they decide what happens when you leave a field out.
Start with the harness and graduate only when you hit a wall. The CLI includes an agentcore export command that turns a harness into a Strands runtime agent, so a prototype is not a dead end. Move to Runtime when you need orchestration the configuration cannot express, such as deterministic approval steps between tool calls or a framework your team already tests against.
Runtime is framework-agnostic because its contract is plain HTTP. For the HTTP protocol your server listens on 0.0.0.0 port 8080, accepts POST on /invocations with a JSON body and returns JSON or Server-Sent Events, and answers GET on /ping with a health status. The bedrock-agentcore Python SDK implements that contract, so an existing OpenAI Agents SDK agent needs only a thin wrapper.
# app/ErpAssistant/main.py
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from agents import Agent, Runner, function_tool
app = BedrockAgentCoreApp()
@function_tool
def open_purchase_orders(vendor_code: str) -> list[dict]:
"""Read-only lookup. Writes go through Gateway, where Policy can see them."""
return erp_client.open_pos(vendor_code)
agent = Agent(
name="Procurement assistant",
instructions="Answer purchasing questions. Never create or approve documents.",
tools=[open_purchase_orders],
)
# The decorator registers this as the POST /invocations handler.
# BedrockAgentCoreApp also answers GET /ping on port 8080 for you.
@app.entrypoint
async def invoke(payload, context):
prompt = payload.get("prompt", "")
result = await Runner.run(agent, prompt, max_turns=8)
return {"result": result.final_output}
if __name__ == "__main__":
app.run()The AgentCore CLI is now an npm package that needs Node.js 20 or later, plus Python 3.10 or later for the agent code. Its create command accepts Strands, LangChain_LangGraph, GoogleADK, OpenAIAgents and VercelAI as frameworks, and Bedrock, Anthropic, OpenAI and Gemini as model providers. Deployment is AWS CDK underneath.
agentcore create \
--project-name ProcurementAgents \
--name ErpAssistant \
--language Python \
--framework OpenAIAgents \
--model-provider OpenAI \
--memory none \
--build CodeZip # zip to S3, no Docker needed
agentcore add credential # stores OPENAI_API_KEY for the deployed runtime
agentcore dev # local server + agent inspector, hot reload
agentcore deploy --dry-run # see what CDK will create first
agentcore deploy
agentcore status # prints the agent runtime ARN
agentcore logs --since 30m --level errorTwo details save time. The default CodeZip build uploads a zip to S3 and needs no Docker; if you choose the Container build, the image must be ARM64, which is the first thing to check when a container that runs on an x86 laptop fails health checks after deploy. And on Windows, an older agentcore command from the bedrock-agentcore-starter-toolkit pip package can shadow the npm CLI on PATH, so uninstall it before you trust the version output.
Every Runtime session gets its own microVM with isolated compute, memory and filesystem, and the microVM is terminated and its memory sanitised when the session ends. A session stops after 15 minutes of inactivity by default or after a maximum lifetime of 8 hours on microVMs, configurable between 60 and 28,800 seconds through the CLI. The session ID you pass must be at least 33 characters, and reusing it is what routes a request back to the same warm microVM.
import json
import boto3
client = boto3.client("bedrock-agentcore", region_name="ap-southeast-1")
# AgentCore does not map sessions to users. Your backend does.
# The id must be at least 33 characters; a short one is rejected.
session_id = f"tenant-{tenant_id}-user-{user_id}-{conversation_uuid}"
response = client.invoke_agent_runtime(
agentRuntimeArn=AGENT_ARN,
runtimeSessionId=session_id, # same id = same microVM, warm context
payload=json.dumps({"prompt": "Which POs for V0042 are overdue?"}).encode(),
qualifier="DEFAULT",
)
body = b"".join(chunk for chunk in response["response"]).decode("utf-8")
# Wrong: a fresh uuid4() per request. Every call lands on a new microVM,
# pays a cold start, and loses whatever the agent held in memory.Anything the agent keeps in process memory or on local disk disappears when the microVM stops. A stopped session can resume on the next invoke with a fresh microVM, but only data in a configured session storage mount survives that cycle. Conversation history and learned facts that must outlive a session belong in AgentCore Memory or your own database. AgentCore also does not enforce which user owns which session, so a multi-tenant ERP portal must keep that mapping, and a per-user session limit, in its own backend.
If your agent reports background work through the ping endpoint, return HealthyBusy only while the work runs, and never refresh time_of_last_update on every ping. The developer guide warns that a timestamp advancing on each ping looks like a continuous status change, so the idle timeout never fires, sessions live until the 8-hour maximum and can exhaust your session quota. The SDK handles ping for you; hand-written servers are where this bites.
Gateway is the part of AgentCore that most directly fits an existing AWS estate. A Lambda function that already wraps the purchasing API becomes an MCP tool by registering it as a gateway target with a tool schema. Inbound, the gateway acts as an OAuth resource server and validates tokens from your IdP. Outbound, Lambda and Smithy targets use an IAM role, while OpenAPI targets use an API key or OAuth client credentials.
import boto3
control = boto3.client("bedrock-agentcore-control", region_name="ap-southeast-1")
# Inbound: Gateway is an OAuth resource server. Point it at your IdP.
gateway = control.create_gateway(
name="erp-tools",
roleArn=GATEWAY_ROLE_ARN,
protocolType="MCP",
authorizerType="CUSTOM_JWT",
authorizerConfiguration={
"customJWTAuthorizer": {
"allowedClients": [COGNITO_APP_CLIENT_ID],
"discoveryUrl": COGNITO_DISCOVERY_URL,
}
},
)
# Outbound: a Lambda that wraps the ERP API becomes one MCP tool.
# The schema is the contract the model sees; keep it narrow.
control.create_gateway_target(
gatewayIdentifier=gateway["gatewayId"],
name="PurchaseOrders",
targetConfiguration={
"mcp": {
"lambda": {
"lambdaArn": PO_LAMBDA_ARN,
"toolSchema": {
"inlinePayload": [{
"name": "create_po_draft",
"description": "Create a DRAFT purchase order. Never posts.",
"inputSchema": {
"type": "object",
"properties": {
"vendorCode": {"type": "string"},
"amountIdr": {"type": "integer"},
},
"required": ["vendorCode", "amountIdr"],
},
}]
},
}
}
},
credentialProviderConfigurations=[{"credentialProviderType": "GATEWAY_IAM_ROLE"}],
)Two consequences follow. The model never holds the ERP credential; it holds an MCP connection to the gateway, and the gateway holds the role. And because every tool call now passes one choke point, it can be logged, searched and governed in one place. For large tool catalogues the gateway also exposes a built-in x_amz_bedrock_agentcore_search tool, so the agent can find the right tool by a natural-language query instead of loading every schema into its context.
An instruction such as never create a purchase order above 50 million rupiah is a request to the model, not a control. Policy in AgentCore moves that rule to the gateway: a policy engine is attached to the gateway and every tool call is evaluated before it runs. Policies are written in Dogwood, an open-source language compatible with Cedar, so plain Cedar policies work unchanged, and they can also be drafted in natural language and then validated against the tool schema.
// Action names are <TargetName>___<tool>. No wildcards in action names,
// and the resource must be a specific gateway ARN when actions are named.
permit(
principal is AgentCore::OAuthUser,
action == AgentCore::Action::"PurchaseOrders___create_po_draft",
resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:ap-southeast-1:123456789012:gateway/erp-tools-a1b2c3"
)
when {
principal.hasTag("role") &&
principal.getTag("role") == "buyer" &&
context.input.amountIdr <= 50000000 // integer schema = Cedar Long
};
// Incident switch: forbid always beats permit.
forbid(
principal,
action,
resource is AgentCore::Gateway
);The evaluation model is short, and the third rule is the one that surprises people.
Check the enforcement mode before relying on any policy. When the gateway's policy engine configuration is set to LOG_ONLY, decisions are recorded but not enforced, and every tool call still succeeds. LOG_ONLY is the right way to test a new rule set against real traffic; leaving it on in production means your limits exist only in the logs.
The Asia Pacific (Jakarta) region, ap-southeast-3, does not appear in the AgentCore region table at all. For a team in Indonesia the practical choice is Asia Pacific (Singapore), ap-southeast-1, which supports almost every service. Malaysia is closer in coverage than people expect for Runtime, but it lacks the harness and Memory.
| Capability | Singapore | Malaysia | Jakarta |
|---|---|---|---|
| Harness | Yes | No | Not listed |
| Runtime on microVMs | Yes | Yes | Not listed |
| Runtime on Instances, sessions up to 14 days | Yes | No | Not listed |
| Memory | Yes | No | Not listed |
| Gateway, Identity, built-in tools, Policy, Evaluations, Observability | Yes | Yes | Not listed |
| Agent Registry | No | No | Not listed |
That has two operational consequences. Agent sessions, memory records and traces live in Singapore even when the ERP database stays in Jakarta, so the tool calls cross a region boundary and your data-classification review has to cover what the agent can read. And latency from the agent to a Jakarta-hosted API adds to every tool call, which favours fewer, coarser tools over many chatty ones. If certain data must not leave Indonesia, keep those tools returning summaries or identifiers rather than raw records.
At DevDay on 29 September 2026, OpenAI highlighted Bedrock Managed Agents, a limited preview first announced in April that takes on the core features of the OpenAI Agents API, can be customised for AWS and connects directly to AWS resources. It is a third option beside the harness and Runtime, aimed at teams that want OpenAI's hosted agent model while their data and governance stay inside AWS. As a preview, check its region list before planning around it; nothing in the AgentCore region table suggests a Jakarta deployment is close. A reasonable order for an AWS-first team is this.
The common mistake is to adopt everything at once. Runtime plus Observability is a complete first deployment; Memory, Gateway and Policy are added when a concrete requirement appears, which is exactly what the modular design allows.
AgentCore is easiest to reason about as separate answers to separate problems: the harness or Runtime for where the loop runs, Memory for what survives a session, Gateway and Identity for how tools are reached, and Policy for what the agent may never do. Pick the smallest set that covers today's requirement, deploy it to Singapore if you are in Indonesia, and enforce limits at the gateway rather than in the prompt.
Sources