翻訳待ち:From Legacy Bedrock Agents to Strands Agents on Bedrock AgentCore Runtime
AI サービスが一時的に利用できないため、復旧後に翻訳を補完します。ソース概要:Back to Blog December 2025 When AWS announced Amazon Bedrock AgentCore as the next evolution of their agent infrastructure, we knew it was time to take a hard look at our architecture. At Hypertrail, we’d built our enti…
AI サービスが一時的に利用できないため、復旧後に翻訳を補完します。
Back to Blog December 2025 When AWS announced Amazon Bedrock AgentCore as the next evolution of their agent infrastructure, we knew it was time to take a hard look at our architecture. At Hypertrail, we’d built our entire AI automation platform on Bedrock Agents, the only available solution when we started the platform. Now we had to figure out how to migrate. This blog post tells that story. It highlights the challenges we encountered, the solutions we found, and ultimately the value of our new runtime and how it positions Hypertrail perfectly for building the future of Agentic AI for the enterprise. What We Were Working With Hypertrail is a Context-first AI Agent platform. Our customers use it to build and deploy agentic Micro-use cases which are single-responsibility agentic use cases deployed for high-volume traffic powered by their Enterprise systems. In a nutshell, Hypertrail makes it easy for enterprises to connect Enterprise systems events in real time (think high volume booking, purchase, clickstream, employee records…) and trigger large parallel agentic use cases. We use a proprietary context storage layer allowing agents to access “digital twins” from their enterprise systems so that they always have the full business context needed to take the right action, for the right use case at the right time. Read more in our latest blog post. For example, a retail brand can ingest real-time purchase events from their Point of Sales system, update the customer profile with the purchase and have agents generate and serve real-time personalized ads based on customer profile, purchase history and shopping mission intent. To achieve this, customer create Micro-agents. Each customer creates dedicated micro-agents for each use case via our no-code interface. Behind the scenes, each agent maps to a Bedrock Agent that: Receives natural language prompts for each enterprise system event. Decides which tools to invoke (tools execution runs on AWS Lambda) Executes actions against customer systems and public tools Returns structured responses with full observability The Hypertrail platform is primarily written in Go using the Amazon Bedrock Agent Go SDK. As we knew early on that we were building on early unproven tech that was likely to change quickly, we had the forethought to put Amazon Bedrock behind a clean interface (one of our best early design decisions). We will see later how this helped smooth the migration over. type IAgentConfig interface { CreateAgent(agentName, description, instructions, model string, options AgentOptions) (Agent, error) DeleteAgent(agentId string) error InvokeAgent(agent Agent, sessionID, memoryID, input string) (AgentResponse, error) CreateApiActionGroup(agent Agent, name, description, schemaBucket, schemaPath, lambdaArn string) error // ... 15+ methods } Why We Needed to Move After re:Invent 2025, it had become clear that Amazon Bedrock AgentCore was where AWS was planning to concentrate most of their Agentic tooling investments. Announcements like A2A support, native MCP, Policies, native browser tools and many others made it clear that we were missing out on capabilities and needed to migrate fast. AgentCore Runtime represents a significant shift in how AWS thinks about agents. Less managed, supports multiple open source frameworks like LangChain and Strands, it offers more flexibility and control at the expense of a more complex development experience. What ChangedBedrock AgentsAgentCore RuntimeDeploymentLambda-backedECS-backedCustomizationConfigurationFull code control via open source frameworksTool ProtocolProprietaryMCP (Model Context Protocol)ObservabilityIn-stream tracesOpenTelemetry Being new to AgentCore, we got started by asking Anthropic Claude Opus to analyze our architecture and recommend a migration path. The key recommendations: Use the Strands Agents SDK—a Python framework that runs natively on AgentCore. Opus suggested thta using langchain, while more feature-rich, might introduce unnecessary complexity compare to Strands. Use AgentCore Gateway for tool discovery via MCP. Note that, strangely, Opus did not recommend Gateway originally, we had to introduce the idea in the prompt. Keep the Go interface, but wrap the Python runtime behind it. Essentially, we use the AgentCore Go SDK to invoke the agent allowing us to stay compatible with the current implementation. The Strands Agent code itself is written in Python and running in a container executed by the AgentCore Runtime. (We prefer the AgentCore runtime to a standard container runtime like ECS because we assume AWS has and will further optimize it leading to lower run cost and more efficient implementation) Implement dual observability to maintain API compatibility. The current version of Hypertrail parses the agent traces at runtime and stores them directly in DynamoDB. AgentCore has been designed to support Open-Source observability standards and has a native AWS CloudWatch implementation. We will discuss later in this post why we chose to keep both our native DynamoDB trace storage and CloudWatch and how we ended up implementing. We explicitly instructed Opus NOT to change anything and to start by creating a design document. After a little back and forth, Opus came up with this architecture that seemed sound. ┌─────────────────────────────────────────────────────────────────┐ │ Go Client (nm-core/strands/go) │ │ │ │ StrandsAgentConfig implements bedrock.IAgentConfig │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ bedrockagentcorecontrol (Control Plane) │ │ │ │ - CreateAgentRuntime (dynamic deployment) │ │ │ │ - UpdateAgentRuntime (update config) │ │ │ │ - DeleteAgentRuntime (cleanup) │ │ │ │ - ListAgentRuntimes │ │ │ └─────────────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ bedrockagentcore (Data Plane) │ │ │ │ - InvokeAgentRuntime │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Amazon Bedrock AgentCore Runtime (AWS Managed) │ │ │ │ • Serverless, auto-scaling │ │ • Session isolation (dedicated microVMs) │ │ • Built-in CloudWatch observability │ │ • Session persistence │ │ │ │ │ ▼ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Python Agent (Container on ECR) │ │ │ │ │ │ │ │ BedrockAgentCoreApp + Strands Agent │ │ │ │ - Configured via environment variables │ │ │ │ - Lambda tools │ │ │ │ - Knowledge base tool (OpenSearch) │ │ │ │ - Bedrock models │ │ │ └──────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ Directory Structure Hypertrail is built on 3 main level of abstractions: 1/ At the top, we have functional use cases which include Hypertrail business logic directly triggered by API calls 2/ These business use cases share common logic via a nm-common package. 3/ All interactions with AWS services (including our legacy Amazon Bedrock implementation) are abstracted via an nm-core package. This has many benefits: It allows us to change implementations when AWS releases new services or non-backward compatible upgrades (the case of this blog post). It facilitates integration tests via advanced mocks. As a result we just needed to create a new implementation of our IAgentConfig interface in nm-core. This made the migration easy. ┌───────────────────────────────────────────────────────────────────────────┐ | Hypertrail Use Cases | | (InvokAgent, Create Trail...) │ | ┌─────────────────────────────────────────────────────────────────┐ │ | │ Hypertrail Common │ │ | │ ┌─────────────────────────────────────────────────────────┐ │ │ | │ │ Hypertrail Core │ │ │ | │ └─────────────────────────────────────────────────────────┘ │ │ | └─────────────────────────────────────────────────────────────────┘ │ └───────────────────────────────────────────────────────────────────────────┘ Here is the code structure of our strand implementation nm-core/strands/ ├── go/ # Go client │ ├── strands.go # StrandsAgentConfig implementation │ ├── strands_types.go # Request/response types │ ├── strands_mock.go # Mock for testing │ ├── strands_test.go # Unit tests │ └── strands_integration_test.go # Integration tests │ ├── agent/ # Python agent (for ECR deployment) │ ├── agent.py # BedrockAgentCoreApp entrypoint │ ├── tools/ # Tool definitions │ │ ├── lambda_tool.py # Lambda action invocation │ │ └── knowledge_base.py # OpenSearch RAG tool │ ├── Dockerfile # ARM64 container │ └── requirements.txt │ ├── deploy.sh # Deploy base container to ECR ├── deploy-local.sh # Run agent locally for testing ├── test.sh # Test runner └── README.md # The readme file Note that AWS offers a way to import existing Bedrock Agents into AgentCore but Hypertrail customers don’t use pre-configured agents. They create dedicated micro-agents through our platform at runtime. We needed to create agents programmatically, not import already created ones. The Implementation We started our AgentCore migration by implementing IAgentConfig for Strands. // strands.go type StrandsAgentConfig struct { controlClient *bedrockagentcorecontrol.Client dataClient *bedrockagentcore.Client baseContainerURI string runtimeRoleArn string runtimeCache map[string]string } // static type check var _ bedrock.IAgentConfig = &StrandsAgentConfig{} With this in place, our existing backend code continued to work unchanged (plus-or-minus a few small non-backward compatible tweaks we had to make). // This call works with BOTH implementations responses, err := services.LlmService.CallAgents( bedrock.Agent{ID: persona.AgentID}, requestedModels, prompt, sessionID, sessionAttributes, ) For this to work we had to create additional resources on AWS side that the Amazon bedrock implementation did not need. This includes: A new IAM role to be assumed by the AgentCore with the permissions to create/get the AgentCore runtime, Gateways. The calling compute (Lambda in our case) needs permission to pass this role to AgentCore. If you don’t provide the PassRole permission, you will get an undescriptive 403 error while calling your agent. This error comes all the way at the end when everything else is working which is rather frustrating An ECR Repository to store the agent container image. A test Lambda function to run integration tests with “real” actions. The Lambda function would support 2 tools: a Calculate tool and an Echo tool allowing us to verify that the agent is configured correctly and successfully calls the tools. We created the following Test CDK stack to be able to fully run integration tests proving that our new implementation reproduces the exact same behavior as our legacy one. export class StrandsTestInfraStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // ECR Repository for Strands Agent container const ecrRepo = new ecr.Repository(this, 'StrandsAgentEcrRepo', { imageScanOnPush: true, removalPolicy: cdk.RemovalPolicy.DESTROY, // For test environment lifecycleRules: [ { maxImageCount: 10, // Keep last 10 images }, ], }); // IAM Role for AgentCore Runtime const agentCoreRuntimeRole = new iam.Role(this, 'AgentCoreRuntimeRole', { description: 'IAM role for Strands AgentCore Runtime (dev)', assumedBy: new iam.ServicePrincipal('bedrock-agentcore.amazonaws.com'), managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonBedrockFullAccess'), iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchLogsFullAccess'), iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ContainerRegistryReadOnly'), ], }); // Inline policy for Lambda invocation agentCoreRuntimeRole.addToPolicy( new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['lambda:InvokeFunction'], reso [truncated for AI cost control]