Skip to content

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

Closed

Description

Description

BedrockChatClient hard-codes response_format: None in BedrockChatOptions, which blocks structured output entirely. The Converse API now supports outputConfig.textFormat with a jsonSchema type for API-enforced structured output (GA since February 2026, works with Converse, ConverseStream, InvokeModel, and InvokeModelWithResponseStream). The Anthropic, Gemini, and OpenAI clients in MAF all support response_format already. Bedrock is the odd one out.

What needs to change

1. Remove the response_format: None override so ChatOptions.response_format can flow through naturally.

2. Add a _prepare_output_config() helper that converts Pydantic models or dict schemas into the Bedrock wire format:

def _prepare_output_config(self, response_format):
    if response_format is None:
        return None

    if isinstance(response_format, dict):
        schema = response_format.get("json_schema", {}).get("schema", response_format)
        name = response_format.get("json_schema", {}).get("name", "output_schema")
    else:
        schema = response_format.model_json_schema()
        name = response_format.__name__

    self._set_additional_properties_false(schema)

    return {
        "textFormat": {
            "type": "jsonSchema",
            "jsonSchema": {
                "name": name,
                "schema": json.dumps(schema),  # Bedrock wants a JSON string, not a dict
            },
        }
    }

The recursive _set_additional_properties_false helper mirrors what AnthropicChatClient._prepare_response_format() does (lines 659-693).

3. Wire it into _prepare_options() after the toolConfig block:

if output_config := self._prepare_output_config(options.get("response_format")):
    run_options["outputConfig"] = output_config

4. Populate ChatResponse.value by passing response_format through to _build_response, same as the Anthropic client does.

Compatibility notes

  • When response_format is omitted, nothing changes. No outputConfig gets sent.
  • Models that don't support outputConfig.textFormat will return a ValidationException from Bedrock. Surface that clearly rather than silently falling back to unstructured text.
  • Agent.run(response_format=...) might need a separate follow-up to pass the option down to the client layer.

Acceptance criteria

  • outputConfig.textFormat.jsonSchema.schema is serialized as a JSON string (not a dict)
  • additionalProperties: false is set recursively on all object schemas
  • No outputConfig in the request when response_format is not provided
  • Clear error when a model doesn't support it (no silent downgrade)
  • ChatResponse.value is populated with a parsed Pydantic model
  • Unit tests covering request shape, string serialization, and the no-op path

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on May 20, 2026
  2. changed the title [-][Feature]: Python: BedrockChatClient — support Converse API outputConfig.textFormat for structured output[/-] [+][Feature]: Python: BedrockChatClient support Converse API outputConfig.textFormat for structured output[/+] on May 20, 2026
  3. changed the title [-][Feature]: Python: BedrockChatClient support Converse API outputConfig.textFormat for structured output[/-] [+]Python: [Feature]: Python: BedrockChatClient — support Converse API outputConfig.textFormat for structured output[/+] on May 20, 2026
  4. removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on May 21, 2026
  5. karthik-0306 commented on May 23, 2026

    @karthik-0306
    Contributor

    I've now verified the correct wire format against the AWS CLI reference and the Feb 4, 2026 Bedrock API changelog.

    The issue description's proposed _prepare_output_config() has two problems in the generated shape:

    1. Missing structure wrapper — the correct nesting is textFormat -> structure -> jsonSchema, not textFormat -> jsonSchema.

    2. Wrong type string — the correct value is "json_schema" (underscore), not "jsonSchema" (camelCase).

    The correct wire format is:

    {
      "outputConfig": {
        "textFormat": {
          "type": "json_schema",
          "structure": {
            "jsonSchema": {
              "name": "output_schema",
              "schema": "{...}"
            }
          }
        }
      }
    }

    My implementation plan accounts for both of these. I'll follow the 4-step approach:

    1. Remove the response_format: None override
    2. Generate _prepare_output_config() with the correct structure
    3. Wire it into _prepare_options()
    4. Populate ChatResponse.value in _build_response()

    I’ll also add unit tests covering:

    • correct wire shape
    • JSON string serialization
    • no-op path behavior

    Happy to open a draft PR shortly.

  6. added a commit that references this issue on Jun 1, 2026
    5d98bed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

pythonUsage: [Issues, PRs], Target: Python

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions