View a markdown version of this page

Node.js の直接コードデプロイ - Amazon Bedrock AgentCore

Node.js の直接コードデプロイ

直接コードデプロイを使用すると、エージェントコードとその依存関係を .zip ファイルアーカイブにパッケージ化するだけで、Node.js ベースのエージェントを Amazon Bedrock AgentCore ランタイムに持ち込むことができます。エージェントは引き続き AgentCore ランタイム要件に従う必要があります。POST および /ping GET /invocations サーバーエンドポイントを実装するエントリポイント.jsファイルが必要です。

依存関係は、ZIP node_modules/でベンダーとして、または esbuild バンドルされた単一.jsファイルとして含めることができます。

前提条件

開始する前に、以下があることを確認してください。

ステップ 1: プロジェクトをセットアップし、依存関係をインストールする

次のコマンドを使用してプロジェクトを初期化します。

mkdir agentcore_runtime_node_deploy cd agentcore_runtime_node_deploy npm init -y

必要に応じて、 npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation を実行して Amazon Bedrock AgentCore オブザーバビリティトレースを有効にします。

ステップ 2: エージェントコードを作成する

エージェントエントリポイントを作成します。エージェントは、/pingGET ヘルスエンドポイントと POST ハンドラーを使用して AgentCore Runtime HTTP /invocations 契約を実装する必要があります。

Strands Agents SDK

Strands Agents SDK とその依存関係をインストールします。

npm install @strands-agents/sdk express zod npm install -D @types/express @types/node typescript

という名前src/app.tsのファイルを作成します。

import express, { Request, Response } from "express"; import { Agent, tool } from "@strands-agents/sdk"; import z from "zod"; const PORT = 8080; const app = express(); app.use(express.json()); const currentTime = tool({ name: "current_time", description: "Returns the current date and time", inputSchema: z.object({}), callback: () => { return new Date().toISOString(); }, }); const agent = new Agent({ tools: [currentTime], printer: false, }); app.get("/ping", (_req: Request, res: Response) => { res.json({ status: "Healthy" }); }); app.post("/invocations", async (req: Request, res: Response) => { const prompt = req.body?.prompt || "No prompt provided"; try { const result = await agent.invoke(prompt); res.json({ result: result.lastMessage }); } catch (error: unknown) { const message = error instanceof Error ? error.message : String(error); res.status(500).json({ error: message }); } }); app.listen(PORT, "0.0.0.0", () => { console.log("Strands agent listening on port " + PORT); });

TypeScript を JavaScript にコンパイルします。

npx tsc --init --target ES2022 --module commonjs --outDir ./dist npx tsc

のコンパイルされた出力dist/app.jsは、デプロイしたものです。エージェントを作成するときは、.tsソースではなく、"entryPoint": ["dist/app.js"]コンパイルされた JavaScript 出力を使用します。

HTTP (no framework)

この例では、外部依存関係のない組み込みnode:httpモジュールを使用します。

という名前app.jsのファイルを作成します。

const http = require("node:http"); const PORT = 8080; const server = http.createServer((req, res) => { if (req.url === "/ping" && req.method === "GET") { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ status: "Healthy" })); } else if (req.url === "/invocations" && req.method === "POST") { let body = ""; req.on("data", (chunk) => { body += chunk; }); req.on("end", () => { try { const input = JSON.parse(body); const prompt = input.prompt || input.command || "No prompt provided"; res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ result: "Hello from Node.js managed runtime! You said: " + prompt, runtime: "NODE_22", nodeVersion: process.version, timestamp: new Date().toISOString() })); } catch (e) { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ result: "Hello from Node.js managed runtime!", runtime: "NODE_22", nodeVersion: process.version, input: body, timestamp: new Date().toISOString() })); } }); } else { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ message: "Node.js managed runtime agent is running" })); } }); server.listen(PORT, "0.0.0.0", () => { console.log("Node.js agent listening on port " + PORT); });

ステップ 3: ローカルでテストする

開始する前に、ポート 8080 が空いていることを確認してください。一般的な問題と解決策「使用中のポート 8080 (ローカルのみ)」を参照してください。

