Skip to content

Python: [Bug]: Non-streaming FoundryChatClient / FoundryAgent drop oauth_consent_request output items (empty answer, no consent link) #8975

Closed

Description

Description

When a Foundry tool (toolbox / MCP connection) needs the user's OAuth consent, the service returns an oauth_consent_request output item with a consent_link and marks the response incomplete.

The streaming path surfaces it: try_parse_oauth_consent_event (added for #3950) turns response.output_item.added / response.oauth_consent_requested into Content.from_oauth_consent_request(...).

The non-streaming path does not. RawFoundryChatClient._parse_response_from_openai and RawFoundryAgentChatClient._parse_response_from_openai only post-process reasoning items / agent_session_id, and the base RawOpenAIChatClient._parse_response_from_openai hits case _: logger.debug("Unparsed output of type ...") for the consent item. agent.run() (non-streaming is the default) therefore returns an empty assistant message, finish_reason=None, no exception, and the consent link is lost. The caller cannot tell the user to sign in.

  • Expected: the response contains an oauth_consent_request content with the consent_link, same as with stream=True.
  • Actual: the response has no content at all.

Code Sample

Self-contained repro (no Azure resources; the HTTP layer is mocked, the real OpenAI SDK parses the payload):

import asyncio, importlib
from unittest.mock import MagicMock
from openai import AsyncOpenAI, DefaultAsyncHttpxClient
from agent_framework_foundry import FoundryAgent

# httpx (openai 2.x) or httpx2 (openai 3.x), whichever the installed SDK uses
httpx = importlib.import_module(DefaultAsyncHttpxClient.__mro__[1].__module__.partition(".")[0])

def handler(request):
    return httpx.Response(200, json={
        "id": "resp_1", "object": "response", "created_at": 0, "model": "gpt-5.4",
        "status": "incomplete",
        "output": [{
            "type": "oauth_consent_request", "id": "oauth-item-1",
            "consent_link": "https://consent-host.example.com/login?data=abc123",
            "server_label": "github",
        }],
    })

async def main():
    oai = AsyncOpenAI(api_key="x", http_client=DefaultAsyncHttpxClient(transport=httpx.MockTransport(handler)))
    project = MagicMock()
    project.get_openai_client.return_value = oai
    agent = FoundryAgent(project_client=project, agent_name="toolbox-agent")
    response = await agent.run("List my repos")
    print([c.type for m in response.messages for c in m.contents])  # [] -> consent link lost

asyncio.run(main())

Same result with FoundryChatClient(...).get_response(...). With stream=True the consent content is returned.

Root cause

  • python/packages/foundry/agent_framework_foundry/_chat_client.py:338 (RawFoundryChatClient._parse_response_from_openai) and python/packages/foundry/agent_framework_foundry/_agent.py:423 (RawFoundryAgentChatClient._parse_response_from_openai) never look for oauth_consent_request items; only the streaming overrides (:367 / :434) call try_parse_oauth_consent_event.
  • The item then falls through to python/packages/openai/agent_framework_openai/_chat_client.py:3543 (logger.debug("Unparsed output of type ...")).

Proposed fix

Add a small helper in _oauth_helpers.py that converts oauth_consent_request items of a completed response's output into Content.from_oauth_consent_request (same HTTPS validation as the streaming path), and append the result to the message in both non-streaming overrides. PR with regression tests for both clients is ready.

Code Sample

Error Messages / Stack Traces

Package Versions

agent-framework-foundry: 1.14.0, agent-framework-openai: 1.15.0, agent-framework-core: 1.20.0 (main @ e9857bd)

Python Version

Python 3.12

Additional Context

Related: #3950 (streaming events silently dropped). That fix covers the streaming path only.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 2, 2026
  2. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    on Oct 2, 2026
  3. github-actions commented on Oct 2, 2026

    @github-actions
    Contributor

    🤖 Automated triage reproduction notes (agent-authored — trust but verify)

    Agent analysis

    The bug occurs in python/packages/foundry/agent_framework_foundry/_chat_client.py::RawFoundryChatClient._parse_response_from_openai and _agent.py::RawFoundryAgentChatClient._parse_response_from_openai when a non-streaming response contains an oauth_consent_request output item. Minimal repro: mock an OpenAI Responses API payload containing that item, then call FoundryChatClient.get_response() or FoundryAgent.run() and assert that the returned message contains OAuth consent content; both currently return none.

    • Failing test: python/packages/foundry/tests/foundry/test_foundry_chat_client.py::test_get_response_non_streaming_surfaces_oauth_consent_request
    • Files examined: python/packages/foundry/agent_framework_foundry/_chat_client.py, python/packages/foundry/agent_framework_foundry/_agent.py, python/packages/foundry/agent_framework_foundry/_oauth_helpers.py, python/packages/openai/agent_framework_openai/_chat_client.py, python/packages/foundry/tests/foundry/test_foundry_chat_client.py, python/packages/foundry/tests/foundry/test_foundry_agent.py, python/packages/foundry/tests/foundry/test_oauth_helpers.py, python/packages/foundry/pyproject.toml
    • Tests run: test_get_response_non_streaming_surfaces_oauth_consent_request, test_run_non_streaming_surfaces_oauth_consent_request, test_parse_chunk_surfaces_oauth_consent_request for FoundryChatClient, test_parse_chunk_surfaces_oauth_consent_request for FoundryAgent
    • Reported version: 1.14.0
    • Current version: 1.14.0
  4. added
    agentsUsage: [Issues, PRs], Target: Single agent
    foundryUsage: [Issues, PRs], Target: all Foundry integrations
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

agentsUsage: [Issues, PRs], Target: Single agentfoundryUsage: [Issues, PRs], Target: all Foundry integrationspythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions