Skip to content

Python: [Bug]: FoundryAgent inherits unrelated OPENAI_CHAT_MODEL for agent-reference requests #7272

Description

Description

FoundryAgent incorrectly inherits OPENAI_CHAT_MODEL from the process environment even though the target Prompt Agent or Hosted Agent already owns its model through agent_reference.

This can cause an unrelated OpenAI deployment name to be copied into FoundryAgent.default_options and sent alongside the Foundry agent reference. Foundry then rejects the request when that value differs from the persisted agent definition's model.

Observed with a Prompt Agent configured for gpt-5.4 and a development .env containing OPENAI_CHAT_MODEL=gpt-4.1:

FOUNDRY_MODEL='gpt-5.4'
RawFoundryAgentChatClient.model='gpt-4.1'
FoundryAgent.client.model='gpt-4.1'
FoundryAgent.default_options.model='gpt-4.1'

The value flows through these steps:

  1. RawFoundryAgentChatClient obtains an OpenAI-compatible client from AIProjectClient.
  2. Its RawOpenAIChatClient base resolves OPENAI_CHAT_MODEL even though no model is required for an agent-reference request.
  3. Agent.__init__ copies client.model into default_options.
  4. RawFoundryAgentChatClient._prepare_options sees options["model"] as populated and therefore does not strip it.
  5. Foundry compares the unrelated model with the persisted agent model and rejects the request.

Expected behavior: generic OPENAI_* and AZURE_OPENAI_* model environment variables must not implicitly configure RawFoundryAgentChatClient/FoundryAgent. The persisted Foundry agent definition should resolve the model. If explicitly supplying a matching model remains supported, it should be distinguishable from an environment-derived value.

This was discovered while independently validating the stateless reasoning replay work from #7233; it prevents the request from reaching that workflow logic and is a separate defect.

Code Sample

import asyncio
import os

from agent_framework.foundry import FoundryAgent
from azure.identity.aio import AzureCliCredential


async def main() -> None:
    # The existing Prompt Agent named below is configured with gpt-5.4.
    os.environ["OPENAI_CHAT_MODEL"] = "gpt-4.1"

    async with (
        AzureCliCredential() as credential,
        FoundryAgent(
            project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
            agent_name="existing-gpt-5.4-prompt-agent",
            agent_version="1",
            credential=credential,
        ) as agent,
    ):
        print(f"client model: {agent.client.model!r}")
        print(f"request model: {agent.default_options.get('model')!r}")
        await agent.run("Respond with exactly: ok")


asyncio.run(main())

The local contamination can also be demonstrated without a service call by supplying a mocked project client's OpenAI client and inspecting RawFoundryAgentChatClient.model and FoundryAgent.default_options.

Error Messages / Stack Traces

Error code: 400
{
  "error": {
    "code": "invalid_payload",
    "message": "Invalid payload",
    "type": "invalid_request_error",
    "details": [
      {
        "code": "ValidationError",
        "message": "Model must match the agent's model 'gpt-5.4' when agent is specified.",
        "param": "model",
        "type": "error"
      }
    ]
  }
}

Package Versions

Latest main source at 2d34deeb8269ebaa2c27332e1bbf80726fa48b32 with local environment metadata: agent-framework-core==1.11.0, agent-framework-foundry==1.10.1, azure-ai-projects==2.2.0, openai==2.45.0.

Python Version

Python 3.13.5

Additional Context

Suggested regression coverage:

  • Set OPENAI_CHAT_MODEL to a value different from the persisted Foundry agent model.
  • Assert RawFoundryAgentChatClient.model does not inherit it.
  • Assert FoundryAgent.default_options does not contain the inherited model.
  • Assert an agent-reference request omits an environment-derived model.
  • Preserve intentional behavior for an explicitly supplied matching model, if that override is supported.

Metadata

Metadata

Labels

pythonUsage: [Issues, PRs], Target: Python

Type

No type

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions