

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

# 的直接代码部署 Node.js
<a name="runtime-get-started-code-deploy-node"></a>

通过直接代码部署，您只需将 Node.js-based 代理代码及其依赖项打包到.zip 文件存档中，即可将代理引入 Amazon Bedrock AgentCore Runtime。您的代理仍需要遵循[AgentCore 运行时要求](https://docs.amazonaws.cn/bedrock-agentcore/latest/devguide/runtime-service-contract.html)：拥有一个实现 P `/invocations` OST 和 `/ping` GET 服务器端点的入口点`.js`文件。

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

## 先决条件
<a name="prerequisites-node"></a>

在开始之前，请确保您满足以下条件：
+  ** Amazon 配置**了凭据的账户。要配置您的 Amazon 证书，请参阅 C Amazon LI 中的[配置和凭据文件设置。](https://docs.amazonaws.cn/cli/latest/userguide/cli-configure-files.html)
+  [**Node.js**](https://nodejs.org/)并**安装了 ** npm。我们建议安装您计划在 AgentCore Runtime 上部署的主要版本相同（例如，`NODE_22`运行时为 Node.js 22）。有关支持的版本，请参阅[支持的语言运行时](runtime-code-deploy-supported-runtimes.md)。
+  ** Amazon 权限**：要创建和部署代理，必须具有相应的权限。有关更多信息，请参阅[AgentCore 运行时权限](https://docs.amazonaws.cn/bedrock-agentcore/latest/devguide/runtime-permissions.html)。
+  **模型访问权限**：默认情况下，Amazon Bedrock 允许访问基础模型。要使用非基础模型，请按照[模型访问步骤](https://docs.amazonaws.cn/bedrock/latest/userguide/model-access.html#model-access-sdk-step4)进行操作。

## 第 1 步：设置项目并安装依赖项
<a name="step-1-setup-node"></a>

使用以下命令初始化您的项目：

```
mkdir agentcore_runtime_node_deploy
cd agentcore_runtime_node_deploy
npm init -y
```

（可选）运行`npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation`以启用 [ Amazon Bedrock AgentCore 可观测性跟踪。](https://docs.amazonaws.cn/xray/latest/devguide/xray-services-adot.html)

## 第 2 步：创建代理代码
<a name="step-2-create-agent-node"></a>

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

**Example**  
安装 [ Strands Agents SDK ](https://strandsagents.com/latest/) 及其依赖项：  

```
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`源代码。
此示例使用没有外部依赖关系的内置`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 步：在本地测试
<a name="step-3-test-locally-node"></a>

在启动之前，请确保端口 8080 是空闲的。[如果端口已在使用中，请参见](runtime-get-started-cli.md#common-issues)故障排除。

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

**Example**  

```
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`以停止代理。

```
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 步：为您的代理启用可观察性
<a name="step-4-enable-observability-node"></a>

 [Amazon Bedrock 可 AgentCore 观测性](https://docs.amazonaws.cn/bedrock-agentcore/latest/devguide/observability.html)可帮助您跟踪、调试和监控您在运行时托管的 AgentCore 代理。首先，按照启用 Amazon Bedrock AgentCore 运行时可观察性[中的说明](https://docs.amazonaws.cn/bedrock-agentcore/latest/devguide/observability-configure.html#observability-configure-builtin)启用 CloudWatch 交易搜索。要观察您的代理，请参阅[查看您的亚马逊 Bedrock AgentCore 代理的可观测性数据。](https://docs.amazonaws.cn/bedrock-agentcore/latest/devguide/observability-view.html)

要为您的 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 运行时并调用
<a name="step-5-deploy-node"></a>

**注意**  
AgentCore 运行时不会本机运行 TypeScript (`.ts`) 文件。在部署 JavaScript 之前，必须转换 TypeScript 为。有关详细信息，请参阅 [与... 合作 TypeScript](#concept-node-typescript)。

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

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

```
npm install --production
zip -r deployment_package.zip dist/ node_modules/ package.json
```
创建代理时，使用 `"entryPoint": ["dist/app.js"]` — 编译后的 JavaScript 输出，而不是`.ts`源代码。
由于此示例没有外部依赖关系，因此只需要入口点文件：  

```
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](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc731667(v=ws.10))。\+。。如果您没有授予 AgentCore Runtime 访问部署包中目录所需的权限，R AgentCore untime 会将这些目录的权限设置为 755 (rwxr-xr-x)。

包含 Linux ** arm64 ** 依赖项的 ZIP 存档需要上传到 S3，这是创建代理运行时的先决条件。以下代码要求指定的 S3 存储桶已经存在。请按照[此处](https://docs.amazonaws.cn/AmazonS3/latest/userguide/creating-bucket-s3.html)的 Amazon 文档创建存储桶。以下 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 上调用代理，请参阅以编程方式[调用代理。](runtime-get-started-cli.md#invoke-programmatically)

## 步骤 6：停止会话、更新或清理
<a name="step-6-update-cleanup-node"></a>

以下 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 直接代码部署的概念
<a name="runtime-code-deploy-node-concepts"></a>

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

**Topics**

### 入口点要求
<a name="concept-node-entry-point"></a>

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

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

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

### 依赖项打包选项
<a name="concept-node-dependency-packaging"></a>

有两种方法可以打包 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 ](https://esbuild.github.io/) 将所有依赖项捆绑到一个文件中：

```
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 以下，部署速度更快。供应商部署更简单，不需要构建步骤，但可以更大。

### 原生模块和 arm64 兼容性
<a name="concept-node-native-modules"></a>

AgentCore 运行时仅支持 ** arm64 ** 指令集架构。如果您的代理使用包含本机模块（已编译`.node`或`.so`文件）的 npm 包，则必须针对 Linux arm64 编译这些二进制文件。

AgentCore Runtime 通过读取部署包中所有`.node``.so`文件的 ELF 头文件来验证它们的架构。如果针对不同的架构（例如 x86\_64 或 macOS）编译了任何二进制文件，则您的代理创建将失败并显示状态。`CREATE_FAILED`

要安装与 arm64 兼容的原生模块，请执行以下操作：
+ 在 arm64 计算机（例如 Amazon Graviton-based 亚马逊 EC2 实例）上安装依赖项
+ 使用 npm `--arch` 和`--platform`标志：

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

大多数流行的 npm 包（Express、Axios、Fastify、Hono、ws）都是纯的 JavaScript ，不包含原生模块。

### 与... 合作 TypeScript
<a name="concept-node-typescript"></a>

AgentCore 运行时不直接运行 TypeScript 文件。在部署 JavaScript 之前，必须将 TypeScript 源代码编译为。这与 Amazon 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 引擎
<a name="concept-node-engines"></a>

如果您`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 版本，请参阅[支持的语言运行时](runtime-code-deploy-supported-runtimes.md)。