ターミナルウィンドウを開き、エージェントを起動します。

Strands Agents SDK
node dist/app.js

別のターミナルウィンドウを開き、エージェントを呼び出します。

curl -X POST http://localhost:8080/invocations \ -H "Content-Type: application/json" \ -d '{"prompt": "What time is it right now?"}'

Success: エージェントのcurrent_timeツールによって返された現在の時刻を含むレスポンスが表示されます。エージェントを実行しているターミナルウィンドウで、 と入力Ctrl+Cしてエージェントを停止します。

HTTP (no framework)
node app.js

別のターミナルウィンドウを開き、エージェントを呼び出します。

curl -X POST http://localhost:8080/invocations \ -H "Content-Type: application/json" \ -d '{"prompt": "Hello!"}'

成功: のようなレスポンスが表示されます{"result": "Hello from Node.js managed runtime! You said: Hello!","runtime":"NODE_22",…​}。エージェントを実行しているターミナルウィンドウで、 と入力Ctrl+Cしてエージェントを停止します。

ステップ 4: エージェントのオブザーバビリティを有効にする

Amazon Bedrock AgentCore オブザーバビリティは、AgentCore ランタイムでホストするエージェントをトレース、デバッグ、モニタリングするのに役立ちます。まず、「Amazon Bedrock AgentCore ランタイムオブザーバビリティを有効にする」の手順に従って CloudWatch トランザクション検索を有効にします。エージェントを監視するには、「Amazon Bedrock AgentCore エージェントのオブザーバビリティデータを表示する」を参照してください。

Node.js エージェントの自動計測を有効にするには、ADOT パッケージを追加します。

npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation
重要

ADOT 自動計測は、実行時に Node.js require()呼び出しにパッチを適用することで機能します。つまり、CommonJS モジュールの出力とのみ互換性があります。TypeScript を --module nodenextまたは --module esnext (ESM importステートメントを生成する) でコンパイルすると、ADOT 計測はサイレントに失敗し、トレースは出力されません。ADOT を使用するには、 でコンパイル--module commonjsするか、 で esbuild を使用します --platform=node (Node.js 組み込みモジュールのrequire()呼び出しを保持します)。

デプロイするときは、ZIP node_modules/に を含め、エントリポイントに opentelemetry-instrument プレフィックスを使用します (ステップ 5 を参照)。

ステップ 5: AgentCore ランタイムにデプロイして呼び出す

注記

AgentCore Runtime は TypeScript (.ts) ファイルをネイティブに実行しません。デプロイする前に TypeScript を JavaScript にトランスパイルする必要があります。詳細については、「TypeScript の操作」を参照してください。

エージェントコードと依存関係を含む .zip ファイルを作成します。AgentCore ランタイムは arm64 命令セットアーキテクチャのみをサポートします。ネイティブモジュール (.node ファイル) が arm64 用にコンパイルされていることを確認します。

Strands Agents SDK

コンパイルされた出力とベンダーの依存関係をパッケージ化します。

npm install --production zip -r deployment_package.zip dist/ node_modules/ package.json

エージェントを作成するときは、.tsソースではなく、"entryPoint": ["dist/app.js"]コンパイルされた JavaScript 出力を使用します。

HTTP (no framework)

この例では外部依存関係がないため、エントリポイントファイルのみが必要です。

zip deployment_package.zip app.js

エージェントを作成するときは、 "entryPoint": ["app.js"] を使用します。

注記

。 AgentCore Runtime の .zip デプロイパッケージの最大サイズは、250 MB (圧縮) と 750 MB (解凍) です。この制限は、アップロードするすべてのファイルの合計サイズに適用されることに注意してください。AgentCore ランタイムには、デプロイパッケージ内のファイルを読み取るためのアクセス許可が必要です。Linux アクセス許可の 8 進表記では、AgentCore Runtime には、非実行可能ファイル (rw-r—r--) には 644 個のアクセス許可が必要であり、ディレクトリと実行可能ファイルには 755 個のアクセス許可 (rwxr-xr-x) が必要です。Linux と MacOS で、デプロイパッケージ内のファイルやディレクトリのファイルアクセス権限を変更するには、chmod コマンドを使用します。たとえば、実行可能でないファイルに正しいアクセス許可を付与するには、次のコマンド chmod 644 <filepath> を実行します。Windows でファイルアクセス許可を変更するには、「Microsoft Windows ドキュメント」の「Set, View, Change, or Remove Permissions on an Object」を参照してください。+ .。 AgentCore Runtime にデプロイパッケージ内のディレクトリにアクセスするために必要なアクセス許可を付与しない場合、AgentCore Runtime はそれらのディレクトリのアクセス許可を 755 (rwxr-xr-x) に設定します。

