Home / Articles

Bedrock AgentCore Hands-On: Terraform, LangGraph and the Gotchas Found

What AgentCore's Runtime, Gateway, Memory and Identity do, plus six deployment gotchas, rough pricing and a verdict versus hand-built agent hosting on AWS.

Publisher: REACTAPP.TOP9 min read2141 words

This article is published in English.

Sources: Amazon Bedrock AgentCore, What It Is, How to Use It, and What Hosting Looks Like

Hosting an AI agent on AWS by hand means solving session isolation, tool access, memory and authentication yourself. Amazon Bedrock AgentCore is the managed version of that same problem, generally available since October 2025. One practical way to judge a platform like this is to stop reading about it and build something real, and a small read-only DevOps triage agent served that purpose here. It was deployed with Terraform instead of AWS's own CLI wizard, and written with LangGraph instead of AWS's Strands SDK. Both choices were deliberate, because the point was to learn what holds up away from the paved path.

What AgentCore is

AgentCore is a bundle of managed pieces that cover the dull, load-bearing parts of running an agent in production, and it lets any existing agent framework stay in place. The any-framework promise is the headline claim and it mostly holds. LangGraph, LangChain, CrewAI, Strands and plain API calls are all accepted.

The pieces, and the job of each:

  • Runtime hosts the agent's code and gives every session an isolated microVM of its own. It scales to zero when idle and bills by the second while working.
  • Gateway turns existing Lambda functions or APIs into MCP-compatible tools that an agent can call, so no hand-written MCP server is needed.
  • Memory stores conversation history as short-term events and can optionally extract long-term semantic knowledge across sessions.
  • Identity covers two directions of authentication: who may call the agent, and what the agent may call on a user's behalf, including third-party services such as Slack or GitHub.
  • Observability sends OpenTelemetry traces to CloudWatch so there is a record of what the agent did and why.
  • A Browser tool and a Code Interpreter tool serve agents that must act on the open web or run arbitrary code.

A June 2026 AWS Summit announcement added a Harness layer and native web search. Both are still young enough that critical infrastructure should not rest on them yet.

Onboarding has already been rebuilt once. The original Starter Toolkit CLI is now legacy, replaced by a CDK-based npm package called @aws/agentcore. A tutorial that shows agentcore configure and agentcore launch as separate steps describes the old flow. The detail matters because it signals the pace of change: nine months after general availability, the getting-started path has already been redone, so anything written about the product has a shelf life.

The test project

The agent answers questions such as whether any CloudWatch alarms are firing, or what the status of a particular EC2 instance is. It has two real, read-only tools, so nothing it can use is able to change infrastructure, only observe it. It remembers the conversation across turns, and every hop between components is authenticated.

LangGraph was chosen over Strands because Strands is AWS's own framework and gets the smoothest route through every official example. Using something else was the real test of the any-framework claim, and it matched tooling already at hand. Terraform was chosen over the CLI for a similar reason. The wizard is built to get a demo running quickly, and the goal here was to see every IAM trust relationship and every connection between components, not have them generated invisibly. That visibility turned out to matter more than expected.

The architecture is a Runtime container running the LangGraph agent, which talks to a Gateway exposing two Lambda-backed tools over MCP. AgentCore Memory holds the conversation, and Cognito issues machine-to-machine tokens for each hop.

Click through before scripting

Before any Terraform was written, the console version of the setup was worked through once, mainly to see what was being automated. The habit is worth copying even when Terraform handles the real deployment, because reading the infrastructure files is much easier after having seen the forms they fill in.

The container registry deserves a manual walkthrough whatever tool handles the rest, since it is the one step Terraform cannot do. Creating the repository is a single console screen. The image, however, has to arrive some other way, since the console has no button that builds a Dockerfile. That happens in a terminal with docker buildx build for the linux/arm64 platform, followed by a push. Naming the platform by hand is the whole game. Leave it off and the image builds without complaint, then gets silently rejected when Runtime tries to start it, because Runtime runs only on Graviton.

Once the image lands, the console shows its exact URI. That string is the one piece of state that must travel from work done by hand into what Terraform knows, whether it goes into a tfvars file or into the Runtime's container image field for someone staying in the console.

The AgentCore screens for Memory, Gateway and Runtime sit in their own section of the Bedrock console. Each is a form for the same fields Terraform sets, which makes sense because Terraform calls the same API beneath.

  • Memory asks for a name and how long short-term events are kept.
  • Gateway asks for a protocol, an execution role and a method of authenticating callers. The Cognito audience-versus-client-id gotcha described below shows up right here, as a dropdown that forces a choice.
  • Runtime asks for the registry URI, a role and the same authorizer setup as Gateway.

None of it is hard once the forms are in front of you. Terraform is still the better choice for anything meant to last, because clicking through seven forms in three console sections is not a deployment process anyone wants to repeat or hand to a colleague.

Where it bit

Images must be ARM64

Runtime is Graviton-only, with no exceptions. A plain docker build on most laptops yields an amd64 image that is silently refused at deploy time. Every build needs the buildx command with the arm64 platform flag. A comment directly above the FROM line in the Dockerfile is a cheap safeguard, because it will be forgotten otherwise.

