AWSでAIエージェントをサーバーレス運用できるインフラ「AgentCoreランタイム」のTypeScript SDKに、ついにAPIサーバー機能が実装されました!!
何が嬉しいの?
最近はAIエージェントを開発するのに、LangChainやStrandsなどのPython系フレームワークだけでなく、MastraやVoltAgentなどのTS系フレームワークも人気が出ています。
これをAgentCoreにデプロイするとき、ランタイムの仕様に沿ってAPIサーバー化するために、これまでは自分でExpress.jsなどのHTTPサーバーを使って、所定のエンドポイントを用意する必要がありました。
TypeScript版のAgentCore SDKがランタイムに対応したことで、この実装が簡単になります!
やってみよう
セットアップ
以下コマンドを実行して、TypeScriptプロジェクトを初期化します。
# Node.jsプロジェクトの初期化
npm init -y
npm pkg set type=module
# 依存パッケージの追加
npm i @mastra/core @ai-sdk/amazon-bedrock bedrock-agentcore @opentelemetry/auto-instrumentations-node
# TypeScript関連の設定
npm i -D typescript @types/node
npx tsc --init --target ES2022 --outDir dist --module NodeNext --moduleResolution NodeNext
# npmスクリプトの追加
npm pkg set scripts.build="tsc"
npm pkg set scripts.start="node dist/index.js"
# AIエージェント用スクリプトの作成
touch index.ts
AIエージェントの開発
Mastraの最新版v1を使って、AIエージェントを書きます。
LLMはAI SDK経由でBedrockのClaudeを指定しています。
これをAgentCore SDKでAPIサーバー化しましょう。
import { BedrockAgentCoreApp } from 'bedrock-agentcore/runtime'
import { Agent } from '@mastra/core/agent'
import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock'
import { fromNodeProviderChain } from '@aws-sdk/credential-providers'
import { z } from 'zod'
// AI SDKでBedrockモデルを設定(ランタイム環境のIAMロール認証を使用)
const bedrock = createAmazonBedrock({
region: 'ap-northeast-1',
credentialProvider: fromNodeProviderChain(),
})
// Mastraエージェントを作成
const agent = new Agent({
id: 'mastra-agent',
name: 'Mastra Agent',
instructions: 'あなたはツンデレAIエージェントです',
model: bedrock('jp.anthropic.claude-haiku-4-5-20251001-v1:0'),
})
// AgentCore SDKでAPIサーバーを作成
const app = new BedrockAgentCoreApp({
invocationHandler: {
requestSchema: z.object({ prompt: z.string() }) as any,
process: async function* (request: { prompt: string }) {
// ストリーミングで応答を返却
const result = await agent.stream([{ role: 'user', content: request.prompt }])
const reader = result.textStream.getReader()
while (true) {
const { done, value } = await reader.read()
if (done) break
yield { data: { text: value } }
}
},
},
})
// サーバーを起動
app.run()
自前実装に比べて、コードがかなり短くなりました!
内部ではHTTPサーバーにFastifyを使っているようです。
(Express.jsを採用しかけてやめた模様。パフォーマンス観点かな?)
AWSへデプロイ
以下の記事で紹介したように、昨日デプロイツール側もTS対応しています!
これを使ってデプロイしましょう。
# AWS認証
aws login
# スターターツールキットをインストール(初回のみ)
pip install --upgrade bedrock-agentcore-starter-toolkit awscrt
# 設定ファイルを作成
agentcore configure
# デプロイ(Macのローカルでビルド)
agentcore deploy --local-build
デプロイ後に表示されるAgent ARNをコピーしておいてください。
呼び出してみよう!
デプロイしたエージェントをクライアントアプリから呼び出してみます。
今回はクライアントもTS製のシンプルなCLIツールです。
いまコピーしたAgent ARNを10行目に貼り付けます。
import {
BedrockAgentCoreClient,
InvokeAgentRuntimeCommand,
} from '@aws-sdk/client-bedrock-agentcore'
// AgentCore クライアントを初期化(東京リージョン)
const client = new BedrockAgentCoreClient({ region: 'ap-northeast-1' })
// 呼び出すエージェントのARN
const agentArn = '<ここにARNを入れる>'
// リクエストを送信
const payload = JSON.stringify({ prompt: '元気?' })
const command = new InvokeAgentRuntimeCommand({
agentRuntimeArn: agentArn,
runtimeSessionId: crypto.randomUUID(),
payload: new TextEncoder().encode(payload),
contentType: 'application/json',
accept: 'text/event-stream',
})
const response = await client.send(command)
// ストリーミングレスポンスを処理
if (response.response) {
const stream = response.response as AsyncIterable<Buffer>
for await (const chunk of stream) {
const text = new TextDecoder().decode(chunk)
for (const line of text.split('\n')) {
if (line.startsWith('data: ')) {
try {
const data = JSON.parse(line.slice(6))
if (data.text) process.stdout.write(data.text)
} catch {}
}
}
}
}
console.log()
以下コマンドで実行します。
npx tsx client.ts
無事にツンデレエージェントがストリーミング応答してくれました!
ふ、ふん...別に心配してくれなくたっていいんだからね!
...まあ、元気にしてるけど。あなたこそ、何か用があるの?べ、別にあなたのことが気になってるわけじゃないんだからね。ただ...返事くらいはしてあげるってだけよ。
何か手伝えることがあれば言いなさいよ。ほっとけないじゃない...じゃなくて、効率的に対応するだけだからね!
おまけ
StrandsとかAgentCoreがそもそもよく分からない方は、こちらから!