Linux arm64 依存関係を含む ZIP アーカイブは、エージェントランタイムを作成する前提条件として S3 にアップロードする必要があります。次のコードでは、指定された S3 バケットがすでに存在している必要があります。バケットを作成するには、こちらの AWS ドキュメントに従ってください。次の TypeScript コードは、.zip ファイルアーカイブを S3 にアップロードし、Amazon Bedrock AgentCore ランタイムを作成します。

import { readFileSync } from "node:fs"; import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"; import { BedrockAgentCoreControlClient, CreateAgentRuntimeCommand, } from "@aws-sdk/client-bedrock-agentcore-control"; const accountId = "your-aws-account-id"; const agentName = "nodejs_agent"; const region = "us-west-2"; const bucketName = `bedrock-agentcore-code-${accountId}-${region}`; const s3Client = new S3Client({ region }); console.log("Uploading deployment_package.zip to S3..."); await s3Client.send(new PutObjectCommand({ Bucket: bucketName, Key: `${agentName}/deployment_package.zip`, Body: readFileSync("deployment_package.zip"), ExpectedBucketOwner: accountId, })); console.log(`Upload completed. S3 location: s3://${bucketName}/${agentName}/deployment_package.zip`); const controlClient = new BedrockAgentCoreControlClient({ region }); const response = await controlClient.send(new CreateAgentRuntimeCommand({ agentRuntimeName: agentName, agentRuntimeArtifact: { codeConfiguration: { code: { s3: { bucket: bucketName, prefix: `${agentName}/deployment_package.zip`, }, }, runtime: "NODE_22", entryPoint: ["dist/app.js"], }, }, networkConfiguration: { networkMode: "PUBLIC" }, roleArn: `arn:aws:iam::${accountId}:role/AmazonBedrockAgentCoreSDKRuntime-${region}`, lifecycleConfiguration: { idleRuntimeSessionTimeout: 300, maxLifetime: 1800, }, })); console.log(`Agent Runtime created successfully!`); console.log(`Agent Runtime ARN: ${response.agentRuntimeArn}`); console.log(`Status: ${response.status}`);

OTEL 自動計測を有効にするには、ZIP node_modules/@aws/aws-distro-opentelemetry-node-autoinstrumentation/に を含め、エントリポイントに opentelemetry-instrument プレフィックスを使用します。

entryPoint: ["opentelemetry-instrument", "dist/app.js"],

Amazon Bedrock AgentCore ランタイムでエージェントをプログラムで呼び出すには、「Invoke an agent programmatically」を参照してください。

ステップ 6: セッション、更新、またはクリーンアップを停止する

次の TypeScript コードは AgentCore ランタイムを更新します。新しいデプロイパッケージを S3 にアップロードし、 UpdateAgentRuntimeCommand を呼び出します。

