View a markdown version of this page

Implementazione diretta del codice per Node.js - Amazon Bedrock AgentCore

Implementazione diretta del codice per Node.js

L'implementazione diretta del codice ti consente di portare il tuo Node.js-based agente su Amazon Bedrock AgentCore Runtime semplicemente impacchettando il codice dell'agente e le sue dipendenze in un archivio di file.zip. Il tuo agente deve comunque rispettare i requisiti di AgentCore Runtime: disporre di un .js file entrypoint che implementi gli /invocations endpoint del server POST e GET. /ping

Puoi includere le dipendenze come indicato dal fornitore node_modules/ nel tuo file ZIP o come singolo file raggruppato con esbuild. .js

Prerequisiti

Prima di iniziare, assicurati di disporre dei seguenti elementi:

Fase 1: Configura il progetto e installa le dipendenze

Inizializza il tuo progetto con i seguenti comandi:

mkdir agentcore_runtime_node_deploy cd agentcore_runtime_node_deploy npm init -y

Facoltativamente, esegui npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation per abilitare le tracce di AgentCore osservabilità di Amazon Bedrock.

Passaggio 2: crea il codice del tuo agente

Crea il tuo punto di ingresso per l'agente. Il tuo agente deve implementare il contratto HTTP AgentCore Runtime con un endpoint sanitario /ping GET e un gestore /invocations POST.

Esempio
Strands Agents SDK

Installa l'SDK di Strands Agents e le sue dipendenze:

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

Crea un file denominato: 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); });

Compila il file TypeScript in JavaScript:

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

L'output compilato dist/app.js è quello che distribuisci. Quando crei l'agente, usa"entryPoint": ["dist/app.js"]: l' JavaScript output compilato, non la .ts fonte.

HTTP (no framework)

Questo esempio utilizza il node:http modulo integrato senza dipendenze esterne.

Crea un file denominatoapp.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); });

Fase 3: Esegui il test localmente

Assicurati che la porta 8080 sia libera prima di iniziare. Vedi Porta 8080 in uso (solo locale) in Problemi e soluzioni comuni.

Apri una finestra di terminale e avvia il tuo agente:

Esempio
Strands Agents SDK
node dist/app.js

Apri un'altra finestra di terminale e richiama l'agente:

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

Operazione riuscita: dovrebbe apparire una risposta contenente l'ora corrente restituita dallo current_time strumento dell'agente. Nella finestra del terminale in cui è in esecuzione l'agente, immettete Ctrl+C per arrestarlo.

HTTP (no framework)
node app.js

Apri un'altra finestra del terminale e richiama l'agente:

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

Operazione riuscita: dovresti vedere una risposta del tipo{"result": "Hello from Node.js managed runtime! You said: Hello!","runtime":"NODE_22",…​}. Nella finestra del terminale in cui è in esecuzione l'agente, immettete Ctrl+C per arrestarlo.

Fase 4: Abilita l'osservabilità per il tuo agente

Amazon Bedrock AgentCore Observability ti aiuta a tracciare, eseguire il debug e monitorare gli agenti ospitati in Runtime. AgentCore Per prima cosa abilita CloudWatch Transaction Search seguendo le istruzioni in Enabling Amazon Bedrock AgentCore runtime observability. Per osservare il tuo agente, consulta Visualizzare i dati di osservabilità per i tuoi agenti Amazon Bedrock AgentCore .

Per abilitare la strumentazione automatica per il tuo Node.js agente, aggiungi il pacchetto ADOT:

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

La strumentazione automatica ADOT funziona Node.js require() patchando le chiamate in fase di esecuzione. Ciò significa che è compatibile solo con l'output del modulo CommonJS. Se si compila TypeScript con --module nodenext o --module esnext (producendo import istruzioni ESM), la strumentazione ADOT fallisce silenziosamente e non viene emessa alcuna traccia. Per usare ADOT, compila --module commonjs o usa esbuild with (che conserva le chiamate ai moduli integrati). --platform=node require() Node.js

Durante la distribuzione, includetelo node_modules/ nel file ZIP e utilizzate il opentelemetry-instrument prefisso nel punto di ingresso (vedi Fase 5).

