View a markdown version of this page

Implantação direta de código para Node.js - Amazon Bedrock AgentCore

Implantação direta de código para Node.js

A implantação direta de código permite que você leve seu Node.js-based agente para o Amazon Bedrock AgentCore Runtime simplesmente empacotando o código do agente e suas dependências em um arquivo de arquivos.zip. Seu agente ainda precisa seguir os requisitos de AgentCore tempo de execução: ter um .js arquivo de ponto de entrada que implemente os endpoints do servidor /invocations POST e /ping GET.

Você pode incluir dependências conforme fornecidas node_modules/ em seu ZIP ou como um arquivo único empacotado com esbuild. .js

Pré-requisitos

Antes de começar, verifique se você tem:

Etapa 1: configurar o projeto e instalar dependências

Inicialize seu projeto com os seguintes comandos:

mkdir agentcore_runtime_node_deploy cd agentcore_runtime_node_deploy npm init -y

Opcionalmente, execute npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation para habilitar os rastreamentos de AgentCore observabilidade do Amazon Bedrock.

Etapa 2: crie seu código de agente

Crie seu ponto de entrada para agentes. Seu agente deve implementar o contrato HTTP AgentCore Runtime com um endpoint de integridade /ping /invocations GET e um manipulador POST.

exemplo
Strands Agents SDK

Instale o SDK do Strands Agents e suas dependências:

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

Crie um arquivo chamadosrc/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); });

Compile o TypeScript para JavaScript:

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

A saída compilada dist/app.js é a que você implanta. Ao criar o agente, use "entryPoint": ["dist/app.js"] — a JavaScript saída compilada, não a .ts fonte.

HTTP (no framework)

Este exemplo usa o node:http módulo incorporado sem dependências externas.

Crie um arquivo chamadoapp.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); });

Etapa 3: testar localmente

Certifique-se de que a porta 8080 esteja livre antes de iniciar. Consulte Porta 8080 em uso (somente local) em Problemas e soluções comuns.

Abra uma janela do terminal e inicie seu agente:

exemplo
Strands Agents SDK
node dist/app.js

Abra outra janela do terminal e chame o agente:

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

Sucesso: você deve ver uma resposta contendo a hora atual retornada pela current_time ferramenta do agente. Na janela do terminal que está executando o agente, digite Ctrl+C para interromper o agente.

HTTP (no framework)
node app.js

Abra outra janela do terminal e chame o agente:

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

Sucesso: Você deve ver uma resposta como{"result": "Hello from Node.js managed runtime! You said: Hello!","runtime":"NODE_22",…​}. Na janela do terminal que está executando o agente, digite Ctrl+C para interromper o agente.

Etapa 4: habilitar a observabilidade para seu agente

O Amazon Bedrock AgentCore Observability ajuda você a rastrear, depurar e monitorar agentes que você hospeda no Runtime. AgentCore Primeiro, habilite a Pesquisa de CloudWatch transações seguindo as instruções em Habilitando a observabilidade do tempo de AgentCore execução do Amazon Bedrock. Para observar seu agente, consulte Visualizar dados de observabilidade de seus agentes do Amazon Bedrock AgentCore .

Para ativar a instrumentação automática para seu Node.js agente, adicione o pacote ADOT:

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

A instrumentação automática ADOT funciona Node.js require() corrigindo chamadas em tempo de execução. Isso significa que ele só é compatível com a saída do módulo CommonJS. Se você compilar TypeScript com --module nodenext ou --module esnext (produzindo import instruções ESM), a instrumentação ADOT falhará silenciosamente e nenhum rastreamento será emitido. Para usar ADOT, compile com --module commonjs ou use esbuild with --platform=node (que preserva as require() chamadas para Node.js módulos integrados).

Ao implantar, inclua node_modules/ em seu ZIP e use o opentelemetry-instrument prefixo em seu ponto de entrada (consulte a Etapa 5).

Etapa 5: implantar no AgentCore Runtime e invocar