import { readFileSync } from "node:fs"; import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"; import { BedrockAgentCoreControlClient, UpdateAgentRuntimeCommand, } from "@aws-sdk/client-bedrock-agentcore-control"; const accountId = "your-aws-account-id"; const agentName = "nodejs_agent"; const region = "us-west-2"; const bucketName = `bedrock-agentcore-code-${accountId}-${region}`; const s3Client = new S3Client({ region }); console.log("Uploading deployment_package.zip to S3..."); await s3Client.send(new PutObjectCommand({ Bucket: bucketName, Key: `${agentName}/deployment_package.zip`, Body: readFileSync("deployment_package.zip"), ExpectedBucketOwner: accountId, })); console.log("Upload completed successfully!"); const controlClient = new BedrockAgentCoreControlClient({ region }); const response = await controlClient.send(new UpdateAgentRuntimeCommand({ agentRuntimeId: "<your-agent-runtime-id>", agentRuntimeArtifact: { codeConfiguration: { code: { s3: { bucket: bucketName, prefix: `${agentName}/deployment_package.zip`, }, }, runtime: "NODE_22", entryPoint: ["dist/app.js"], }, }, networkConfiguration: { networkMode: "PUBLIC" }, roleArn: `arn:aws:iam::${accountId}:role/AmazonBedrockAgentCoreSDKRuntime-${region}`, })); console.log(`Agent Runtime updated successfully!`); console.log(`Agent Runtime ARN: ${response.agentRuntimeArn}`); console.log(`Status: ${response.status}`);

設定可能な IdleRuntimeSessionTimeout (デフォルトは 15 分) より前に実行中のセッションを停止し、潜在的なランアウェイコストを節約するには、次のコードを使用します。

import { BedrockAgentCoreClient, StopRuntimeSessionCommand, } from "@aws-sdk/client-bedrock-agentcore"; const region = "us-west-2"; const dataClient = new BedrockAgentCoreClient({ region }); const response = await dataClient.send(new StopRuntimeSessionCommand({ agentRuntimeArn: "arn:aws:bedrock-agentcore:us-west-2:<account-id>:runtime/<agent-runtime-id>", runtimeSessionId: "<your-session-id>", qualifier: "DEFAULT", })); console.log("Session stopped successfully!");

次の TypeScript コードでは、Amazon Bedrock AgentCore ランタイムと .zip アーカイブファイルが S3 で削除されます。

import { S3Client, DeleteObjectCommand } from "@aws-sdk/client-s3"; import { BedrockAgentCoreControlClient, DeleteAgentRuntimeCommand, } from "@aws-sdk/client-bedrock-agentcore-control"; const accountId = "your-aws-account-id"; const agentName = "nodejs_agent"; const region = "us-west-2"; const bucketName = `bedrock-agentcore-code-${accountId}-${region}`; const controlClient = new BedrockAgentCoreControlClient({ region }); console.log("Deleting Agent from Amazon Bedrock AgentCore Runtime!"); const response = await controlClient.send(new DeleteAgentRuntimeCommand({ agentRuntimeId: "<your-agent-runtime-id>", })); console.log(`Agent Runtime deleted successfully!`); console.log(`Status: ${response.status}`); const s3Client = new S3Client({ region }); console.log("Deleting deployment archive from S3..."); await s3Client.send(new DeleteObjectCommand({ Bucket: bucketName, Key: `${agentName}/deployment_package.zip`, ExpectedBucketOwner: accountId, })); console.log("Archive deleted successfully from S3!");

直接コードデプロイの Node.js 固有の概念

Amazon Bedrock AgentCore ランタイムで直接コードデプロイを使用する場合の Node.js 固有の概念について説明します。