Fase 5: Esegui la distribuzione su Runtime e richiama AgentCore

Nota

AgentCore Runtime non esegue i file TypeScript (.ts) in modo nativo. È necessario traspilare TypeScript to JavaScript prima della distribuzione. Per informazioni dettagliate, consulta Lavorare con TypeScript .

Crea un file.zip con il codice dell'agente e le dipendenze. AgentCore Runtime supporta solo l'architettura del set di istruzioni arm64: assicurati che tutti i moduli (.nodefile) nativi siano compilati per arm64.

Esempio
Strands Agents SDK

Package dell'output compilato e delle dipendenze fornite dal fornitore:

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

Quando crei l'agente, usa"entryPoint": ["dist/app.js"]: l' JavaScript output compilato, non la .ts fonte.

HTTP (no framework)

Poiché questo esempio non ha dipendenze esterne, è necessario solo il file del punto di ingresso:

zip deployment_package.zip app.js

Quando crei l'agente, usa"entryPoint": ["app.js"].

Nota

. La dimensione massima per un pacchetto di distribuzione.zip per AgentCore Runtime è 250 MB (compresso) e 750 MB (decompresso). Tieni presente che questo limite si applica alla dimensione combinata di tutti i file che carichi. Il AgentCore Runtime richiede l'autorizzazione per leggere i file nel pacchetto di distribuzione. Nella notazione ottale delle autorizzazioni Linux, AgentCore Runtime richiede 644 autorizzazioni per i file non eseguibili (rw-r—r--) e 755 permessi (rwxr-xr-x) per le directory e i file eseguibili. In Linux e macOS, utilizza il comando chmod per modificare le autorizzazioni file su file e directory nel pacchetto di implementazione. Ad esempio, per assegnare a un file non eseguibile le autorizzazioni corrette, esegui il comando seguente,. chmod 644 <filepath> Per modificare le autorizzazioni file in Windows, consulta Set, View, Change, or Remove Permissions on an Object nella documentazione di Microsoft Windows. +.. Se non concedi a AgentCore Runtime le autorizzazioni necessarie per accedere alle directory nel pacchetto di distribuzione, AgentCore Runtime imposta le autorizzazioni per tali directory su 755 (rwxr-xr-x).

Un archivio ZIP contenente le dipendenze Linux arm64 deve essere caricato su S3 come prerequisito per Create Agent Runtime. Il codice seguente richiede che il bucket S3 specificato esista già. Segui la AWS documentazione qui per creare un bucket. Il TypeScript codice seguente caricherà l'archivio di file.zip su S3 e creerà un runtime Amazon AgentCore Bedrock.

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

Per abilitare la strumentazione automatica OTEL, includi node_modules/@aws/aws-distro-opentelemetry-node-autoinstrumentation/ nel tuo ZIP e usa il opentelemetry-instrument prefisso nel punto di ingresso:

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

Per richiamare un agente sul AgentCore runtime di Amazon Bedrock a livello di codice, consulta: Richiamare un agente a livello di codice

Passaggio 6: interrompere la sessione, l'aggiornamento o la pulizia

Il TypeScript codice seguente aggiornerà un AgentCore Runtime. Carica il nuovo pacchetto di distribuzione su S3, quindi chiamaUpdateAgentRuntimeCommand:

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

Per interrompere la sessione in esecuzione prima di quella configurabile IdleRuntimeSessionTimeout (impostazione predefinita a 15 minuti) e risparmiare su eventuali costi inutili, usa il codice seguente:

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

Il TypeScript codice seguente eliminerà un AgentCore runtime di Amazon Bedrock e il file di archivio.zip in 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 concetti per la distribuzione diretta del codice

Scopri Node.js-specific i concetti relativi all'utilizzo della distribuzione diretta del codice con Amazon Bedrock AgentCore Runtime.

