Skip to content

Python: raise clear error for runtime response_format on FoundryAgent (#5467)#5493

Open
GitAashishG wants to merge 5 commits intomicrosoft:mainfrom
GitAashishG:fix/foundry-agent-runtime-response-format-5467
Open

Python: raise clear error for runtime response_format on FoundryAgent (#5467)#5493
GitAashishG wants to merge 5 commits intomicrosoft:mainfrom
GitAashishG:fix/foundry-agent-runtime-response-format-5467

Conversation

@GitAashishG
Copy link
Copy Markdown

@GitAashishG GitAashishG commented Apr 26, 2026

Fixes #5467

Problem

When a user passes response_format= (per-call or via default_options) to a
FoundryAgent, the request fails at the wire with an opaque server error:

openai.BadRequestError: Error code: 400 - {'error': {
  'code': 'invalid_payload',
  'message': "Not allowed when agent is specified."
}}

The Foundry agent endpoint owns response-schema configuration at agent
creation time — so per-call text / response_format options are not a
supported runtime knob for FoundryAgent.

Approach

Per @moonbox3's review, silently stripping the option would be wrong — it
would turn response_format into a client-side parse hint that contradicts
the FoundryAgent design. Instead this PR raises an explicit, actionable
error up-front:

raise ChatClientInvalidRequestException(
    "FoundryAgent does not support per-call 'response_format'. "
    "Foundry agents are created with a fixed response schema. "
    "Either (a) recreate the Foundry agent with the desired "
    "response_format on the server side, or (b) use "
    "FoundryChatClient (without binding to a Foundry agent) "
    "wrapped in Agent for per-call structured output."
)

The guard sits at the top of _RawFoundryAgentChatClient._prepare_options,
so it covers both streaming and non-streaming entry points and also catches
response_format set via Agent.default_options.

Scope

  • Affects only FoundryAgent (bound to a server-side agent)
  • FoundryChatClient is unchanged — per-call response_format continues to
    work there (existing test_response_format_parse_path covers this)
  • No public API surface change; only adds a clearer error path

Testing

  • New unit test test_raw_foundry_agent_chat_client_prepare_options_rejects_runtime_response_format
    covers both the Pydantic BaseModel and dict / json_schema variants
  • Full Foundry suite: 293 passed, 15 skipped
  • ruff check, ruff format --check, pyright — all clean

Files changed

  • python/packages/foundry/agent_framework_foundry/_agent.py — guard +
    import of ChatClientInvalidRequestException
  • python/packages/foundry/tests/foundry/test_foundry_agent.py — new guard
    test

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
Copilot AI review requested due to automatic review settings April 26, 2026 06:01
@moonbox3
Copy link
Copy Markdown
Contributor

moonbox3 commented Apr 26, 2026

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/foundry/agent_framework_foundry
   _agent.py2325476%122, 125, 232–233, 237–239, 244–247, 355, 428–429, 441–442, 454–456, 458–459, 461–467, 469–470, 472, 474, 480–482, 485–494, 498–499, 686–687, 690, 716, 726, 742, 807
TOTAL30505356088% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
6132 30 💤 0 ❌ 0 🔥 1m 38s ⏱️

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

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 text and text_format from RawFoundryAgentChatClient._prepare_options request payload.
  • Extend the existing _prepare_options stripping test to cover text/text_format.
  • Add a new test to ensure runtime response_format variants (Pydantic and dict/json_schema) don’t result in text/text_format being 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.

Comment on lines +360 to +361
# configured to emit JSON matching the requested schema; otherwise
# ``response.value`` will raise ``pydantic.ValidationError`` on access.
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
# 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.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@moonbox3 moonbox3 left a comment

Choose a reason for hiding this comment

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

As I eluded to in the original issue: the preferred direction here is to raise a clear runtime error in _prepare_options when response_format is provided, pointing the caller to either configure it at agent creation or use FoundryChatClient + Agent for per-call response formats.

# dict / ``json_schema`` ``response_format``, the lazy path only parses
# JSON and may raise ``ValueError`` on invalid JSON; it does not
# validate against the schema.
run_options.pop("text", None)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The 400 going away isn't equivalent to runtime response_format being supported: silently stripping it turns the option into a client-side parse hint, which contradicts the FoundryAgent design (settings at creation time).

GitAashishG and others added 2 commits April 27, 2026 18:58
Per maintainer review feedback (microsoft#5493): FoundryAgent is bound to a server-side agent whose response schema is fixed at creation time. Per-call response_format is not a supported runtime option. Replace the previous strip-and-parse approach with an up-front guard in _RawFoundryAgentChatClient._prepare_options that raises ChatClientInvalidRequestException pointing the caller at the two supported paths (recreate the agent server-side, or use FoundryChatClient + Agent for per-call structured output).
@GitAashishG GitAashishG changed the title Python: fix runtime response_format on foundry agent endpoint Python: raise clear error for runtime response_format on FoundryAgent (#5467) Apr 29, 2026
@GitAashishG
Copy link
Copy Markdown
Author

GitAashishG commented Apr 29, 2026

As I eluded to in the original issue: the preferred direction here is to raise a clear runtime error in _prepare_options when response_format is provided, pointing the caller to either configure it at agent creation or use FoundryChatClient + Agent for per-call response formats.


Thanks, that makes sense. Pivoted to the guard approach: _prepare_options now raises ChatClientInvalidRequestException with a message pointing to the two supported paths (recreate the agent server-side, or FoundryChatClient + Agent). Updated tests accordingly. Let me know if the message wording works for you.

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: [Bug]: agent-framework-foundry: Cannot use response_format at runtime (run/options) - raises 400 error

3 participants