View a markdown version of this page

的直接代码部署 Node.js - 亚马逊基岩 AgentCore

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

的直接代码部署 Node.js

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

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

先决条件

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

  • AWS 配置了凭据的账户。要配置您的 AWS 证书,请参阅 C AWS LI 中的配置和凭据文件设置。

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

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

  • 模型访问权限:默认情况下,Amazon Bedrock 允许访问基础模型。要使用非基础模型,请按照模型访问步骤进行操作。

第 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 是空闲的。如果端口已在使用中,请参见故障排除。

打开终端窗口并启动代理:

例
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 交易搜索。要观察您的代理,请参阅查看您的亚马逊 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()调用)。

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

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

注意

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

使用您的代理代码和依赖项创建 .zip 文件。 AgentCore 运行时仅支持 arm64 指令集架构——确保所有原生模块(.node文件)均为 arm64 编译。

例
Strands Agents SDK

打包编译后的输出和供应商的依赖关系:

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 权限八进制表示法中, AgentCore 运行时对不可执行文件(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 访问部署包中目录所需的权限,R AgentCore untime 会将这些目录的权限设置为 755 (rwxr-xr-x)。

包含 Linux arm64 依赖项的 ZIP 存档需要上传到 S3,这是创建代理运行时的先决条件。以下代码要求指定的 S3 存储桶已经存在。请按照此处的 AWS 文档创建存储桶。以下 TypeScript 代码会将.zip 文件档案上传到 S3 并创建亚马逊 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 自动检测,请在node_modules/@aws/aws-distro-opentelemetry-node-autoinstrumentation/您的 ZIP 中opentelemetry-instrument添加并在入口点使用前缀:

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

要以编程方式在 Amazon Bedrock AgentCore Runtime 上调用代理,请参阅以编程方式调用代理。

步骤 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 代码将删除 S3 中的亚马逊 Bedrock AgentCore 运行时和 .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 直接代码部署的概念

了解在亚马逊 Bedrock R AgentCore untime 中使用直接代码部署时的 Node.js-specific 概念。

主题

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

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

    当您指定子目录入口点时,请确保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(最小的 ZIP)捆绑在一起:

    使用 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 通过读取部署包中所有.node.so文件的 ELF 头文件来验证它们的架构。如果针对不同的架构(例如 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.js或dist/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 运行时还会检查该engines.node字段中是否存在常见的依赖关系node_modules/。如果其中任何一个声明的 Node.js 版本范围不包括目标运行时版本,则代理创建将失败。

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