# How to Integrate earendil π with Amazon Bedrock: Complete Implementation Guide

> Learn how to integrate earendil π with Amazon Bedrock. This guide shows how to expose Bedrock as a first class LLM provider with AWS credentials or bearer token.

- Repository: [Earendil Works/pi](https://github.com/earendil-works/pi)
- Tags: how-to-guide
- Published: 2026-05-25

---

**earendil π exposes Amazon Bedrock as a first-class LLM provider through automatic lazy registration in the `packages/ai` package, requiring only standard AWS credentials or a bearer token to begin routing requests.**

The earendil-works/pi repository delivers a seamless way to integrate earendil π with Amazon Bedrock without manual provider configuration. The integration relies on an internal provider architecture that handles streaming, authentication, and request metadata automatically once credentials are supplied.

## Architecture of the Bedrock Provider

The integration centers on [`packages/ai/src/providers/amazon-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/providers/amazon-bedrock.ts), which implements the full Bedrock runtime API. This module is lazily loaded when running under the Bun runtime to keep the default Node.js bundle lightweight.

### Core Components

| Component | Role | Source |
|---|---|---|
| **Provider implementation** | Implements the streaming Bedrock API using the AWS SDK (`@aws-sdk/client-bedrock-runtime`). Handles region/profile resolution, optional bearer-token auth, proxy support, and request-metadata tagging. | [`packages/ai/src/providers/amazon-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/providers/amazon-bedrock.ts) |
| **Provider options** | `BedrockOptions` extends the generic `StreamOptions` and adds Bedrock-specific fields (`region`, `profile`, `toolChoice`, `reasoning`, `thinkingBudgets`, `interleavedThinking`, `thinkingDisplay`, `requestMetadata`, `bearerToken`). | lines 53‑85 of [`amazon-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/amazon-bedrock.ts) |
| **Streaming entry point** | `streamBedrock` is the `StreamFunction` that the rest of π calls. It builds the request payload, creates a `BedrockRuntimeClient` with the resolved configuration, and parses the streamed JSON events into `AssistantMessageEventStream` objects. | lines 89‑124 of [`amazon-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/amazon-bedrock.ts) |
| **Lazy registration (Bun runtime)** | [`register-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/register-bedrock.ts) imports the provider module and registers it via `setBedrockProviderModule`. This file is only loaded when the CLI runs under Bun, keeping the default Node bundle lightweight. | [`packages/coding-agent/src/bun/register-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/bun/register-bedrock.ts) |
| **Provider lookup** | [`model-resolver.ts`](https://github.com/earendil-works/pi/blob/main/model-resolver.ts) maps the provider id (`"amazon-bedrock"`) to a default model ID and registers the provider name for UI display. | [`packages/coding-agent/src/core/model-resolver.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/model-resolver.ts) |
| **Display names** | [`provider-display-names.ts`](https://github.com/earendil-works/pi/blob/main/provider-display-names.ts) maps the internal id to a human-readable label ("Amazon Bedrock") used by the `/login` UI and the interactive mode. | [`packages/coding-agent/src/core/provider-display-names.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/provider-display-names.ts) |
| **Credential detection** | `hasBedrockCredentials()` checks for `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY` (or a bearer token) and is used by the test harness to skip Bedrock tests when no credentials are present. | [`packages/ai/test/bedrock-utils.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/test/bedrock-utils.ts) |

## Provider Implementation Details

The `streamBedrock` function in [`packages/ai/src/providers/amazon-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/providers/amazon-bedrock.ts) serves as the primary entry point for all Bedrock requests. It constructs a `BedrockRuntimeClient` with configuration resolved from environment variables and explicit options.

### Configuration Resolution

The provider builds a `BedrockRuntimeClientConfig` object (lines 17‑34) that prioritizes explicit options over environment variables:

- **Region**: Explicit `options.region` → `AWS_REGION` environment variable → SDK defaults
- **Profile**: Loaded from `options.profile` for credential resolution
- **Proxy**: `NodeHttpHandler` configured when `HTTPS_PROXY` or `HTTP_PROXY` is detected
- **Authentication**: Bearer token support via `token`/`authSchemePreference` when `AWS_BEARER_TOKEN_BEDROCK` is set

### Request Building and Streaming

The request payload construction (lines 88‑98) assembles a `commandInput` object containing:

- `modelId`: The fully-qualified Bedrock model identifier
- Converted messages and system prompts
- Inference configuration and tool configuration
- Optional `requestMetadata` for cost-allocation tagging
- Model-specific fields like `thinkingBudgets` for Claude models

The `ConverseStreamCommand` executes the request, and `parseStreamingJson` processes the response into `AssistantMessageEventStream` events including `text`, `tool_call`, `thinking`, `usage`, and `stop` signals.

## Runtime Registration

The integration uses lazy loading to avoid bundling Bedrock-specific dependencies in Node.js environments. When running under Bun, [`packages/coding-agent/src/bun/register-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/bun/register-bedrock.ts) executes and calls `setBedrockProviderModule(bedrockProviderModule)`, registering the compiled provider module with the internal registry.

At runtime, the generic `getModel(providerId, modelId)` function (exposed from `@earendil-works/pi-ai`) looks up the provider using the registry that includes the lazy-registered Bedrock module. This architecture means users need no manual registration code—merely installing π and providing credentials activates the integration.

## Usage Examples

### TypeScript API Integration

Import `getModel` from the AI package and specify `"amazon-bedrock"` as the provider ID:

```typescript
import { getModel } from "@earendil-works/pi-ai";

const model = getModel(
  "amazon-bedrock",
  // Fully‑qualified Bedrock model identifier
  "global.anthropic.claude-opus-4-6-v1"
);

// Use the model in a prompt
const response = await model.run({
  messages: [{ role: "user", content: "Write a haiku about sunrise." }],
  // optional Bedrock‑specific options
  region: "us-east-1",                 // overrides AWS_REGION
  thinkingDisplay: "summarized",       // how Claude thinking is returned
  requestMetadata: { project: "demo" } // cost‑allocation tags
});

console.log(response.content);

```

### CLI with IAM Credentials

Export standard AWS environment variables and invoke the CLI:

```bash
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=us-east-1           # optional, defaults to us-east-1

# Run π with the Bedrock provider

./pi -p "amazon-bedrock" -m "global.anthropic.claude-opus-4-6-v1" \
    -t "Write a short poem about the sea."

```

### Bearer Token Authentication

For environments using bearer tokens instead of IAM keys:

```bash
export AWS_BEARER_TOKEN_BEDROCK=eyJhbGciOi...
./pi -p amazon-bedrock -m "us.anthropic.claude-sonnet-4-5" \
    "Explain quantum entanglement in plain English."

```

## Environment Variables Reference

The following variables control the Bedrock integration behavior in [`packages/ai/src/providers/amazon-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/providers/amazon-bedrock.ts) (lines 36‑39, 44‑50, 78‑84):

| Variable | Purpose |
|---|---|
| `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` | Standard IAM credentials consumed by the AWS SDK |
| `AWS_REGION` | Default region when no explicit `region` option is provided |
| `AWS_PROFILE` | Named profile for credential resolution |
| `AWS_BEARER_TOKEN_BEDROCK` | Direct bearer-token authentication (requires `bedrock:CallWithBearerToken` permission) |
| `AWS_BEDROCK_SKIP_AUTH=1` | Bypass AWS signing for unauthenticated endpoints |
| `AWS_BEDROCK_FORCE_HTTP1=1` | Force HTTP/1.1 when custom endpoints reject HTTP/2 |
| `HTTPS_PROXY` / `HTTP_PROXY` | Proxy URLs translated into node-http agents via `createHttpProxyAgentsForTarget` |

## Summary

- **earendil π** integrates Amazon Bedrock through the [`packages/ai/src/providers/amazon-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/providers/amazon-bedrock.ts) provider implementation
- The provider supports both **IAM credentials** and **bearer token authentication** with automatic proxy detection
- **Lazy registration** via [`packages/coding-agent/src/bun/register-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/bun/register-bedrock.ts) keeps Node.js bundles lightweight while enabling Bun runtime support
- The `streamBedrock` function handles request construction, streaming via `ConverseStreamCommand`, and event parsing into `AssistantMessageEventStream` objects
- Users configure the integration through standard AWS environment variables or explicit options in the TypeScript API, with no manual provider registration required

## Frequently Asked Questions

### What AWS credentials does earendil π require for Bedrock integration?

earendil π accepts standard IAM credentials via `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`, or alternatively a bearer token through `AWS_BEARER_TOKEN_BEDROCK`. The credential detection logic in [`packages/ai/test/bedrock-utils.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/test/bedrock-utils.ts) uses `hasBedrockCredentials()` to verify that at least one authentication method is present before attempting calls.

### Does the Bedrock provider work in Node.js environments?

The Bedrock provider is lazily registered only when running under the Bun runtime via [`packages/coding-agent/src/bun/register-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/bun/register-bedrock.ts). While the core provider code in `packages/ai` is runtime-agnostic, the automatic registration mechanism currently targets Bun specifically to maintain a lightweight default bundle for Node.js users.

### How does earendil π handle Bedrock's streaming responses?

The `streamBedrock` function (lines 89‑124 of [`amazon-bedrock.ts`](https://github.com/earendil-works/pi/blob/main/amazon-bedrock.ts)) executes a `ConverseStreamCommand` and processes the response through `parseStreamingJson`, converting Bedrock's JSON events into standardized `AssistantMessageEventStream` objects that include text content, tool calls, thinking blocks, usage statistics, and stop signals.

### Can I specify custom regions or endpoints for Bedrock?

Yes. The provider accepts a `region` option that overrides `AWS_REGION`, and supports custom endpoints through the `endpoint` field in the `BedrockRuntimeClientConfig`. Additionally, setting `AWS_BEDROCK_FORCE_HTTP1=1` forces HTTP/1.1 for endpoints that do not support HTTP/2.