Bedrock AgentCore SDKはPython向けにしか提供されていませんが、なんとかRuntimeにMastraをデプロイできました。
ソース一式はこちらです。
Bedrock AgentCore Runtimeにデプロイには?
以下の2点が必要です。
-
/invocations
エンドポイント(POST)と/ping
エンドポイント(GET)が必要 -
0.0.0.0
ホストで8080
ポートを待ち受ける
Mastraで上記要件に合わせるには、このあたりのドキュメントに従います。
こうなります。
export const mastra = new Mastra({
agents: {
// ...
},
server: {
port: 8080,
host: "0.0.0.0",
apiRoutes: [
registerApiRoute("/invocations", {
method: "POST",
handler: async (c) => {
// ...
},
}),
registerApiRoute("/ping", {
method: "GET",
handler: async (c) => {
// ...
},
}),
],
},
});
ストリームさせる
Mastraでストリームするにはこんな感じになります
import { streamSSE } from "hono/streaming";
const streamResult = await agent.stream(prompt);
return streamSSE(c, async (stream) => {
for await (const chunk of streamResult.textStream) {
await stream.write(chunk);
}
});
また、MCPツールも組み合わせる場合、ストリーム出力後にmcp.disconnect()
を実行します。
そうしないと二回目以降のリクエストが変な感じになります。
const mcp = new MCPClient({
servers: {
awsKnowledgeMcpServer: {
url: new URL("https://knowledge-mcp.global.api.aws"),
},
},
});
const toolsets = await mcp.getToolsets();
const streamResult = await agent.stream(prompt, {
toolsets: toolsets,
});
return streamSSE(c, async (stream) => {
for await (const chunk of streamResult.textStream) {
await stream.write(chunk);
}
await mcp.disconnect();
});
Dockerfileを作る
npm run build
(mastra build
)をすると、.mastra/output
ディレクトリに必要なものが一式で生成されます。
マルチステージビルドを使って起動に必要なものだけをコピーしてみました。
Dockerfile
# Build stage
FROM public.ecr.aws/docker/library/node:20-alpine AS builder
# Set working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install all dependencies (including devDependencies for building)
RUN npm ci
# Copy source code
COPY . .
# Build the application
RUN npm run build
# Production stage
FROM public.ecr.aws/docker/library/node:20-alpine AS production
# Set working directory
WORKDIR /app
# Create non-root user for security
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001
# Copy only the built .mastra/output directory (contains everything needed)
COPY --from=builder --chown=nextjs:nodejs /app/.mastra/output ./
USER nextjs
# Expose port 8080 as required by AgentCore
EXPOSE 8080
# Set environment variables
ENV NODE_ENV=production
# Start the application using the command from build output
CMD ["node", "--import=./instrumentation.mjs", "./index.mjs"]
ECRにプッシュ
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
AWS_REGION=us-west-2
AGENT_NAME=agentcore-mastra
docker buildx create --use
aws ecr create-repository --repository-name ${AGENT_NAME} --region ${AWS_REGION}
aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com
docker buildx build --platform linux/arm64 -t ${ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${AGENT_NAME}:latest --push .
マネコンでAgentCore Runtimeにデプロイ
クライアントから呼び出し
import {
BedrockAgentCoreClient,
InvokeAgentRuntimeCommand,
} from "@aws-sdk/client-bedrock-agentcore";
const client = new BedrockAgentCoreClient({
region: "us-west-2",
});
const command = new InvokeAgentRuntimeCommand({
agentRuntimeArn: "arn:aws:bedrock-agentcore:us-west-2:**********",
payload: JSON.stringify({
prompt: "S3はなんの略称ですか?",
}),
qualifier: "DEFAULT",
});
const response = await client.send(command);
console.log(response.contentType);
for await (const item of response.response) {
process.stdout.write(new TextDecoder().decode(item));
}
console.log();
オブザーバビリティはちょっと挫折。。
TypeScript SDKもほしいね!
間違いがあればご指摘お願いします!
最後まで読んでいただいてありがとうございます!