Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/integrations/bedrock.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,29 @@ Or configure using AWS CLI:
aws configure
```

### Bedrock API Key (Bearer Token) Authentication

Instead of AWS credentials, you can authenticate with an [Amazon Bedrock API key](https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys.html). Bedrock offers short-term keys (up to 12 hours, recommended for production) and long-term keys (recommended only for exploration).

Pass the key directly via `api_key`:

```python
import instructor

client = instructor.from_provider(
"bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0",
api_key="your-bedrock-api-key",
)
```

Or set the environment variable that botocore reads natively:

```bash
export AWS_BEARER_TOKEN_BEDROCK=your-bedrock-api-key
```

> **Note:** Bearer token authentication requires `boto3>=1.39.0`. When a Bedrock API key is set, it takes precedence over AWS credentials for Bedrock requests.

## Sync Example

```python
Expand Down
9 changes: 8 additions & 1 deletion instructor/v2/auto_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,7 @@ def _build_bedrock(
model_name: str,
async_client: bool,
mode: Mode | None,
api_key: str | None, # noqa: ARG001
api_key: str | None,
kwargs: dict[str, Any],
provider_info: dict[str, str],
) -> InstructorType:
Expand All @@ -987,6 +987,13 @@ def _build_bedrock(
)
region = os.environ.get("AWS_DEFAULT_REGION", "us-east-1")

# Bedrock API keys (bearer tokens) authenticate without SigV4 credentials.
# botocore >= 1.39.0 reads AWS_BEARER_TOKEN_BEDROCK at request time, so
# exporting the key is the supported way to enable bearer auth.
if api_key:
os.environ["AWS_BEARER_TOKEN_BEDROCK"] = api_key
logger.debug("Using Bedrock API key (bearer token) authentication")

# Extract AWS-specific parameters
# Dictionary to collect AWS credentials and session parameters for boto3 client
aws_kwargs = {}
Expand Down
63 changes: 63 additions & 0 deletions tests/v2/test_auto_client_deterministic.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,69 @@ def fake_from_bedrock(_client: Any, **kwargs: Any) -> dict[str, Any]:
assert calls[1]["mode"] == Mode.MD_JSON


def test_build_bedrock_api_key_enables_bearer_token_auth(
monkeypatch: pytest.MonkeyPatch,
) -> None:
import os

boto3_module = ModuleType("boto3")
setattr(boto3_module, "client", lambda *_args, **_kwargs: object()) # noqa: B010
monkeypatch.setitem(__import__("sys").modules, "boto3", boto3_module)

import instructor.v2.providers.bedrock.client as bedrock_client

monkeypatch.setattr(
bedrock_client, "from_bedrock", lambda _client, **kwargs: kwargs
)

# Ensure the variable is absent but restored to its original state on teardown
monkeypatch.setenv("AWS_BEARER_TOKEN_BEDROCK", "sentinel")
monkeypatch.delenv("AWS_BEARER_TOKEN_BEDROCK")

auto_client._build_bedrock(
provider="bedrock",
model_name="anthropic.claude-3-7-sonnet",
async_client=False,
mode=None,
api_key="bedrock-api-key",
kwargs={},
provider_info={"provider": "bedrock", "operation": "initialize"},
)

assert os.environ["AWS_BEARER_TOKEN_BEDROCK"] == "bedrock-api-key"


def test_build_bedrock_without_api_key_leaves_bearer_token_unset(
monkeypatch: pytest.MonkeyPatch,
) -> None:
import os

boto3_module = ModuleType("boto3")
setattr(boto3_module, "client", lambda *_args, **_kwargs: object()) # noqa: B010
monkeypatch.setitem(__import__("sys").modules, "boto3", boto3_module)

import instructor.v2.providers.bedrock.client as bedrock_client

monkeypatch.setattr(
bedrock_client, "from_bedrock", lambda _client, **kwargs: kwargs
)

monkeypatch.setenv("AWS_BEARER_TOKEN_BEDROCK", "sentinel")
monkeypatch.delenv("AWS_BEARER_TOKEN_BEDROCK")

auto_client._build_bedrock(
provider="bedrock",
model_name="anthropic.claude-3-7-sonnet",
async_client=False,
mode=None,
api_key=None,
kwargs={},
provider_info={"provider": "bedrock", "operation": "initialize"},
)

assert "AWS_BEARER_TOKEN_BEDROCK" not in os.environ


def test_build_ollama_uses_tool_mode_only_for_tool_capable_models(
monkeypatch: pytest.MonkeyPatch,
) -> None:
Expand Down