Skip to content
Draft
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
61 changes: 53 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -928,13 +928,25 @@ An example of using the client with Microsoft Entra ID (formerly known as Azure

## Amazon Bedrock

To use this library with [Amazon Bedrock's OpenAI-compatible API](https://docs.aws.amazon.com/bedrock/latest/userguide/models-api-compatibility.html), use the `BedrockOpenAI` class instead of the `OpenAI` class.
To use this library with [Amazon Bedrock's OpenAI-compatible API](https://docs.aws.amazon.com/bedrock/latest/userguide/models-api-compatibility.html), configure the standard `OpenAI` client with the Bedrock provider.

Install the optional Bedrock dependencies to use the standard AWS credential chain and SigV4 authentication:

```sh
pip install 'openai[bedrock]'
```

```py
from openai import BedrockOpenAI
from openai import OpenAI
from openai.providers import bedrock

# gets the bearer token from AWS_BEARER_TOKEN_BEDROCK and the region from AWS_REGION/AWS_DEFAULT_REGION
client = BedrockOpenAI()
# Uses your normal AWS credentials. You can omit region when it is
# configured through AWS_REGION, AWS_DEFAULT_REGION, or your AWS profile.
client = OpenAI(
provider=bedrock(
region="us-west-2",
)
)

response = client.responses.create(
model="openai.gpt-5.4",
Expand All @@ -944,19 +956,52 @@ response = client.responses.create(
print(response.output_text)
```

`BedrockOpenAI` configures AWS bearer auth and the Bedrock Mantle endpoint, then uses the normal SDK resources. AWS controls which endpoints and features are supported; unsupported calls surface the provider's normal HTTP errors through the SDK.
The provider configures AWS authentication and the Bedrock Mantle endpoint while retaining the normal SDK resources, retries, streaming, and error handling. AWS controls which endpoints and features are supported; unsupported calls surface the provider's normal HTTP errors through the SDK.

The default AWS credential chain supports environment credentials, shared credentials and config files, named profiles, SSO and assume-role profiles, and workload credentials such as ECS, EKS, and EC2 metadata. To select a named profile:

```py
client = OpenAI(
provider=bedrock(
profile="my-profile",
)
)
```

You can also pass `access_key_id` and `secret_access_key`, with an optional `session_token`, or a refreshable `credential_provider` that returns botocore-compatible credentials. Explicit bearer and AWS credential options are mutually exclusive.

Pass `base_url` or set `AWS_BEDROCK_BASE_URL` to override the derived `https://bedrock-mantle.<region>.api.aws/openai/v1` endpoint. The legacy module client supports `openai.api_type = "amazon-bedrock"` or `OPENAI_API_TYPE=amazon-bedrock`.
Pass `base_url` to `bedrock(...)` or set `AWS_BEDROCK_BASE_URL` to override the derived `https://bedrock-mantle.<region>.api.aws/openai/v1` endpoint.

Set `AWS_BEARER_TOKEN_BEDROCK` to an [Amazon Bedrock API key](https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys.html). To refresh tokens yourself, pass a provider instead of `api_key`:
SigV4 requests require replayable, fully serialized request bodies. Standard JSON requests already meet this requirement, and response streaming is unaffected. Low-level one-shot request streams must be buffered before sending, or sent with bearer authentication and retries disabled.

Bearer tokens remain available as a compatibility or manual authentication mode. Set `AWS_BEARER_TOKEN_BEDROCK` to an [Amazon Bedrock API key](https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys.html), pass `api_key`, or provide a refresh callback:

```py
client = OpenAI(
provider=bedrock(
region="us-west-2",
token_provider=lambda: refresh_bedrock_token(),
)
)
```

Without explicit authentication, `AWS_BEARER_TOKEN_BEDROCK` takes precedence over the default AWS credential chain for backwards compatibility.

### Legacy `BedrockOpenAI` client

`BedrockOpenAI` and `AsyncBedrockOpenAI` remain available for existing applications and delegate to the same provider implementation. New applications should prefer `OpenAI(provider=bedrock(...))`.

```py
from openai import BedrockOpenAI

client = BedrockOpenAI(
aws_region="us-west-2",
bedrock_token_provider=lambda: refresh_bedrock_token(),
aws_profile="my-profile",
)
```

The legacy module client also continues to support `openai.api_type = "amazon-bedrock"` or `OPENAI_API_TYPE=amazon-bedrock`.

## Versioning

This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
Expand Down
12 changes: 7 additions & 5 deletions examples/bedrock.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from openai import BedrockOpenAI
from openai import OpenAI
from openai.providers import bedrock

client = BedrockOpenAI()

# For refreshed Bedrock bearer tokens:
# client = BedrockOpenAI(aws_region="us-west-2", bedrock_token_provider=get_bedrock_token)
client = OpenAI(
provider=bedrock(
region="us-west-2",
)
)

response = client.responses.create(
model="openai.gpt-5.4",
Expand Down
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"]
realtime = ["websockets >= 13, < 16"]
datalib = ["numpy >= 1", "pandas >= 1.2.3", "pandas-stubs >= 1.1.0.11"]
voice_helpers = ["sounddevice>=0.5.1", "numpy>=2.0.2"]
bedrock = [
"botocore[crt]>=1.42.0,<1.43; python_version < '3.10'",
"botocore[crt]>=1.42.0,<2; python_version >= '3.10'",
]

[tool.rye]
managed = true
Expand All @@ -57,6 +61,7 @@ dev-dependencies = [
"respx",
"pytest",
"pytest-asyncio",
"jsonschema>=4.23.0",
"ruff",
"time-machine",
"nox",
Expand All @@ -65,6 +70,7 @@ dev-dependencies = [
"rich>=13.7.1",
"inline-snapshot>=0.28.0",
"azure-identity >=1.14.1",
"botocore==1.42.97",
"types-tqdm > 4",
"types-pyaudio > 0",
"trio >=0.22.2",
Expand Down
27 changes: 24 additions & 3 deletions requirements-dev.lock
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,20 @@ async-timeout==5.0.1
# via aiohttp
attrs==25.4.0
# via aiohttp
# via jsonschema
# via nox
# via outcome
# via referencing
# via trio
awscrt==0.31.2
# via botocore
azure-core==1.36.0
# via azure-identity
azure-identity==1.25.1
backports-asyncio-runner==1.2.0
# via pytest-asyncio
botocore==1.42.97
# via openai
certifi==2026.1.4
# via httpcore
# via httpx
Expand Down Expand Up @@ -100,6 +106,11 @@ iniconfig==2.1.0
inline-snapshot==0.31.1
jiter==0.12.0
# via openai
jmespath==1.1.0
# via botocore
jsonschema==4.25.1
jsonschema-specifications==2025.9.1
# via jsonschema
markdown-it-py==3.0.0
# via rich
mdurl==0.1.2
Expand Down Expand Up @@ -161,16 +172,23 @@ pytest==8.4.2
pytest-asyncio==1.2.0
pytest-xdist==3.8.0
python-dateutil==2.9.0.post0
# via botocore
# via pandas
# via time-machine
pytz==2025.2
# via pandas
referencing==0.36.2
# via jsonschema
# via jsonschema-specifications
requests==2.32.5
# via azure-core
# via msal
respx==0.22.0
rich==14.2.0
# via inline-snapshot
rpds-py==0.27.1
# via jsonschema
# via referencing
ruff==0.14.7
six==1.17.0
# via python-dateutil
Expand All @@ -194,9 +212,11 @@ trio==0.31.0
types-pyaudio==0.2.16.20250801
types-pytz==2025.2.0.20251108
# via pandas-stubs
types-requests==2.32.4.20250913
types-requests==2.31.0.6
# via types-tqdm
types-tqdm==4.67.0.20250809
types-urllib3==1.26.25.14
# via types-requests
typing-extensions==4.15.0
# via aiosignal
# via anyio
Expand All @@ -211,15 +231,16 @@ typing-extensions==4.15.0
# via pydantic-core
# via pyright
# via pytest-asyncio
# via referencing
# via typing-inspection
# via virtualenv
typing-inspection==0.4.2
# via pydantic
tzdata==2025.2
# via pandas
urllib3==2.5.0
urllib3==1.26.20
# via botocore
# via requests
# via types-requests
virtualenv==20.35.4
# via nox
websockets==15.0.1
Expand Down
8 changes: 8 additions & 0 deletions requirements.lock
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ async-timeout==5.0.1
# via aiohttp
attrs==25.4.0
# via aiohttp
awscrt==0.31.2
# via botocore
botocore==1.42.97
# via openai
certifi==2026.1.4
# via httpcore
# via httpx
Expand Down Expand Up @@ -53,6 +57,8 @@ idna==3.11
# via yarl
jiter==0.12.0
# via openai
jmespath==1.1.0
# via botocore
multidict==6.7.0
# via aiohttp
# via yarl
Expand Down Expand Up @@ -100,6 +106,8 @@ typing-inspection==0.4.2
# via pydantic
tzdata==2025.2
# via pandas
urllib3==1.26.20
# via botocore
websockets==15.0.1
# via openai
yarl==1.22.0
Expand Down
13 changes: 13 additions & 0 deletions src/openai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,19 @@ def api_key(self, value: str | None) -> None: # type: ignore

_bedrock_api_key = value

@override
def _refresh_api_key(self) -> str:
if api_key is not None:
return api_key

return super()._refresh_api_key()

@override
def _legacy_auth_configuration(self) -> _bedrock._LegacyAuthConfiguration:
if api_key is not None:
return ("bearer", api_key)
return super()._legacy_auth_configuration()


class _AmbiguousModuleClientUsageError(OpenAIError):
def __init__(self) -> None:
Expand Down
Loading
Loading