トピック

    Node.js の AgentCore ランタイムは、.jsエントリポイントのみを受け入れます。TypeScript ファイル (.ts) は直接受け入れられません。パッケージ化する前に JavaScript にトランスパイルする必要があります。esbuild を使用して、1 つのステップでトランスパイルおよびバンドルすることをお勧めします。esbuild を開発依存関係として に追加npm install -D esbuildします。

    エントリポイントはサブディレクトリに配置できます。たとえば、 src/app.jsまたは dist/index.jsは有効なエントリポイントです。Node.js モジュール解決は、エントリポイントの場所からディレクトリツリーをウォークアップするため、ZIP のルートnode_modules/にある の依存関係が自動的に検出されるため、NODE_PATH設定は必要ありません。

    サブディレクトリエントリポイントを指定するときは、entryPoint設定のパスが ZIP ファイル内のパスと一致することを確認します。

    Node.js エージェントの依存関係をパッケージ化するには、次の 2 つのアプローチがあります。

    ベンダーの依存関係 (最もシンプル):

    エントリポイントと一緒に ZIP node_modules/に直接含めます。

    npm install --production zip -r my-agent.zip app.js node_modules/ package.json

    これにより、次の構造を持つ ZIP が生成されます。

    my-agent.zip
    ├── app.js
    ├── package.json
    └── node_modules/

    esbuild (最小 ZIP):

    esbuild を使用して、すべての依存関係を 1 つのファイルにバンドルします。

    npx esbuild app.js --bundle --platform=node --target=node22 --outfile=bundle.js zip my-agent.zip bundle.js

    これにより、最小限の ZIP が生成されます。

    my-agent.zip
    └── bundle.js

    どちらのアプローチも機能します。バンドルされたデプロイは通常 10 MB 未満で、デプロイが速くなります。ベンダーデプロイはよりシンプルで、ビルドステップは必要ありませんが、大きくすることができます。

    AgentCore ランタイムは arm64 命令セットアーキテクチャのみをサポートします。エージェントがネイティブモジュール (コンパイル済み .nodeまたは .so ファイル) を含む npm パッケージを使用している場合、これらのバイナリは Linux arm64 用にコンパイルする必要があります。

    AgentCore Runtime は、ELF ヘッダーを読み取ることで、デプロイパッケージ内のすべての .nodeおよび.soファイルのアーキテクチャを検証します。バイナリが別のアーキテクチャ (x86_64 や macOS など) 用にコンパイルされている場合、エージェントの作成はステータス CREATE_FAILED で失敗します。

    arm64 互換のネイティブモジュールをインストールするには:

    • arm64 マシン (Graviton ベースの Amazon EC2 インスタンスなど) AWS に依存関係をインストールする

    • npm の --archフラグと --platformフラグを使用します。

      npm install --arch=arm64 --platform=linux
    • ランタイムにネイティブモジュールを回避できる場合は、esbuild を使用してコードをバンドルします。

    最も一般的な npm パッケージ (Express、Axios、Fastify、Hono、ws) は純粋な JavaScript であり、ネイティブモジュールは含まれていません。

    AgentCore Runtime は TypeScript ファイルを直接実行しません。デプロイする前に TypeScript ソースコードを JavaScript にコンパイルする必要があります。これは Lambda AWS で使用されるのと同じパターンです。

    TypeScript コンパイラ (tsc) の使用:

    npm install -g typescript npx tsc --init --target ES2022 --module commonjs --outDir ./dist npx tsc

    次に、コンパイルされた出力をパッケージ化します。

    cd dist zip -r ../deployment_package.zip .

    エージェントを作成するときは、エントリポイントをコンパイルされた.jsファイル (ZIP 構造dist/app.jsに応じて app.jsまたは など) に設定します。

    esbuild の使用 (よりシンプルなパッケージ化に推奨):

    npx esbuild app.ts --bundle --platform=node --target=node22 --outfile=app.js zip deployment_package.zip app.js

    esbuild は TypeScript をコンパイルし、依存関係を 1 つのステップでバンドルして、自己完結型の小さな.jsファイルを生成します。

    engines.nodeフィールドpackage.jsonが含まれている場合、AgentCore Runtime は指定された範囲が選択した Node.js バージョンと互換性があることを検証します (NODE_22ランタイムを使用する場合の Node.js 22 など)。範囲がそのバージョンを除外すると、エージェントの作成はステータス CREATE_FAILED で失敗します。

    たとえば、次のengines宣言は Node.js 22 と互換性があります。

    { "engines": { "node": ">=18" } } { "engines": { "node": ">=14 <18 || >=20" } } { "engines": { "node": "22" } }

    次の宣言は互換性がなく、エージェントの作成が失敗します。

    { "engines": { "node": "<18" } } { "engines": { "node": ">=14 <18" } }

    AgentCore Runtime は、 の一般的な依存関係についても node_modules/ engines.nodeフィールドをチェックします。これらのいずれかが、ターゲットランタイムバージョンを除外する Node.js バージョン範囲を宣言すると、エージェントの作成は失敗します。

    engines.node 互換性がない場合は、パッケージをターゲットの Node.js バージョンをサポートするバージョンに更新するか、 から package.json enginesフィールドを削除します。サポートされている Node.js バージョンについては、「サポートされている言語ランタイム」を参照してください。