Skip to content

feat(aws): add AWS plugin (Bedrock LLM, Transcribe STT, Polly TTS)#1998

Open
smorimoto wants to merge 13 commits into
livekit:mainfrom
smorimoto:feat/aws-plugin
Open

feat(aws): add AWS plugin (Bedrock LLM, Transcribe STT, Polly TTS)#1998
smorimoto wants to merge 13 commits into
livekit:mainfrom
smorimoto:feat/aws-plugin

Conversation

@smorimoto

Copy link
Copy Markdown
Contributor

Summary

  • Add @livekit/agents-plugin-aws, a new provider plugin covering LLM (Amazon Bedrock Converse), STT (Amazon Transcribe streaming) and TTS (Amazon Polly)
  • Add an 'aws' ProviderFormat to @livekit/agents for converting ChatContext into Bedrock Converse messages, alongside the existing google/mistralai/openai formats
  • TTS synthesises raw PCM (16-bit little-endian, mono) rather than mp3, as the framework has no mp3 decoder; Polly only supports PCM at 8000 Hz or 16000 Hz, so sampleRate is restricted to those two values
  • STT handles Amazon Transcribe's ~15s idle-timeout reconnects transparently, keeping word/segment timestamps monotonic and speaking state consistent across reconnects, including per audio channel
  • Credentials resolve via the AWS SDK v3 default credential chain unless supplied explicitly; region resolves from regionAWS_REGIONAWS_DEFAULT_REGIONus-east-1
  • Nova Sonic realtime is intentionally out of scope for this change and will follow separately
  • Adds examples/src/aws.ts, a plugin README, a root README table entry, turbo.json env vars, and a changeset

Test plan

  • pnpm build (all 38 packages, including examples)
  • pnpm test — unit tests for the provider format and all three components pass without AWS credentials; live tests gate on AWS_ACCESS_KEY_ID/AWS_PROFILE and are skipped otherwise
  • pnpm lint / pnpm format:check
  • Live smoke test against real AWS credentials (node ./examples/src/aws.ts dev)

Add @livekit/agents-plugin-aws, providing:
- LLM via Amazon Bedrock Converse (streaming, tool calling, prompt caching)
- STT via Amazon Transcribe streaming (word-level timestamps, channel
  identification, idle-timeout reconnects)
- TTS via Amazon Polly (PCM output, since the framework has no mp3 decoder)

Also adds an 'aws' provider format to @livekit/agents for converting
ChatContext into Bedrock Converse messages.

Nova Sonic realtime is out of scope for this change.
@smorimoto smorimoto requested a review from a team as a code owner July 8, 2026 18:35
@changeset-bot

changeset-bot Bot commented Jul 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d98d3e1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 37 packages
Name Type
@livekit/agents-plugin-aws Major
@livekit/agents Major
@livekit/agents-plugin-anam Major
@livekit/agents-plugin-anthropic Major
@livekit/agents-plugin-assemblyai Major
@livekit/agents-plugin-baseten Major
@livekit/agents-plugin-bey Major
@livekit/agents-plugin-cartesia Major
@livekit/agents-plugin-cerebras Major
@livekit/agents-plugin-deepgram Major
@livekit/agents-plugin-did Major
@livekit/agents-plugin-elevenlabs Major
@livekit/agents-plugin-fishaudio Major
@livekit/agents-plugin-google Major
@livekit/agents-plugin-hedra Major
@livekit/agents-plugin-hume Major
@livekit/agents-plugin-inworld Major
@livekit/agents-plugin-lemonslice Major
@livekit/agents-plugin-liveavatar Major
@livekit/agents-plugin-livekit Major
@livekit/agents-plugin-minimax Major
@livekit/agents-plugin-mistral Major
@livekit/agents-plugin-mistralai Major
@livekit/agents-plugin-neuphonic Major
@livekit/agents-plugin-openai Major
@livekit/agents-plugin-perplexity Major
@livekit/agents-plugin-phonic Major
@livekit/agents-plugin-resemble Major
@livekit/agents-plugin-rime Major
@livekit/agents-plugin-runway Major
@livekit/agents-plugin-sarvam Major
@livekit/agents-plugin-silero Major
@livekit/agents-plugin-soniox Major
@livekit/agents-plugin-tavus Major
@livekit/agents-plugins-test Major
@livekit/agents-plugin-trugen Major
@livekit/agents-plugin-xai Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