nota

AgentCore O tempo de execução não executa arquivos TypeScript (.ts) nativamente. Você deve transpilar TypeScript para JavaScript antes da implantação. Para obter mais detalhes, consulte Trabalhando com TypeScript .

Crie um arquivo.zip com o código e as dependências do seu agente. AgentCore O Runtime suporta apenas a arquitetura de conjunto de instruções arm64 — certifique-se de que todos os módulos (.nodearquivos) nativos sejam compilados para arm64.

exemplo
Strands Agents SDK

Package a saída compilada e as dependências fornecidas:

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

Ao criar o agente, use "entryPoint": ["dist/app.js"] — a JavaScript saída compilada, não a .ts fonte.

HTTP (no framework)

Como esse exemplo não tem dependências externas, somente o arquivo do ponto de entrada é necessário:

zip deployment_package.zip app.js

Ao criar o agente, use"entryPoint": ["app.js"].

nota

. O tamanho máximo de um pacote de implantação.zip para AgentCore Runtime é 250 MB (compactado) e 750 MB (descompactado). Observe que esse limite se aplica ao tamanho combinado de todos os arquivos que você carrega. O AgentCore Runtime precisa de permissão para ler os arquivos em seu pacote de implantação. Na notação octal de permissões do Linux, o AgentCore Runtime precisa de 644 permissões para arquivos não executáveis (rw-r—r--) e 755 permissões (rwxr-xr-x) para diretórios e arquivos executáveis. No Linux e no MacOS, use o comando chmod para alterar as permissões de arquivo em arquivos e diretórios do seu pacote de implantação. Por exemplo, para dar a um arquivo não executável as permissões corretas, execute o comando a seguir,. chmod 644 <filepath> Para alterar as permissões de arquivo no Windows, consulte Set, View, Change, or Remove Permissions on an Object na documentação do Microsoft Windows. +.. Se você não conceder ao AgentCore Runtime as permissões necessárias para acessar os diretórios em seu pacote de implantação, o AgentCore Runtime definirá as permissões desses diretórios como 755 (rwxr-xr-x).

Um arquivo ZIP contendo dependências Linux arm64 precisa ser carregado no S3 como pré-requisito para criar o Agent Runtime. O código abaixo exige que o bucket S3 especificado já exista. Siga a AWS documentação aqui para criar um bucket. O TypeScript código a seguir fará o upload do arquivo de arquivos.zip para o S3 e criará um tempo de execução do 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 a instrumentação automática do OTEL, inclua node_modules/@aws/aws-distro-opentelemetry-node-autoinstrumentation/ em seu ZIP e use o opentelemetry-instrument prefixo no ponto de entrada:

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

Para invocar um agente no tempo de AgentCore execução do Amazon Bedrock de forma programática, consulte: Invocar um agente programaticamente

Etapa 6: interromper a sessão, atualizar ou limpar

O TypeScript código a seguir atualizará um AgentCore Runtime. Faça o upload do novo pacote de implantação para o S3 e ligue paraUpdateAgentRuntimeCommand:

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 interromper a sessão em execução antes do configurável IdleRuntimeSessionTimeout (o padrão é de 15 minutos) e economizar em possíveis custos descontrolados, use o código a seguir:

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!");

O TypeScript código a seguir excluirá um tempo de AgentCore execução do Amazon Bedrock e o arquivo de arquivamento .zip no 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 conceitos para implantação direta de código

Aprenda sobre Node.js-specific conceitos ao usar a implantação direta de código com o Amazon Bedrock AgentCore Runtime.

