Dinuda Yaggahavita
Dinuda Yaggahavita

Reputation: 990

How to invoke Agent using Bedrock Agent Runtime Client in AWS SDK for Javascript V3

Invoke Bedrock Agent using the Javacript SDK v3. Link to the SDK: InvokeAgentCommand

Here's my code so far:

const { BedrockAgentRuntimeClient, InvokeAgentCommand } = require("@aws-sdk/client-bedrock-agent-runtime");

const config = {
    accessKeyId: process.env.AWS_BEDROCK_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_BEDROCK_SECRET_ACCESS_KEY,
};


const client = new BedrockAgentRuntimeClient(config);

const input = { 
    agentId: "agentId", 
    agentAliasId: "agentAliasId", 
    sessionId: "abc123", 
    inputText: "Hello",
};

async invokeAgent() {
   return new Promise(async (resolve, reject) => {
      const command = new InvokeAgentCommand(input);
      const response = await client.send(command);
      resolve(response);
   });
}

The response I get currently from the endpoint is:

{
    "$metadata": {
        "httpStatusCode": 200,
        "requestId": "reqId",
        "attempts": 1,
        "totalRetryDelay": 0
    },
    "contentType": "application/json",
    "sessionId": "abc123",
    "completion": {
        "options": {
            "messageStream": {
                "options": {
                    "inputStream": {},
                    "decoder": {
                        "headerMarshaller": {},
                        "messageBuffer": [],
                        "isEndOfStream": false
                    }
                }
            }
        }
    }
}

There is no error that is specified in the SDK either.

Upvotes: 1

Views: 2954

Answers (2)

Aditi Tripathi
Aditi Tripathi

Reputation: 41

For getting trace events, you also need to loop over chunkEvent.trace.

const {
  BedrockAgentRuntimeClient,
  InvokeAgentCommand
} = require("@aws-sdk/client-bedrock-agent-runtime");


const credentials = {
  accessKeyId: "accessKeyId",
  secretAccessKey: "secretAccessKey",
  sessionToken: "sessionToken"
};

const invokingAgent = async(newPayload) => {
  const client = new BedrockAgentRuntimeClient({
    region: "us-west-2",
    credentials: credentials
  });
  console.log("client endpoint: ", client.config.endpoint);

  const command = new InvokeAgentCommand({ ...newPayload
  });
  let runningResponseText = '';
  let runningTraces = [];
  let requestId = '';
  let intermediatePayload = null;
  try {
    let completion = "";
    const response = await client.send(command);

    if (response.completion === undefined) {
      throw new Error("Completion is undefined");
    }
    if (response.completion) {
      requestId = response.$metadata.requestId;
      console.log("requestId: ", response.$metadata);
      for await (const event of response.completion) {
        if (event.chunk) {
          const response = new TextDecoder('utf-8').decode(event.chunk.bytes);
          runningResponseText += response;
        }
        if (event.trace) {
          runningTraces = [...runningTraces, event.trace];
        }
        if (event.returnControl ? .invocationInputs) {
          intermediatePayload = {
            requestId,
            traces: runningTraces,
            invocationInputs: event.returnControl.invocationInputs,
            invocationId: event.returnControl.invocationId,
          };
        }
      }
      console.log("chunk response: ", runningResponseText);
      console.log("returnControl: ", intermediatePayload);
      console.log("trace: ", runningTraces);
      return runningResponseText;
    }
  } catch (e) {
    console.log("Error occurred L50");
    console.error(e);
  }
};


const inputPayload = {
  agentId: "AGENTID",
  agentAliasId: "ALIASID",
  sessionId: "sessionId123new",
  inputText: "can you help with historical weather ? ",
  enableTrace: true
};


(async() => {
  try {
    const result = await invokingAgent(inputPayload);
    console.log(result);
  } catch (error) {
    console.error("Error:", error);
  }
})();

Upvotes: 4

Dinuda Yaggahavita
Dinuda Yaggahavita

Reputation: 990

In the example(invoke a bedrock agent using the API) that was given there was no high level documentation informing users about the need to properly handle the asynchronous nature of streaming data in this case.

async invokeAgent() {
   return new Promise(async (resolve, reject) => {
      let completion = "";
      const command = new InvokeAgentCommand(input);
      const response = await client.send(command);

      for await (const chunkEvent of response.completion) {
        if (chunkEvent.chunk) {
          const chunk = chunkEvent.chunk;
          let decoded = new TextDecoder("utf-8").decode(chunk.bytes);
          completion += decoded;
        }
      }      
      
      resolve(response);
   });
}

for await is used to iterate over the chunks in the response asynchronously. The loop will wait for each chunk to be available before moving on to the next iteration.

Upvotes: 4

Related Questions