-
-
Notifications
You must be signed in to change notification settings - Fork 999
feat(bedrock): Add support for AWS Bedrock native structured outputs #2084
Description
Is your feature request related to a problem? Please describe.
AWS Bedrock announced native structured outputs support in February 2026, providing guaranteed JSON schema compliance for Claude 4.5+ models and select open-weight models. Currently, Instructor's Bedrock integration relies on prompt engineering (BEDROCK_JSON mode) or basic tool calling (BEDROCK_TOOLS mode), which can lead to validation failures and retries.
The current implementation:
- Injects JSON schema instructions into system prompts for
BEDROCK_JSONmode (seehandle_bedrock_json()ininstructor/providers/bedrock/utils.py:417-453) - Uses basic
toolConfigwithout schema enforcement forBEDROCK_TOOLSmode (seehandle_bedrock_tools()ininstructor/providers/bedrock/utils.py:456-482)
This approach misses the benefits of Bedrock's native feature:
- No guaranteed schema compliance (relies on model interpretation)
- Higher retry rates when validation fails
- Increased token costs from retries
- Less predictable production behavior
Describe the solution you'd like
Add support for Bedrock's native structured outputs feature through two complementary approaches, following the patterns established by other providers (OpenAI's TOOLS_STRICT/JSON_SCHEMA, Mistral's MISTRAL_STRUCTURED_OUTPUTS):
1. JSON Schema Output Format
Add a new mode (or enhance existing BEDROCK_JSON to use) that leverages outputConfig.textFormat for the Converse API:
import instructor
from pydantic import BaseModel
client = instructor.from_provider(
"bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0",
mode=instructor.Mode.BEDROCK_STRUCTURED_OUTPUTS # or Mode.JSON_SCHEMA
)
class User(BaseModel):
name: str
age: int
user = client.create(
modelId="anthropic.claude-sonnet-4-5-20250929-v1:0",
messages=[{"role": "user", "content": "Extract: Jason is 25 years old"}],
response_model=User,
)
# Response guaranteed to conform to User schemaImplementation approach (based on similar providers):
Follow the pattern from handle_mistral_structured_outputs() in instructor/providers/mistral/utils.py:94-109.
Add handler function in instructor/providers/bedrock/utils.py:
def handle_bedrock_structured_outputs(
response_model: type[Any], new_kwargs: dict[str, Any]
) -> tuple[type[Any], dict[str, Any]]:
"""
Handle Bedrock structured outputs mode using native outputConfig.
Kwargs modifications:
- Adds: "outputConfig" with textFormat.jsonSchema
- Removes: System prompt JSON instructions (no longer needed)
"""
schema = response_model.model_json_schema()
new_kwargs["outputConfig"] = {
"textFormat": {
"type": "json_schema",
"structure": {
"jsonSchema": {
"schema": json.dumps(schema),
"name": response_model.__name__,
"description": response_model.__doc__ or f"Extract {response_model.__name__}"
}
}
}
}
# Remove any JSON instruction prompts from system messages
# since native schema enforcement handles this
return response_model, _prepare_bedrock_converse_kwargs_internal(new_kwargs)2. Strict Tool Use
Enhance BEDROCK_TOOLS mode to support the strict: true flag for tool definitions:
client = instructor.from_provider(
"bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0",
mode=instructor.Mode.BEDROCK_TOOLS_STRICT # or enhance existing BEDROCK_TOOLS
)Implementation approach:
Update generate_bedrock_schema() in instructor/providers/bedrock/utils.py:19-43 to add strict parameter:
def generate_bedrock_schema(
response_model: type[Any],
strict: bool = False
) -> dict[str, Any]:
"""Generate Bedrock tool schema from a Pydantic model."""
schema = response_model.model_json_schema()
tool_spec = {
"name": response_model.__name__,
"description": response_model.__doc__ or f"Correctly extracted `{response_model.__name__}`",
"inputSchema": {"json": schema},
}
if strict:
tool_spec["strict"] = True
return {"toolSpec": tool_spec}Update handle_bedrock_tools() to use strict mode when appropriate.
Describe alternatives you've considered
-
Do nothing: Continue with prompt-based JSON extraction
- Misses guaranteed schema compliance
- Higher operational costs from retries
- Inconsistent with how Instructor handles native structured outputs for other providers
-
Only add strict tool use, not JSON schema format
- Simpler initial implementation
- But incomplete - doesn't cover all use cases
-
Map to existing generic modes (
Mode.JSON_SCHEMA,Mode.TOOLS_STRICT)- Cleaner, following mode migration strategy
- Consistent with mode migration guide
- Requires ensuring generic modes properly route to Bedrock-specific handlers
Additional context
Official AWS Documentation
Supported Models (as of Feb 2026)
Anthropic Claude:
- Claude Haiku 4.5 (
anthropic.claude-haiku-4-5-20251001-v1:0) - Claude Sonnet 4.5 (
anthropic.claude-sonnet-4-5-20250929-v1:0) - Claude Opus 4.5 (
anthropic.claude-opus-4-5-20251101-v1:0) - Claude Opus 4.6 (
anthropic.claude-opus-4-6-v1)
Open-weight models: Qwen3, OpenAI OSS, DeepSeek V3.1, Gemma 3, MiniMax M2, Mistral variants, Moonshot Kimi K2, NVIDIA Nemotron
API Examples from AWS Docs
Converse API with JSON Schema:
{
"outputConfig": {
"textFormat": {
"type": "json_schema",
"structure": {
"jsonSchema": {
"schema": "{\"type\": \"object\", \"properties\": {...}, \"required\": [...]}",
"name": "data_extraction",
"description": "Extract structured data"
}
}
}
}
}Converse API with Strict Tools:
{
"toolConfig": {
"tools": [{
"toolSpec": {
"name": "get_weather",
"strict": true,
"inputSchema": {
"json": {
"type": "object",
"properties": {...}
}
}
}
}]
}
}Related Code References
Files to modify:
instructor/providers/bedrock/utils.py- Add handlers for structured outputsinstructor/providers/bedrock/client.py- Update mode validationinstructor/mode.py- Add new modes if needed (or map to generic modes)docs/integrations/bedrock.md- Document the new featuretests/llm/test_bedrock/- Add tests for structured outputs
Similar implementations to reference:
- Mistral:
instructor/providers/mistral/utils.py(seehandle_mistral_structured_outputs) - OpenAI:
instructor/providers/openai/utils.py(seehandle_json_modeswithMode.JSON_SCHEMA)
Benefits of Implementation
- Production reliability: Guaranteed schema compliance eliminates parsing errors
- Cost reduction: Fewer retries from validation failures
- Developer experience: Simpler code without custom validation loops
- Consistency: Aligns Bedrock integration with other providers' native structured outputs support
- Future-proof: Leverages AWS's native feature rather than workarounds
Compatibility Notes
From AWS documentation:
- Works with Converse, ConverseStream, InvokeModel, InvokeModelWithResponseStream APIs
- Compatible with cross-region inference and batch inference
- Incompatible with citations for Anthropic models (returns 400 error if both enabled)
- Schema compilation caches for 24 hours (first request may take longer)
Related Issues
- [bedrock] - Bedrock caching broken in v1.13.0 - ValueError with cachePoint dict content #1954 - Bedrock caching broken (cachePoint content validation)
- Allow MD_JSON for bedrock client #2076 - Allow MD_JSON for Bedrock client (Kimi K2 Thinking model)