View a markdown version of this page

Despliegue directo de código para Node.js - Amazon Bedrock AgentCore

Despliegue directo de código para Node.js

La implementación directa del código le permite llevar a su Node.js-based agente a Amazon Bedrock AgentCore Runtime simplemente empaquetando el código del agente y sus dependencias en un archivo zip. Su agente aún debe cumplir con los requisitos de AgentCore tiempo de ejecución: tener un .js archivo de punto de entrada que implemente los puntos de enlace de los servidores /invocations POST y GET. /ping

Puedes incluir las dependencias tal y como vienen node_modules/ en tu ZIP o como un único archivo empaquetado con esbuild. .js

Requisitos previos

Antes de comenzar, asegúrese de que dispone de lo siguiente:

Paso 1: Configurar el proyecto e instalar las dependencias

Inicialice su proyecto con los siguientes comandos:

mkdir agentcore_runtime_node_deploy cd agentcore_runtime_node_deploy npm init -y

Si lo desea, ejecute npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation para habilitar los rastreos de AgentCore observabilidad de Amazon Bedrock.

Paso 2: Crea tu código de agente

Crea el punto de entrada de tu agente. Su agente debe implementar el contrato HTTP en tiempo de AgentCore ejecución con un terminal /ping GET health y un controlador /invocations POST.

ejemplo
Strands Agents SDK

Instale el SDK de Strands Agents y sus dependencias:

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

Cree un archivo llamadosrc/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); });

Compila el TypeScript para JavaScript:

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

El resultado compilado dist/app.js es lo que se despliega. Al crear el agente, utilice "entryPoint": ["dist/app.js"] la JavaScript salida compilada, no la .ts fuente.

HTTP (no framework)

En este ejemplo, se utiliza el node:http módulo integrado sin dependencias externas.

Cree un archivo llamadoapp.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); });

Paso 3: Probar localmente

Asegúrese de que el puerto 8080 esté libre antes de comenzar. Consulte el puerto 8080 en uso (solo local) en Problemas y soluciones comunes.

Abre una ventana de terminal e inicia tu agente:

ejemplo
Strands Agents SDK
node dist/app.js

Abre otra ventana de terminal e invoca al agente:

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

Correcto: debería ver una respuesta con la hora actual devuelta por la current_time herramienta del agente. En la ventana de la terminal en la que se ejecuta el agente, introduzca Ctrl+C para detenerlo.

HTTP (no framework)
node app.js

Abra otra ventana de terminal e invoque al agente:

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

Éxito: deberías ver una respuesta como{"result": "Hello from Node.js managed runtime! You said: Hello!","runtime":"NODE_22",…​}. En la ventana de la terminal en la que se ejecuta el agente, ingresa Ctrl+C para detenerlo.

Paso 4: Habilite la observabilidad para su agente

Amazon Bedrock AgentCore Observability le ayuda a rastrear, depurar y supervisar los agentes que aloja en Runtime. AgentCore En primer lugar, active la búsqueda de CloudWatch transacciones siguiendo las instrucciones de Habilitar la observabilidad en tiempo de AgentCore ejecución de Amazon Bedrock. Para observar a su agente, consulte Ver datos de observabilidad de sus agentes de Amazon Bedrock AgentCore .

Para habilitar la instrumentación automática para su Node.js agente, añada el paquete ADOT:

npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation
importante

La autoinstrumentación de ADOT funciona parcheando Node.js require() las llamadas en tiempo de ejecución. Esto significa que solo es compatible con la salida del módulo CommonJS. Si compila TypeScript con --module nodenext o --module esnext (produce import sentencias de ESM), la instrumentación de ADOT falla silenciosamente y no se emite ningún rastro. Para usar ADOT, compile con --module commonjs o use esbuild with --platform=node (que conserva require() las llamadas a los módulos integrados). Node.js

Al realizar la implementación, node_modules/ inclúyelo en el ZIP y usa el opentelemetry-instrument prefijo en el punto de entrada (consulta el paso 5).