The Gateway's Lambda contract

Several blog posts show a Lambda event wrapped in an envelope with a toolName and parameters. The real event is the tool's input properties as a flat dictionary. The actual tool name comes through context.client_context.custom under the key bedrockAgentCoreToolName, prefixed with the gateway target's name and a triple-underscore delimiter. The discrepancy only surfaced by reading AWS's own Lambda-target documentation directly instead of trusting secondhand summaries. Much of what circulates about this product comes from the preview period or is simply wrong.

Cognito tokens lack an aud claim

This one took real time to reason out. With Cognito used for machine-to-machine authentication, via a client_credentials grant with no human login, Cognito issues an access token and not an ID token. Access tokens never carry aud. Only ID tokens do, and an M2M flow has no ID token since there is no user to issue one to. Configure AgentCore's JWT authorizer to check allowed_audience against such a token and the result is a 403 with no obvious reason. The fix is allowed_clients, which checks the client_id claim that Cognito access tokens do include.

boto3 cannot invoke a JWT-protected Runtime

This was the biggest surprise, and it is not a workaround but a sentence in AWS's own API reference. If the agent uses OAuth-style inbound authentication, InvokeAgentRuntime cannot be called through the AWS SDK at all. The call is instead a raw HTTPS request with a bearer token in the Authorization header, sent to a URL built by hand with the runtime's ARN percent-encoded into the path. Every boto3 example assumes the default IAM and SigV4 path. Once a custom_jwt_authorizer is configured, as it should be for anything not purely internal, that entire category of example stops applying.

A Python package conflict

The mcp Python package shipped a 2.0.0 major release that renames internal modules, while langchain-mcp-adapters has not caught up. It declares compatibility with mcp at or above 1.24.0 with no upper bound, so a plain pip install now produces a broken pairing. It at least fails loudly, with an import error and not a subtle bug. The test project pins mcp at 1.29.0. Check whether the pin is still needed, since quiet patches can turn a fix into leftover clutter.

Deployment is more than one apply

The Runtime resource needs a container image already sitting in the registry, and Terraform cannot build and push an image in its own apply. The real sequence is to create only the registry repository, build and push the image outside Terraform, and then apply everything else. Engineers on much bigger AgentCore stacks have wired CodeBuild into the Terraform graph through null_resource to close the gap. That is a reasonable next step, and a sign the rough edge is widespread and not a personal error.

Conversation state belongs in one place

Not a bug but a structural choice: the agent deliberately does not use LangGraph's own checkpointer for conversation state, though most LangGraph tutorials make it the default. Runtime sessions scale to zero and can hand over a fresh microVM between calls, so anything held only in process memory vanishes. AgentCore Memory is the durable side of that boundary. Running a local checkpointer next to Memory gives the same conversation two competing records, and sooner or later they will disagree about what was said. Choose one. Memory is the sensible pick because it survives a cold start.

What it costs

Pricing is consumption-based with no minimum, a good model for something that spends most of its time waiting on an LLM response. The consequence is that the bill is a sum of several small, separately metered items and not one number. As of writing:

  • Runtime charges roughly 9 cents for each vCPU-hour and about 1 cent for each GB-hour, metered per second with a floor of one second, so a three-second question costs three seconds and not a rounded-up minute.
  • Gateway costs roughly half a cent per thousand MCP calls.
  • Memory is priced at 0.25 cents per 1,000 events stored and 0.5 cents per 1,000 retrieved.
  • Identity carries no charge when it is used via Runtime or Gateway instead of being called directly, which applies to nearly the entire setup.

None of that includes the model calls, which for anything beyond light testing will be the largest number on the bill, and which AgentCore does not influence. That is simply what Bedrock charges for the chosen model. New accounts receive two hundred dollars in AgentCore credits, enough to build and break a project like this several times. The official pricing page should be checked before leaning on any figure, since pricing has shifted more than once since general availability and probably will again.

Managed platform or hand-built hosting

A hand-built agent hosting stack makes a useful comparison, and the honest conclusion has two sides. AgentCore delivers session isolation, a managed MCP gateway, durable memory and an auth model, wired to work together, faster than designing the IAM trust policies manually, and hours were spent on exactly those policies here. That is a large amount of undifferentiated infrastructure work taken off the plate. For anyone whose job is building the agent and not the hosting platform beneath it, the trade is probably worth making.

What the platform does not provide is judgment about what an agent should be allowed to do, how much it should cost at real scale, or whether any framework quietly means any framework with AWS's own getting the best-documented route. Stability is also missing. The CLI has been rebuilt once, and at least three points turned up where AWS documentation disagreed with the real API in small but load-bearing ways. None of that makes the product bad. It simply describes a young managed service evolving quickly, which is better known before starting than discovered halfway through a deploy.

All of it was actually built, not just described. Every resource has Terraform, the agent is complete, the Lambda tools exist, and the test suite needs no AWS credentials, so what could be verified was verified first. For a similar build, two lines are the likeliest places to hit the same wall: the ARM64 platform flag for the image, and allowed_clients in the Cognito authorizer setup.