Python: fix runtime response_format on foundry agent endpoint#5493
Python: fix runtime response_format on foundry agent endpoint#5493GitAashishG wants to merge 2 commits intomicrosoft:mainfrom
Conversation
The Foundry agent endpoint rejects per-call `text` configuration when an agent is bound (400 invalid_payload, "Not allowed when agent is specified."). Strip `text` and `text_format` from the request body in `_RawFoundryAgentChatClient._prepare_options` so the user-supplied `response_format` is honored client-side via ChatResponse's lazy structured-value parsing instead of failing the request. Fixes microsoft#5467
Python Test Coverage Report •
Python Unit Test Overview
|
||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Pull request overview
This PR fixes a regression in agent-framework-foundry where providing response_format at runtime caused Foundry agent endpoint requests to fail with 400 invalid_payload due to disallowed per-call text configuration. The fix removes text and text_format from the outgoing request payload in the Foundry agent chat client so structured output is handled client-side via ChatResponse’s lazy parsing instead of being sent to the service.
Changes:
- Strip
textandtext_formatfromRawFoundryAgentChatClient._prepare_optionsrequest payload. - Extend the existing
_prepare_optionsstripping test to covertext/text_format. - Add a new test to ensure runtime
response_formatvariants (Pydantic and dict/json_schema) don’t result intext/text_formatbeing sent.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| python/packages/foundry/agent_framework_foundry/_agent.py | Drops text/text_format from prepared run options to avoid Foundry agent endpoint rejection and rely on client-side structured parsing. |
| python/packages/foundry/tests/foundry/test_foundry_agent.py | Adds/extends unit tests to assert text/text_format are stripped, including runtime response_format scenarios. |
| # configured to emit JSON matching the requested schema; otherwise | ||
| # ``response.value`` will raise ``pydantic.ValidationError`` on access. |
There was a problem hiding this comment.
The explanatory comment implies that when the bound agent output doesn’t match the runtime schema, accessing response.value will raise pydantic.ValidationError. That’s only true for Pydantic response_format; for the dict/json_schema variant the lazy parsing path only does json.loads(...) and will raise ValueError on invalid JSON (and does not validate against the schema). Consider adjusting the comment to reflect both behaviors to avoid confusing users.
| # configured to emit JSON matching the requested schema; otherwise | |
| # ``response.value`` will raise ``pydantic.ValidationError`` on access. | |
| # configured to emit JSON compatible with the requested format; for a | |
| # Pydantic ``response_format``, accessing ``response.value`` may raise | |
| # ``pydantic.ValidationError`` if validation fails, while for a dict/ | |
| # ``json_schema`` format the lazy path only parses JSON and may raise | |
| # ``ValueError`` for invalid JSON without validating against the schema. |
The Foundry agent endpoint rejects per-call
textconfiguration when an agent is bound (400 invalid_payload, "Not allowed when agent is specified."). Striptextandtext_formatfrom the request body in_RawFoundryAgentChatClient._prepare_optionsso the user-suppliedresponse_formatis honored client-side via ChatResponse's lazy structured-value parsing instead of failing the request.Fixes #5467
Motivation and Context
When using
agent-framework-foundry, passingresponse_formatat runtime (agent.run(..., options={"response_format": MyModel})) fails with:400 invalid_payload, "Not allowed when agent is specified.", param: text
The Foundry agent endpoint rejects per-call
textconfiguration when an agent is bound. The legacyazure-aipackage handled this by droppingresponse_formatfrom the request payload (#3230), but the equivalent strip is missing inagent-framework-foundry, so callers who migrated regressed.Description
In
_RawFoundryAgentChatClient._prepare_options, also poptextandtext_formatfromrun_options(in addition to the existingmodel/tools/tool_choice/parallel_tool_callsstrips).The user-supplied
response_formatstill flows throughvalidated_options, soOpenAIResponsesChatClient._parse_response_from_openaisetsChatResponse.response_format = MyModel. The lazy validation path in_parse_structured_response_value(added in #3274 for #3268) then surfaces a realpydantic.ValidationErrorif the agent's output does not match the runtime schema.Net effect:
response.valueis a validated instance (or a clearValidationErroron access).response.valueis a parseddict.response.valuewill raise on access. This matches the priorazure-aibehavior expectations.Tests:
test_raw_foundry_agent_chat_client_prepare_options_strips_client_side_fieldsto asserttextandtext_formatare stripped.test_raw_foundry_agent_chat_client_prepare_options_strips_text_for_runtime_response_formatcovering the Pydantic and dict json_schema variants.Contribution Checklist