Skip to content

Python: feat(bedrock): implement native structured output support via Converse API#6052

Open
karthik-0306 wants to merge 5 commits into
microsoft:mainfrom
karthik-0306:fix-issue-5966
Open

Python: feat(bedrock): implement native structured output support via Converse API#6052
karthik-0306 wants to merge 5 commits into
microsoft:mainfrom
karthik-0306:fix-issue-5966

Conversation

@karthik-0306
Copy link
Copy Markdown

Motivation and Context

BedrockChatClient was the only chat client in MAF without structured output support. It actively blocked the feature by hardcoding response_format: None in BedrockChatOptions, silently discarding any schema passed by the caller regardless of what the user specified.
AWS Bedrock's Converse API added native structured output support via outputConfig.textFormat (GA February 4, 2026), making this workaround unnecessary. Every other MAF provider client — Anthropic, OpenAI, and Gemini — already supports response_format. This PR brings Bedrock to full parity.
Fixes #5966.

Description

Removed the response_format: None override in BedrockChatOptions so the field flows through from the parent ChatOptions naturally.
Added _prepare_output_config() which translates MAF's response_format (either a Pydantic model class or an OpenAI-style dict schema) into the exact wire format the Converse API requires:

json
{
  "outputConfig": {
    "textFormat": {
      "type": "json_schema",
      "structure": {
        "jsonSchema": {
          "name": "MyModel",
          "schema": "{...}",
          "description": "optional"
        }
      }
    }
  }
}

Added _set_additional_properties_false(), a recursive helper that mirrors the identical method in AnthropicChatClient. It walks the full schema tree and sets additionalProperties: false on every object type, as required by AWS for strict schema enforcement. A copy.deepcopy() guards against mutating the caller's original dict schema.
Threaded response_format through _process_converse_response() and _build_response_stream() so MAF's base class machinery handles response parsing and lazily hydrates ChatResponse.value with the validated Pydantic model — no custom JSON parsing logic needed.
Wrapped _invoke_converse() in a try/except that catches botocore.exceptions.ClientError. When AWS returns a ValidationException referencing outputConfig (which happens when a model like Claude 3.x, Nova, or Llama receives the parameter), it is re-raised as a descriptive ValueError naming the model and listing supported alternatives. No silent fallback to unstructured text.
When response_format is not provided, behaviour is identical to before — no outputConfig is sent and no existing functionality is affected.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Approval mode is correctly propagated and enforced in progressive mode
  • Is this a breaking change? No — when response_format is omitted, the request is identical to before. No existing interfaces are modified.

Copilot AI review requested due to automatic review settings May 23, 2026 09:25
@github-actions github-actions Bot changed the title feat(bedrock): implement native structured output support via Converse API Python: feat(bedrock): implement native structured output support via Converse API May 23, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds structured output support for Bedrock Converse by translating response_format into Bedrock’s outputConfig.textFormat=json_schema, and ensures resulting ChatResponse.value is populated (including streaming), with tests covering schema wiring and an unsupported-model error path.

Changes:

  • Implement outputConfig generation from Pydantic models or dict-based JSON schemas and attach it to Converse requests.
  • Plumb response_format through response processing/stream building so ChatResponse.value can be parsed.
  • Add a new pytest suite validating wire shape, strict-schema behavior, streaming parsing, and a ValidationException-to-ValueError mapping.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
python/packages/bedrock/agent_framework_bedrock/_chat_client.py Adds outputConfig(json_schema) request support, strict schema mutation, and a clearer error for unsupported models.
python/packages/bedrock/tests/test_bedrock_structured_output.py Introduces tests for outputConfig shape, schema encoding, recursive strictness, parsing into .value, streaming, and unsupported-model handling.

Comment thread python/packages/bedrock/agent_framework_bedrock/_chat_client.py
Comment thread python/packages/bedrock/agent_framework_bedrock/_chat_client.py Outdated
Comment thread python/packages/bedrock/agent_framework_bedrock/_chat_client.py Outdated
Comment thread python/packages/bedrock/agent_framework_bedrock/_chat_client.py
Comment thread python/packages/bedrock/agent_framework_bedrock/_chat_client.py Outdated
Comment thread python/packages/bedrock/agent_framework_bedrock/_chat_client.py Outdated
@karthik-0306 karthik-0306 requested a review from Copilot May 23, 2026 16:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

Comment thread python/packages/bedrock/agent_framework_bedrock/_chat_client.py
Comment thread python/packages/bedrock/agent_framework_bedrock/_chat_client.py Outdated
Comment thread python/packages/bedrock/agent_framework_bedrock/_chat_client.py
Comment thread python/packages/bedrock/tests/test_bedrock_structured_output.py
Comment thread python/packages/bedrock/tests/test_bedrock_structured_output.py
@karthik-0306 karthik-0306 requested a review from Copilot May 23, 2026 16:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

Comment thread python/packages/bedrock/agent_framework_bedrock/_chat_client.py Outdated
Comment thread python/packages/bedrock/agent_framework_bedrock/_chat_client.py
Comment on lines +334 to +345
# "outputConfig" in error_message catches cases where Bedrock explicitly
# rejects the outputConfig field (unsupported model). Other ValidationExceptions
# (e.g. malformed schema shape, invalid property values) will not mention
# "outputConfig" and will bubble up as raw ClientError without being misdiagnosed.
if error_code == "ValidationException" and (
"outputconfig" in error_message.lower() or "outputconfig" in str(e).lower()
):
raise ValueError(
f"Model '{self.model}' does not support structured output via outputConfig.textFormat. "
"Check the model's Bedrock Converse outputConfig/textFormat support. "
f"AWS error Code: {error_code}. AWS error Message: {error_message}"
) from e
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Checked the existing MAF exception hierarchy — there is no UnsupportedFeature-style exception in the codebase. Two options: use the existing ChatClientInvalidRequestException which semantically fits ("the model rejected this request configuration"), or keep ValueError since it's standard Python for bad argument values and is consistent with how other validation errors are surfaced across MAF. Flagging for human reviewer input before making this call — happy to go either direction.

Comment thread python/packages/bedrock/tests/test_bedrock_structured_output.py
Comment thread python/packages/bedrock/agent_framework_bedrock/_chat_client.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Feature]: Python: BedrockChatClient — support Converse API outputConfig.textFormat for structured output

3 participants