AWS AgentCore
Run an Amazon Bedrock AgentCore agent in the pipeline, in place of an LLM, with AWSAgentCoreProcessor.
Overview
AWSAgentCoreProcessor sends the conversation to an agent hosted on Amazon Bedrock AgentCore
Runtime and pushes the agent's replies as LLMTextFrames, so it sits where an LLM service would:
after the user context aggregator, before TTS.
- On each
LLMContextFrameit builds a payload from the context and callsInvokeAgentRuntime. - Each line the agent streams back is turned into text and pushed as an
LLMTextFrame, betweenLLMFullResponseStartFrameandLLMFullResponseEndFrame. A response is closed when no new text arrives for 1 second.
Installation
bun add @pipedog/awsimport { AWSAgentCoreProcessor } from "@pipedog/aws/agent_core";Prerequisites
-
An agent deployed to AgentCore Runtime, and its ARN.
-
An IAM identity allowed
bedrock-agentcore:InvokeAgentRuntime. -
Keys, in this order of precedence:
awsAccessKey,awsSecretKeyandawsSessionToken.- The
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEYandAWS_SESSION_TOKENenvironment variables. - A
credentialsProviderfunction, called for every request.
The region comes from
awsRegion, elseAWS_REGION, elseus-east-1.
AWSAgentCoreProcessor
Configuration
Prop
Type
Usage
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:
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
- Each call gets a new
X-Amzn-Bedrock-AgentCore-Runtime-Session-Id, as botocore generates one. - A streamed
text/event-streamresponse is split into lines as they arrive, joining a line split across two chunks. Lines must start withdata:, which is stripped before the output transformer sees them. Any other response is read whole and passed to the transformer once. - The
LLMContextFrameis consumed. Other frames pass through unchanged.
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}/invocationswithfetch, signed with SigV4 on WebCrypto. - There is no default AWS credential chain. Use keys, the environment, or
credentialsProvider. endpointUrlandfetchreplace the AgentCore host and the globalfetch.
pipedog is an unofficial community TypeScript port of Pipecat. It is not affiliated with or endorsed by Daily or the Pipecat project.
Portions adapted from the Pipecat documentation, Copyright (c) 2024–2025 Daily, BSD-2-Clause (see apps/docs/LICENSE-pipecat-docs).