Paso 5: Implemente en AgentCore Runtime e invoque

nota

AgentCore Runtime no ejecuta los archivos TypeScript (.ts) de forma nativa. Debe transpilarlos antes de TypeScript implementarlos JavaScript . Para obtener más información, consulte Trabajando con TypeScript .

Cree un archivo.zip con el código de agente y las dependencias. AgentCore El tiempo de ejecución solo es compatible con la arquitectura de conjuntos de instrucciones arm64; asegúrese de que todos los módulos (.nodearchivos) nativos estén compilados para arm64.

ejemplo
Strands Agents SDK

Package la salida compilada y las dependencias vendidas:

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

Al crear el agente, utilice "entryPoint": ["dist/app.js"] la JavaScript salida compilada, no la fuente. .ts

HTTP (no framework)

Como este ejemplo no tiene dependencias externas, solo se necesita el archivo del punto de entrada:

zip deployment_package.zip app.js

Al crear el agente, utilice"entryPoint": ["app.js"].

nota

. El tamaño máximo de un paquete de implementación.zip para AgentCore Runtime es de 250 MB (comprimido) y 750 MB (descomprimido). Tenga en cuenta que este límite se aplica al tamaño combinado de todos los archivos que cargue. El AgentCore Runtime necesita permiso para leer los archivos del paquete de despliegue. En la notación octal de permisos de Linux, AgentCore Runtime necesita 644 permisos para los archivos no ejecutables (rw-r—r--) y 755 permisos (rwxr-xr-x) para los directorios y los archivos ejecutables. En Linux y macOS, utilice el comando chmod para cambiar los permisos de los archivos y directorios del paquete de implementación. Por ejemplo, para conceder los permisos correctos a un archivo no ejecutable, ejecute el siguiente comando:. chmod 644 <filepath> Para cambiar los permisos de los archivos en Windows, consulte Set, View, Change, or Remove Permissions on an Object en la documentación de Microsoft Windows. +.. Si no concedes a AgentCore Runtime los permisos que necesita para acceder a los directorios de tu paquete de implementación, AgentCore Runtime establece los permisos para esos directorios en 755 (rwxr-xr-x).

Es necesario cargar en S3 un archivo ZIP que contenga las dependencias arm64 de Linux como requisito previo para crear Agent Runtime. El siguiente código requiere que el bucket de S3 especificado ya exista. Siga la AWS documentación que se indica aquí para crear un depósito. El siguiente TypeScript código cargará el archivo.zip en S3 y creará un entorno de ejecución de 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}`);

Para habilitar la instrumentación automática de OTEL, node_modules/@aws/aws-distro-opentelemetry-node-autoinstrumentation/ inclúyalo en su código postal y utilice el opentelemetry-instrument prefijo en el punto de entrada:

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

Para invocar un agente en el entorno de AgentCore ejecución de Amazon Bedrock mediante programación, consulte: Invocar un agente mediante programación

Paso 6: Detener la sesión, actualizarla o limpiarla

TypeScript El siguiente código actualizará un AgentCore tiempo de ejecución. Cargue el nuevo paquete de implementación en S3 y, a continuación, llame aUpdateAgentRuntimeCommand:

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}`);

Para detener la sesión en ejecución antes de la sesión configurable IdleRuntimeSessionTimeout (el valor predeterminado es de 15 minutos) y ahorrar en posibles costes excesivos, utilice el siguiente código:

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 El siguiente código eliminará un entorno de AgentCore ejecución de Amazon Bedrock y el archivo de archivo.zip de 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-specific conceptos para el despliegue directo de código

Obtenga información sobre Node.js-specific los conceptos relacionados con la implementación directa de código con Amazon Bedrock AgentCore Runtime.

