# AWS AgentCore

> Run an Amazon Bedrock AgentCore agent in the pipeline, in place of an LLM, with AWSAgentCoreProcessor.

Source: https://polvallverdu.github.io/pipedog/docs/services/llm/aws-agentcore/



## Overview [#overview]

`AWSAgentCoreProcessor` sends the conversation to an agent hosted on Amazon Bedrock AgentCore
Runtime and pushes the agent's replies as `LLMTextFrame`s, so it sits where an LLM service would:
after the user context aggregator, before TTS.

* On each `LLMContextFrame` it builds a payload from the context and calls
  `InvokeAgentRuntime`.
* Each line the agent streams back is turned into text and pushed as an `LLMTextFrame`, between
  `LLMFullResponseStartFrame` and `LLMFullResponseEndFrame`. A response is closed when no new text
  arrives for 1 second.

<Cards>
  <Card title="Source" href="https://github.com/polvallverdu/pipedog/tree/main/packages/aws/src">
    `packages/aws/src/agent_core.ts`.
  </Card>

  <Card title="AgentCore docs" href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-invoke-agent.html">
    Deploying and invoking AgentCore Runtime agents.
  </Card>
</Cards>

## Installation [#installation]

```bash
bun add @pipedog/aws
```

```ts
import { AWSAgentCoreProcessor } from "@pipedog/aws/agent_core";
```

## Prerequisites [#prerequisites]

* An agent deployed to AgentCore Runtime, and its ARN.
* An IAM identity allowed `bedrock-agentcore:InvokeAgentRuntime`.
* Keys, in this order of precedence:

  1. `awsAccessKey`, `awsSecretKey` and `awsSessionToken`.
  2. The `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN` environment
     variables.
  3. A `credentialsProvider` function, called for every request.

  The region comes from `awsRegion`, else `AWS_REGION`, else `us-east-1`.

## AWSAgentCoreProcessor [#awsagentcoreprocessor]

### Configuration [#configuration]

| Option | Type | Required | Description |
|---|---|---|---|
| `agentArn` | `string` | yes | The Amazon Web Services Resource Name (ARN) of the agent. |
| `awsAccessKey` | `string \| null \| undefined` | no | AWS access key ID. If null, falls back to environment variables and `credentialsProvider`. |
| `awsSecretKey` | `string \| null \| undefined` | no | AWS secret access key. Same fallback behaviour as `awsAccessKey`. |
| `awsSessionToken` | `string \| null \| undefined` | no | AWS session token for temporary credentials. |
| `awsRegion` | `string \| null \| undefined` | no | AWS region. |
| `contextToPayloadTransformer` | `((context: LLMContext) => string \| null) \| null \| undefined` | no | Optional function to transform LLMContext into AgentCore payload string. If null, uses `defaultContextToPayloadTransformer`. |
| `responseToOutputTransformer` | `((responseLine: string) => string \| null) \| null \| undefined` | no | Optional function to extract output text from AgentCore response. If null, uses `defaultResponseToOutputTransformer`. |
| `name` | `string \| null \| undefined` | no | Custom name; defaults to `ClassName#count`. |
| `taskManager` | `BaseTaskManager \| null \| undefined` | no | Task manager for handling tasks. |
| `enableDirectMode` | `boolean \| undefined` | no | Process frames immediately instead of using internal queues. |
| `metrics` | `FrameProcessorMetrics \| null \| undefined` | no | Optional metrics collector for this processor. |
| `credentialsProvider` | `AWSCredentialsProvider \| null \| undefined` | no | Keys to sign with when none are passed in or set in the environment. Called for every request or connection, so it can renew temporary credentials. |
| `fetch` | `FetchLike \| null \| undefined` | no | `fetch` used for HTTP calls (defaults to the global `fetch`). |
| `endpointUrl` | `string \| null \| undefined` | no | Override the service endpoint (e.g. a VPC endpoint or a local fake), `https://host[:port]`. |

### Usage [#usage]

```ts title="agent.ts"
import { AWSAgentCoreProcessor } from "@pipedog/aws/agent_core";
import type { LLMContext } from "@pipedog/core/processors/aggregators/llm_context";

const agent = new AWSAgentCoreProcessor({
  agentArn: "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/my-agent",
  awsRegion: "us-east-1",
});
// new Pipeline([transport.input(), stt, userAggregator, agent, tts, transport.output(), ...])
```

By default the payload is `{"prompt": "<text>"}`, from the last message when it is a user or
system message, and each response line is read as `{"response": "<text>"}`. Change both with the
transformers:

```ts
const customAgent = new AWSAgentCoreProcessor({
  agentArn: "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/my-agent",
  // Send the whole conversation instead of the last user message.
  contextToPayloadTransformer: (context: LLMContext) =>
    JSON.stringify({ messages: context.getMessages() }),
  // The agent streams `data: {"text": "..."}` lines; the processor strips `data: `.
  responseToOutputTransformer: (line: string) => {
    try {
      return (JSON.parse(line) as { text?: string }).text ?? null;
    } catch {
      return null;
    }
  },
});
```

A transformer that returns `null` skips the call (for the payload) or the line (for the output).

### Notes [#notes]

* Each call gets a new `X-Amzn-Bedrock-AgentCore-Runtime-Session-Id`, as botocore generates one.
* A streamed `text/event-stream` response is split into lines as they arrive, joining a line
  split across two chunks. Lines must start with `data: `, which is stripped before the output
  transformer sees them. Any other response is read whole and passed to the transformer once.
* The `LLMContextFrame` is consumed. Other frames pass through unchanged.

## Runtime notes [#runtime-notes]

| Runtime            | Works | What it needs |
| ------------------ | ----- | ------------- |
| Bun                | ✅ yes | Nothing.      |
| Node.js            | ✅ yes | Nothing.      |
| Deno               | ✅ yes | Nothing.      |
| Cloudflare Workers | ✅ yes | Nothing.      |

Generated from `pipecat.runtimes` and `pipecat.compat` in `packages/aws/package.json`: ✅ means the compat smoke test passes on that runtime.

* Runs on Bun, Node, Deno and Cloudflare Workers: `POST /runtimes/{arn}/invocations` with `fetch`,
  signed with SigV4 on WebCrypto.
* There is no default AWS credential chain. Use keys, the environment, or `credentialsProvider`.
* `endpointUrl` and `fetch` replace the AgentCore host and the global `fetch`.