Argomenti

    AgentCore Runtime for accetta Node.js solo punti di .js ingresso. TypeScript i file (.ts) non vengono accettati direttamente: è necessario trasporli JavaScript prima del confezionamento. Ti consigliamo di utilizzare esbuild per transpilare e raggruppare in un unico passaggio. Aggiungi esbuild come dipendenza di sviluppo con. npm install -D esbuild

    I punti di ingresso possono trovarsi nelle sottodirectory. Ad esempio, src/app.js o dist/index.js sono punti di ingresso validi. Node.js la risoluzione del modulo risale l'albero delle directory dalla posizione del punto di ingresso, in modo che le dipendenze presenti nella node_modules/ radice del file ZIP vengano trovate automaticamente, senza bisogno di alcuna NODE_PATH configurazione.

    Quando specificate un punto di ingresso della sottodirectory, assicuratevi che il percorso nella entryPoint configurazione corrisponda al percorso all'interno del file ZIP.

    Esistono due approcci per impacchettare le dipendenze per gli Node.js agenti:

    Dipendenze fornite dal fornitore (le più semplici):

    Includi node_modules/ direttamente nel codice ZIP accanto al punto di ingresso:

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

    Questo produce uno ZIP con la seguente struttura:

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

    In bundle con esbuild (lo ZIP più piccolo):

    Usa esbuild per raggruppare tutte le dipendenze in un unico file:

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

    Questo produce uno ZIP minimo:

    my-agent.zip
    └── bundle.js

    Entrambi gli approcci funzionano. Le distribuzioni in bundle sono in genere inferiori a 10 MB e vengono implementate più velocemente. Le implementazioni fornite dai fornitori sono più semplici e non richiedono una fase di creazione, ma possono essere più ampie.

    AgentCore Runtime supporta solo l'architettura del set di istruzioni arm64. Se il tuo agente utilizza pacchetti npm che includono moduli nativi (compilati .node o .so file), tali file binari devono essere compilati per Linux arm64.

    AgentCore Runtime convalida l'architettura di tutti i .node .so file del pacchetto di distribuzione leggendo le relative intestazioni ELF. Se viene compilato un file binario per un'architettura diversa (ad esempio x86_64 o macOS), la creazione dell'agente avrà esito negativo e restituirà status. CREATE_FAILED

    Per installare moduli nativi compatibili con arm64:

    • Installa le dipendenze su una macchina arm64 (come un'istanza Amazon AWS Graviton-based EC2)

    • Usa npm e flag: --arch --platform

      npm install --arch=arm64 --platform=linux
    • Usa esbuild per raggruppare il tuo codice se il modulo nativo può essere evitato in fase di esecuzione

    I pacchetti npm più popolari (Express, Axios, Fastify, Hono, ws) sono puri JavaScript e non contengono moduli nativi.

    AgentCore Runtime non esegue direttamente TypeScript i file. È necessario compilare il codice TypeScript sorgente in JavaScript prima della distribuzione. Questo è lo stesso modello usato da AWS Lambda.

    Usando il TypeScript compilatore (tsc):

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

    Quindi impacchetta l'output compilato:

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

    Quando crei l'agente, imposta il punto di ingresso sul .js file compilato (ad esempio, app.js o in dist/app.js base alla struttura ZIP).

    Usare esbuild (consigliato per una confezione più semplice):

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

    esbuild compila TypeScript e raggruppa le dipendenze in un unico passaggio, producendo un piccolo file autonomo. .js

    Se package.json includi un engines.node campo, AgentCore Runtime verifica che l'intervallo specificato sia compatibile con la Node.js versione selezionata (ad esempio, Node.js 22 quando si utilizza il runtime). NODE_22 Se l'intervallo esclude quella versione, la creazione dell'agente avrà esito negativo e riporterà lo status. CREATE_FAILED

    Ad esempio, le seguenti engines dichiarazioni sono compatibili con Node.js 22:

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

    Le seguenti dichiarazioni sono incompatibili e impediranno la creazione dell'agente:

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

    AgentCore Runtime verifica inoltre la presenza di dipendenze comuni engines.node nel campo. node_modules/ Se una di queste dichiara un intervallo di versioni che esclude la Node.js versione di runtime di destinazione, la creazione dell'agente avrà esito negativo.

    Se riscontri un'engines.nodeincompatibilità, aggiorna il pacchetto a una versione che supporti la versione di destinazione Node.js o rimuovi il engines campo dal tuo. package.json Per Node.js le versioni supportate, consulta Runtime linguistici supportati.