View a markdown version of this page

直接部署代码 Node.js - Amazon Bedrock AgentCore

直接部署代码 Node.js

直接部署代码使您只需将 Node.js-based 代理代码及其依赖项打包到.zip 文件存档中即可将代理引入 Amazon Bedrock Runt AgentCore ime。您的代理仍然需要遵循AgentCore 运行时要求:拥有一个实现 P /invocations OST 和 /ping GET 服务器端点的入口点.js文件。

您可以将依赖项作为供应商包含在 ZIP node_modules/ 中,也可以作为 esbuild 捆绑的单个文件包括在内。.js

先决条件

在开始之前,请确保您满足以下条件:

  • AWS 已配置凭据的@@ 账户。要配置您的 AWS 证书,请参阅 AWS CLI 中的配置和凭证文件设置

  • Node.js并安装了 npm。我们建议安装您计划在 AgentCore Runtime 上部署的主版本相同(例如,NODE_22运行时为 Node.js 22)。有关支持的版本,请参阅支持的语言运行时

  • AWS 权限:要创建和部署代理,必须具有相应的权限。有关更多信息,请参阅AgentCore 运行时权限

  • 模型访问权限:在亚马逊 Bedrock 主机中启用了 Anthropic Claude Sonnet 4.0。有关在 Strands Agents 中使用其他模型的信息,请参阅 Strands Agent s SDK 文档中的模型提供者部分。

第 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 步:创建您的代理代码

创建您的代理入口点。您的代理必须使用 GET AgentCore 运行状况端点和 P /invocations OS /ping T 处理程序实现运行时 HTTP 合约。

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就是您部署的内容。创建代理时,请使用 "entryPoint": ["dist/app.js"] — 编译后的 JavaScript 输出,而不是.ts源代码。

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?"}'

成功:您应该会看到包含代理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,请使用 esbuild 编译--module commonjs或使用 esbuild w --platform=node ith(它保留对 Node.js 内置模块的require()调用)。

部署时,请node_modules/在 ZIP 中包含并在入口点中使用opentelemetry-instrument前缀(参见步骤 5)。

步骤 5:部署到 AgentCore 运行时并调用

注意

AgentCore 运行时不以本机方式运行 TypeScript (.ts) 文件。在部署 JavaScript 之前 TypeScript ,必须转换为。有关详细信息,请参阅 与 TypeScript

使用您的代理代码和依赖项创建一个.zip 文件。 AgentCore Runtime 仅支持 arm64 指令集架构,确保所有原生模块(.node文件)都是针对 arm64 编译的。

Strands Agents SDK

Package 将编译后的输出和供应商依赖项打包:

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

创建代理时,请使用 "entryPoint": ["dist/app.js"] — 编译后的 JavaScript 输出,而不是.ts源代码。

HTTP (no framework)

由于此示例没有外部依赖关系,因此只需要入口点文件:

zip deployment_package.zip app.js

创建代理时,使用"entryPoint": ["app.js"]

注意

。 AgentCore 运行时的.zip 部署包的最大大小为 250 MB(已压缩)和 750 MB(已解压缩)。请注意,此限制适用于您上传的所有文件的总大小。 AgentCore 运行时需要权限才能读取部署包中的文件。在 Linux 权限八进制表示法中,对于不可执行文件(rw-r—r--),Runt AgentCore ime 需要 644 个权限,目录和可执行文件需要 755 个权限(rwxr-xr-x)。在 Linux 和 MacOS 中,使用 chmod 命令更改部署包中文件和目录的文件权限。例如,要为不可执行文件提供正确的权限,请运行以下命令。chmod 644 <filepath>要在 Windows 中更改文件权限,请参阅 Microsoft Windows 文档中的 Set, View, Change, or Remove Permissions on an Object。+。。 如果您不授予 R AgentCore untime 访问部署包中目录所需的权限,则 AgentCore 运行时会将这些目录的权限设置为 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 运行时上调用代理,请参阅:以编程方式调用代理

步骤 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 运行时和 S3 中的.zip 存档文件。

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-specific 直接代码部署的概念

了解在 Amazon Bedrock Runt AgentCore ime 中使用直接代码部署时的 Node.js-specific 概念。

主题

    AgentCore 运行时 Node.js 仅接受.js入口点。 TypeScript 文件 (.ts) 不被直接接受,您必须在打包 JavaScript 之前将其转换为。我们建议使用 esbu ild 在单个步骤中进行转换和捆绑。使用 npm install -D esbuild esbuild 作为开发依赖项添加。

    入口点可以位于子目录中。例如,src/app.jsdist/index.js是有效的入口点。 Node.js 模块解析从入口点的位置向上移动目录树,因此可以自动找到 ZIP 根目录下的依赖项——无需NODE_PATH配置。node_modules/

    指定子目录入口点时,请确保entryPoint配置中的路径与 ZIP 文件中的路径相匹配。

    有两种方法可以为 Node.js 代理打包依赖关系:

    供应商依赖关系(最简单):

    在入口点旁边node_modules/直接包含在你的 ZIP 中:

    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 捆绑在一起(最小的邮政编码):

    使用 esbuild 将所有依赖项捆绑到一个文件中:

    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 标头来验证部署包中所有.so文件.node和文件的架构。如果针对不同的架构(例如 x86_64 或 macOS)编译了任何二进制文件,则代理创建将失败,状态为。CREATE_FAILED

    要安装与 arm64 兼容的原生模块,请执行以下操作

    • 在 arm64 机器(例如 AWS Graviton-based 亚马逊 EC2 实例)上安装依赖关系

    • 使用 npm --arch--platform标志:

      npm install --arch=arm64 --platform=linux
    • 如果可以在运行时避免使用原生模块,请使用 esbuild 来捆绑您的代码

    大多数流行的 npm 包(Express、Axios、Fastify、Hono、ws)都是纯净的,不包含原生 JavaScript 模块。

    AgentCore 运行时不直接运行 TypeScript 文件。在部署 JavaScript 之前,必须将 TypeScript 源代码编译为。这与 AWS Lambda 使用的模式相同。

    使用编 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文件(例如,app.jsdist/app.js视您的 ZIP 结构而定)。

    使用 esbuild(建议使用更简单的打包):

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

    esbuild 只需一个步骤即可编译 TypeScript 和捆绑依赖关系,从而生成一个独立的小文件。.js

    如果您package.json包含一个engines.node字段,则 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 还会检查该engines.node字段中是否有常见的依赖关系node_modules/。如果其中任何一个声明的 Node.js 版本范围不包括目标运行时版本,则代理创建将失败。

    如果您遇到engines.node不兼容问题,请将软件包更新到支持您的目标版本的版本或从您的package.json目标 Node.js 版本中删除该engines字段。有关支持的 Node.js 版本,请参阅支持的语言运行时