Temas

    AgentCore Runtime for Node.js solo acepta puntos .js de entrada. TypeScript los archivos (.ts) no se aceptan directamente; debe transpilarlos JavaScript antes de empaquetarlos. Recomendamos usar esbuild para transpilar y empaquetar en un solo paso. Añada esbuild como una dependencia de desarrollo con. npm install -D esbuild

    Los puntos de entrada pueden estar en subdirectorios. Por ejemplo, src/app.js o dist/index.js son puntos de entrada válidos. Node.js la resolución del módulo recorre el árbol de directorios desde la ubicación del punto de entrada, por lo que las dependencias de la raíz del ZIP se encuentran automáticamente, sin necesidad de realizar ninguna NODE_PATH configuración. node_modules/

    Al especificar un punto de entrada a un subdirectorio, asegúrese de que la ruta de la entryPoint configuración coincida con la ruta del archivo ZIP.

    Existen dos enfoques para empaquetar las dependencias de los Node.js agentes:

    Dependencias de proveedores (las más sencillas):

    Incluye node_modules/ directamente en tu código postal junto a tu punto de entrada:

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

    Esto produce un ZIP con la siguiente estructura:

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

    Incluido con esbuild (el ZIP más pequeño):

    Use esbuild para agrupar todas las dependencias en un solo archivo:

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

    Esto produce un ZIP mínimo:

    my-agent.zip
    └── bundle.js

    Ambos enfoques funcionan. Las implementaciones agrupadas suelen ocupar menos de 10 MB y se despliegan más rápido. Las implementaciones distribuidas por proveedores son más sencillas y no requieren ningún paso de creación, pero pueden ser más grandes.

    AgentCore Runtime solo es compatible con la arquitectura del conjunto de instrucciones arm64. Si su agente usa paquetes npm que incluyen módulos nativos (compilados .node o .so archivos), esos binarios deben compilarse para Linux arm64.

    AgentCore Runtime valida la arquitectura de todos los .so archivos .node y del paquete de implementación leyendo sus encabezados ELF. Si se compila algún binario para una arquitectura diferente (como x86_64 o macOS), la creación del agente fallará con el estado. CREATE_FAILED

    Para instalar módulos nativos compatibles con arm64:

    • Instalar las dependencias en una máquina arm64 (como una instancia de Amazon AWS Graviton-based EC2)

    • Utilice npm e indicadores: --arch --platform

      npm install --arch=arm64 --platform=linux
    • Use esbuild para empaquetar su código si puede evitar el módulo nativo en tiempo de ejecución

    Los paquetes npm más populares (Express, Axios, Fastify, Hono, ws) son puros JavaScript y no contienen módulos nativos.

    AgentCore Runtime no ejecuta TypeScript los archivos directamente. Debe compilar el código TypeScript fuente JavaScript antes de implementarlo. Es el mismo patrón utilizado por AWS Lambda.

    Uso del TypeScript compilador (tsc):

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

    A continuación, empaquete la salida compilada:

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

    Al crear el agente, defina el punto de entrada al .js archivo compilado (por ejemplo, app.js o en dist/app.js función de su estructura ZIP).

    Uso de esbuild (recomendado para un empaquetado más sencillo):

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

    esbuild compila TypeScript y agrupa las dependencias en un solo paso, produciendo un archivo pequeño e independiente. .js

    Si package.json incluye un engines.node campo, AgentCore Runtime valida que el rango especificado es compatible con la Node.js versión que seleccionó (por ejemplo, Node.js 22 cuando usa el NODE_22 motor de ejecución). Si el rango excluye esa versión, la creación del agente fallará con el estado. CREATE_FAILED

    Por ejemplo, las siguientes engines declaraciones son compatibles con Node.js 22:

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

    Las siguientes declaraciones son incompatibles y provocarán un error en la creación del agente:

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

    AgentCore Runtime también comprueba el engines.node campo para ver si hay dependencias comunes en sunode_modules/. Si alguna de estas opciones declara un rango de versiones que excluye la Node.js versión de tiempo de ejecución de destino, no se podrá crear el agente.

    Si encuentra alguna engines.node incompatibilidad, actualice el paquete a una versión que sea compatible con la versión de destino Node.js o elimine el engines campo de la suya. package.json Para ver Node.js las versiones compatibles, consulta Tiempos de ejecución de idiomas compatibles.