Tópicos

    AgentCore O tempo de execução para aceita Node.js apenas pontos .js de entrada. TypeScript arquivos (.ts) não são aceitos diretamente — você deve transpilá-los JavaScript antes de empacotá-los. Recomendamos usar o esbuild para transpilar e agrupar em uma única etapa. Adicione esbuild como uma dependência de desenvolvimento com. npm install -D esbuild

    Os pontos de entrada podem estar em subdiretórios. Por exemplo, src/app.js ou dist/index.js são pontos de entrada válidos. Node.js a resolução do módulo percorre a árvore de diretórios a partir da localização do ponto de entrada, para que as dependências node_modules/ na raiz do seu ZIP sejam encontradas automaticamente — nenhuma NODE_PATH configuração é necessária.

    Ao especificar um ponto de entrada de subdiretório, certifique-se de que o caminho em sua entryPoint configuração corresponda ao caminho dentro do arquivo ZIP.

    Há duas abordagens para empacotar dependências para Node.js agentes:

    Dependências fornecidas (mais simples):

    Inclua node_modules/ diretamente no seu CEP ao lado do seu ponto de entrada:

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

    Isso produz um ZIP com a seguinte estrutura:

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

    Empacotado com esbuild (menor ZIP):

    Use o esbuild para agrupar todas as dependências em um único arquivo:

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

    Isso produz um ZIP mínimo:

    my-agent.zip
    └── bundle.js

    Ambas as abordagens funcionam. As implantações agrupadas geralmente têm menos de 10 MB e são implantadas mais rapidamente. As implantações fornecidas por fornecedores são mais simples e não exigem uma etapa de construção, mas podem ser maiores.

    AgentCore O Runtime suporta apenas a arquitetura do conjunto de instruções arm64. Se seu agente usa pacotes npm que incluem módulos nativos (compilados .node ou .so arquivos), esses binários devem ser compilados para Linux arm64.

    AgentCore O Runtime valida a arquitetura de todos .node os .so arquivos em seu pacote de implantação lendo seus cabeçalhos ELF. Se algum binário for compilado para uma arquitetura diferente (como x86_64 ou macOS), a criação do agente falhará com o status. CREATE_FAILED

    Para instalar módulos nativos compatíveis com arm64:

    • Instale dependências em uma máquina arm64 (como uma instância do Amazon AWS Graviton-based EC2)

    • Use npms --arch e --platform sinalizadores:

      npm install --arch=arm64 --platform=linux
    • Use esbuild para agrupar seu código se o módulo nativo puder ser evitado em tempo de execução

    Os pacotes npm mais populares (Express, Axios, Fastify, Hono, ws) são puros JavaScript e não contêm módulos nativos.

    AgentCore O tempo de execução não executa TypeScript arquivos diretamente. Você deve compilar seu TypeScript código-fonte JavaScript antes da implantação. Esse é o mesmo padrão usado pelo AWS Lambda.

    Usando o TypeScript compilador (tsc):

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

    Em seguida, empacote a saída compilada:

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

    Ao criar o agente, defina o ponto de entrada para o .js arquivo compilado (por exemplo, app.js ou dist/app.js dependendo da sua estrutura ZIP).

    Usando o esbuild (recomendado para um empacotamento mais simples):

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

    O esbuild compila TypeScript e agrupa dependências em uma única etapa, produzindo um arquivo pequeno e independente. .js

    Se você package.json incluir um engines.node campo, o AgentCore Tempo de execução valida se o intervalo especificado é compatível com a Node.js versão selecionada (por exemplo, Node.js 22 ao usar o NODE_22 tempo de execução). Se o intervalo excluir essa versão, a criação do seu agente falhará com o statusCREATE_FAILED.

    Por exemplo, as seguintes engines declarações são compatíveis com Node.js 22:

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

    As declarações a seguir são incompatíveis e farão com que a criação do agente falhe:

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

    AgentCore O Runtime também verifica o engines.node campo em busca de dependências comuns em seunode_modules/. Se algum deles declarar um intervalo de versões que exclui a Node.js versão de tempo de execução de destino, a criação do agente falhará.

    Se você encontrar uma engines.node incompatibilidade, atualize o pacote para uma versão compatível com sua Node.js versão de destino ou remova o engines campo do seupackage.json. Para ver Node.js as versões compatíveis, consulte Tempos de execução de idiomas compatíveis.