こんにちわ。昨年末はラスベガス(AWS re:Invent)に行ったり、事務所移転があったり、決算があったりで、バタバタしっぱなしだった斧山です。
AWSでは今 Bedrock AgentCore が熱いということで、ハンズオンしないといけないなと思いつつも、全然着手できていませんでした。
とにかくやらねばならぬ、ということで正月休みにハンズオンをしてみました(といっても Claude Code が、ですが)。
自己紹介と今回のテーマ
まず、私の経歴です。
もともとはデータセンターでオンプレミスのサーバー構築・運用をしていました。主に WEB 系、ゲーム系です。そこから WEB 開発(Perl、PHP)を経て、AWS クラウドが黒船のようにやって来て、気がつけばオンプレミスをクラウドへマイグレーションしつつ、Node.js、React.js などでシステム開発をしているという、いわゆる古い人間です。
そんな自分から見ると、Bedrock AgentCore が「すごい」と言われても、
- Lambda と何が違うのか
- EC2、ECS、Fargate、App Runner とどう違うのか
が正直よく分からない。
ということで、「とにかくハンズオンしてみた記録」をまとめます。
ハンズオンと言いながら、手順というより 抽象化理解の備忘録 です。
この記事では以下を整理します
- AgentCore Runtime の正体
- Lambda / ECS との違い
- Webサーバーは必要か
- どんなケースで使うべきか
また、以下の方を対象としています。
- Bedrock / Lambda / ECS の基礎理解がある方向けです
古いインフラエンジニアがまず知りたいこと
最初に浮かんだ疑問はこれです。
多分コンテナを動かしてくれるのだろうけど、Web サーバーは要るのか?
業務では、React + Vite を CloudFront にアップロードする構成が多く、他にも WordPress や Laravel を EC2 で配信するケースがあります。その場合は Apache や Nginx をインストールして起動します。
では AI エージェントの場合はどうなのか。
- そもそも Web サーバーは必要なのか
- フロントエンドとどうやって通信するのか
- AgentCore はどこまで面倒を見てくれるのか
このあたりが全く分かりませんでした。
現在弊社では、AI エージェントは Vercel AI SDK を使用し、Lambda 上に配置して AppSync 経由で React から呼び出す構成が多いです。
それと比べて AgentCore は何が違うのか、整理してみました。
Bedrock AgentCore のサービス構成
AgentCore は一言で言っても、いくつかのサービスに分かれています。
| サービス | 役割 | 主な機能 |
|---|---|---|
| Runtime | エージェントのデプロイ・実行基盤 | サーバーレスホスティング、自動スケーリング、セッション管理 |
| Memory | 永続的なコンテキスト記憶 | イベントメモリ、セマンティックメモリ、会話履歴保持 |
| Gateway | API → MCP ツール変換 | 既存 API のツール化、認証統合、セマンティック検索 |
| Identity | 認証・認可管理 | OAuth / OIDC 統合、ユーザー代理認証、トークン管理 |
| Built-in Tools | マネージドツール | Code Interpreter、Browser |
| Observability | 監視・トレース | OpenTelemetry 統合、分散トレース、メトリクス |
| Policy | セキュリティガバナンス | Cedar ポリシー評価、アクセス制御、監査ログ |
これらはそれぞれ独立して利用可能で、必ず全部を組み合わせる必要はありません。
例えば、Lambda から AgentCore Memory だけを使う、といった構成も可能です。
※ Identity、Gateway はRuntimeと連携して使用するため、独立して使用することはできません。 ※ Policy は Gateway と連携してツール呼び出しを制御するため、独立して使用することはできません。
本記事では Runtime に焦点を当てて解説します。
Bedrock AgentCore Runtime は Strands SDK 前提?
AgentCore Runtime は、AWS が提供する Strands SDK と AgentCore SDK を使うことで、ほぼノーコードで AI エージェントをデプロイできます。
ただし、これらは基本的に Python ベース です。
- Strands SDK は TypeScript 対応が発表されたが、未実装機能が多い
- 現時点では TypeScript 版と AgentCore SDK を組み合わせて使えない
AI の世界は、機械学習の流れもあり Python 中心です。
Jupyter Notebook 上で開発する文化ですね。
ただ、
抽象化されすぎていて、何が起きているのか分からない
というのが正直な感想でした。
そこで今回は、Strands SDK / AgentCore SDK を使わず、
- Node.js
- TypeScript
- Hono.js
- Vercel AI SDK
- AWS SDK
- AWS CDK
でデプロイしてみることにしました(Claude Code が)。
Node.js / TypeScript / Hono で動かしてみた
イメージコードは以下のような感じです。
index.ts
import { serve } from '@hono/node-server';
import { Hono } from 'hono';
import { logger } from 'hono/logger';
import { ping } from './routes/ping.js';
import { invocations } from './routes/invocations.js';
// CloudWatch Logs対応:改行を除去して1行出力
const originalConsole = { ...console };
const formatForCloudWatch = (...args: unknown[]): string => {
return args
.map((arg) => {
if (typeof arg === 'string') return arg.replace(/\n/g, ' ');
try {
return JSON.stringify(arg).replace(/\n/g, ' ');
} catch {
return String(arg);
}
})
.join(' ');
};
console.log = (...args: unknown[]) => originalConsole.log(formatForCloudWatch(...args));
console.error = (...args: unknown[]) => originalConsole.error(formatForCloudWatch(...args));
console.warn = (...args: unknown[]) => originalConsole.warn(formatForCloudWatch(...args));
const app = new Hono();
// ミドルウェア - /ping はログ出力しない
app.use('*', async (c, next) => {
if (c.req.path === '/ping') {
return next();
}
return logger()(c, next);
});
// ルート
app.route('/ping', ping);
app.route('/invocations', invocations);
// AgentCore Runtimeはポート8080を使用
const port = 8080;
serve({
fetch: app.fetch,
port: port,
});
invocations.ts
import { Hono } from 'hono';
import { invokeOpenAI, type OpenAIRequest } from '../services/openai.js';
const invocations = new Hono();
interface InvocationPayload {
input: OpenAIRequest;
}
/**
* AgentCore Runtimeからのリクエストを処理するエンドポイント
*/
invocations.post('/', async (c) => {
try {
const payload = await c.req.json<InvocationPayload>();
console.log('Received invocation:', JSON.stringify(payload, null, 2));
if (!payload.input) {
return c.json(
{
result: false,
message: null,
error: 'Invalid payload: input is required',
},
400
);
}
const response = await invokeOpenAI(payload.input);
return c.json(response);
} catch (error) {
console.error('Error processing invocation:', error);
return c.json(
{
result: false,
message: null,
error: error instanceof Error ? error.message : 'Unknown error occurred',
},
500
);
}
});
export { invocations };
上記のようなコードを Docker と AWS CDK を使い、サクッとデプロイできました。
CDK でのデプロイ
CDK のコードです。
import * as cdk from 'aws-cdk-lib';
import * as agentcore from '@aws-cdk/aws-bedrock-agentcore-alpha';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as path from 'path';
export class OpenaiRuntimeStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// ローカル Dockerfile からビルド
const artifact = agentcore.AgentRuntimeArtifact.fromAsset(
path.join(__dirname, '../app')
);
// AgentCore Runtime 作成(IAM認証)
const runtime = new agentcore.Runtime(this, 'OpenAIRuntime', {
runtimeName: 'OpenAIRuntime',
agentRuntimeArtifact: artifact,
environmentVariables: {
SECRET_ARN: 'arn:aws:secretsmanager:ap-northeast-1:xxxx:secret:xxxx',
},
networkConfiguration: agentcore.RuntimeNetworkConfiguration.usingPublicNetwork(),
// IAM認証(デフォルト)
});
// Secrets Manager 読み取り権限を付与
runtime.addToRolePolicy(
new iam.PolicyStatement({
actions: ['secretsmanager:GetSecretValue'],
resources: ['arn:aws:secretsmanager:ap-northeast-1:xxxx:secret:xxxx'],
})
);
// 出力
new cdk.CfnOutput(this, 'RuntimeArn', {
value: runtime.agentRuntimeArn,
description: 'AgentCore Runtime ARN',
});
}
}
なぜ Express.js ではなく Hono.js なのか。 以前、TypeScript 対応の AI エージェントフレームワーク Mastra を触ったときに Hono が対応していて、いいなと思ったからです。それだけです。
MCP サーバーの SDK なども使うのであれば、Express.js の方が良いかもしれません。
AgentCore Runtime の単発呼び出しは Lambda とほぼ同じ
実際にデプロイして分かったことです(今回は Agent のみで、MCP や認証は割愛)。
- Runtime 側で HTTP を待ち受ける
- Runtime 内部ではコンテナが実行される
- コンテナ内部で HTTP サーバーとしてリクエストを処理する(Runtime は HTTP Proxy として処理)
Lambda URL の場合は、コード内で HTTP サーバーを立てる必要はありません。 一方、AgentCore Runtime では Express や Hono などの Web サーバーが必要 です。
つまり、
- ECS / Fargate で Web サーバーを立てる構成
- AgentCore Runtime
は実行モデルとしてはかなり近いです。
待ち受けるエンドポイント仕様は以下の通りです。
| エンドポイント | ポート | 用途 |
|---|---|---|
| /invocations | 8080 | エージェントのメインロジック |
| /ping | 8080 | ヘルスチェック |
| /ws | 8080 | WebSocket(双方向ストリーミング) |
この仕様さえ満たせば、中身は何でも動きます。
- Python に縛られない
- Node.js 以外でも OK
- Go / Rust も可能
Apache や Nginx、Tomcat を使ってPerlやJavaも理論上は可能ですが、AI 向け SDK の少なさやパフォーマンス面を考えると現実的ではなさそうです。
ちなみに AgentCore Runtime の呼び出しは認証があるため、curlなどではなく基本的には AWS SDK 経由で Lambda Invoke のように呼び出します。Cognito などで認証・認可さえ得ていれば、React などのフロントエンドからも ゼロトラスト で呼び出し可能です。
Lambda と比較して
単発呼び出しの場合、
- Lambda:最大 15 分
- AgentCore Runtime:最大 15 分
どちらもコールドスタートがあります。
そのため、単発実行だけを見ると大きな優劣はありません。
すでに Lambda 上で AI エージェントを動かしていて困っていないのであれば、無理に移行する必要はないでしょう。
どちらも、
「プログラム実行環境を AWS が用意してくれる」
という点では同じです。
では何が違うのか
Lambda や ECS で十分では?と思いますが、違いは主に以下です。
- SDK による AI エージェントのノーコードデプロイ
- セッション ID ごとに VM が起動(最長 8 時間)
- ストリーミング処理が強い
- MCP / A2A プロトコル対応
- インフラ・セキュリティ設定が不要(AI エージェント特化)
Lambda でも実装可能ですが、多くのものを 自前で作らなくてよい のがポイントです。
特に、スレッド・ユーザー単位で VM とメモリが管理される点は、会話型 AI エージェントでは大きなメリットです。
セッション ID を指定すると、
- 最大 8 時間、同じ VM が応答
- デプロイ後でも起動中の VM は同一コードで動作
- セッション単位でセキュリティ分離
といった挙動になります。
ストリーミングも、UI/UX 的には必須ではありませんが、
- ツール実行
- 長いコンテキスト
が絡む場合は、体感速度の差は大きいです。
よくある誤解
「AgentCore を使ったから AI エージェント」「Lambda だから違う」というのは誤解です。
どちらも 実行環境 にすぎません。
AI エージェントの本質は以下です。
- 推論(Reasoning)
- ツール実行(Action)
- ループ(Iteration)
- 記憶(Memory)
Vercel AI SDK と既存 AWS リソースでこれを実装しても AI エージェントです。
Strands、Mastra、Bedrock Agent などは、これを まとめて提供してくれる ものとなります。
メモリについて
AgentCore Memory は、
- 短期記憶
- 長期記憶
を提供します。
これは Runtime 専用ではなく、Lambda などから AWS SDK 経由で利用可能です。
短期記憶はデフォルトで 90 日保持されます(7 日〜 365 日で設定可能)。
ただし、
DynamoDB に会話履歴を保存して LLM に渡すのと何が違うのか?
という疑問も出てきます。
例えば、以下のように会話履歴を組み立てて AI SDK に渡すのも同じ発想です。
const messages = [
{
role: 'user',
content: [
{
type: 'text',
text: text_value,
},
],
},
{
role: role,
content: [
{
type: 'text',
text: text_value,
},
],
},
];
const result = await generateText({
model: openai(AI_MODEL_ID),
messages: messages,
});
短期記憶に関しては、できることはほぼ同じ です。保存期間を超えてユーザーが履歴を参照したい場合は、別途 DB に保存する必要があります。
AgentCore は、
AI エージェントの動作に関わるバックエンド
を提供するもので、フロントエンドの要件まですべて満たすものではありません。
なお、Strands + AgentCore Runtime のみで完結させた場合でも、
- Web UI は付いてこない
- Streamlit や React で別途構築が必要
です。
結論:優劣ではなく適材適所
既存資産があるなら、無理に移行する必要はありません。 ただし、新規案件であれば AgentCore を選んでおくのは合理的です。
- ストリーミングが必要か
- セッション管理が必要か
といった ユースケースベース で判断すべきです。
AI エージェントの開発効率は、Runtime よりも フレームワーク側の影響が大きい のも事実です。
WEB システム・インフラの実績があるチームとしては、
- Vercel AI SDK
- TypeScript
- Hono
- Node / Bun
- 既存 AWS スタック
を活かし続ける選択も重要です。
AgentCore は発展途上ですが進化は速い。 要件に合えば積極的に採用し、そうでなければ従来構成を選ぶ。
古い技術を過大評価せず、新しい技術も過信しない。 そのバランスを忘れないようにしたいと思います。
そして何より、Claude Code をはじめとする AI コーディングの進化 も無視できません。
フレームワークの枠に収まらない場合は、AI によるフルコード開発の方が有利な場面も増えていきそうです。
もし、記事に間違いがあればXまで教えていただけましたら幸いです。 https://x.com/onoyamayoichi