devin-ai-integration[bot]

This comment was marked as resolved.

flush() ran before write(audioBytes), always draining an empty buffer
and dropping the tail of synthesized audio when Polly's byte length
isn't an exact 100ms multiple.
chatgpt-codex-connector[bot]

This comment was marked as resolved.

Map SDK status errors to APIStatusError so non-retryable 4xx inputs are not
retried as connection failures, surface Transcribe event-stream exceptions,
and require languageOptions when automatic language identification is enabled.
devin-ai-integration[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

Map validationException to 400, keep modelStreamError 424 retryable,
requeue audio frames across STT reconnects, validate channel options,
and surface speaker labels from Transcribe.
chatgpt-codex-connector[bot]

This comment was marked as resolved.

Honour request timeouts, preserve Transcribe speaker and language metadata, and close owned AWS clients.

Trim redundant tests, exclude test artefacts from the published package, and add API and CI coverage.
devin-ai-integration[bot]

This comment was marked as resolved.

Clear the connection timeout once Bedrock has returned a streaming response, while preserving caller-initiated cancellation.

Add regression coverage for responses that outlive the connection timeout.
chatgpt-codex-connector[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

Reuse the shared toAwsApiError classifier in the Bedrock LLM stream
instead of duplicating its logic, cache decoded image bytes so vision
turns aren't re-decoded on every request, and simplify a couple of
pieces of stream-tracking state in the Transcribe and Polly plugins
that never actually held more than one item.
devin-ai-integration[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d98d3e13c6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/aws/src/llm.ts
const description = tool.description.trim();
return {
toolSpec: {
name,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate Bedrock tool names before sending

When a registered tool name contains characters such as ./space or is longer than 64 characters, this serializes it directly as toolSpec.name; the framework only requires tool names to be non-empty, but Bedrock's ToolSpecification requires names to match [a-zA-Z0-9_-]+ and be at most 64 chars. In those cases any chat with that tool is rejected before inference, so validate or map AWS tool names here and apply the same mapping when replaying toolUse history.

Useful? React with 👍 / 👎.

Comment thread plugins/aws/src/llm.ts
} from '@livekit/agents';
import { type AwsCredentials, createRequestSignal, resolveRegion, toAwsApiError } from './utils.js';

const DEFAULT_MODEL = 'amazon.nova-2-lite-v1:0';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Default to an invokable Nova 2 profile

When callers rely on the advertised default model, new aws.LLM().chat(...) sends amazon.nova-2-lite-v1:0 directly to ConverseStream. Nova 2 Lite on Bedrock runtime requires an inference-profile ID such as us.amazon.nova-2-lite-v1:0/global.amazon.nova-2-lite-v1:0 for on-demand invocation in the default regions, so the zero-config example fails with a ValidationException unless users discover and override the model; default to a region-appropriate profile or to a model ID that supports on-demand throughput.

Useful? React with 👍 / 👎.

Comment thread plugins/aws/src/llm.ts
Comment on lines +292 to +293
if (!toolConfig) {
chatCtx = chatCtx.copy({ excludeFunctionCall: true });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve tool results when disabling new tools

When the framework asks for a follow-up with toolChoice: 'none' after a tool has run (for example after max tool steps are reached), buildToolConfig returns undefined and this drops every function_call/function_call_output from chatCtx. The final Bedrock request therefore no longer contains the tool output it is supposed to answer from, so it can produce a generic answer unrelated to the tool result; only strip tool history when there are no previous tool blocks to replay, or use a separate mechanism to prevent additional tool calls.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant