Skip to content

Python: FoundryAgent does not forward default_headers to underlying client — isolation headers not sent to agent endpoint #6027

@monuminu

Description

@monuminu

Bug Report

Description

FoundryAgent (and RawFoundryAgent) do not accept or forward a default_headers parameter to the underlying RawFoundryAgentChatClient / _FoundryAgentChatClient. This means custom HTTP headers (e.g. Foundry isolation headers) set on the AIProjectClient via HeadersPolicy are not propagated to the OpenAI client that makes the actual /responses API call to the agent endpoint.

Related Issue

This is related to #5416 — the isolation key header requirement was introduced with Header-based isolation mode, but FoundryAgent has no way to pass those headers through to the Responses API call for Azure AI Foundry Hosted Agents

Steps to Reproduce

  1. Create a Hosted Agent in Foundry with Header isolation mode enabled (isolation_key_source.kind: "Header")
    1. Create a FoundryAgent with a project_client that has HeadersPolicy(base_headers={"x-ms-user-isolation-key": "..."})
    1. Call agent.run(...) with a session
from agent_framework.foundry import FoundryAgent
from azure.ai.projects.aio import AIProjectClient
from azure.core.pipeline.policies import HeadersPolicy

isolation_headers = {
    "x-ms-user-isolation-key": "my-user-id",
    "x-ms-chat-isolation-key": "my-conversation-id",
}

project_client = AIProjectClient(
    endpoint=FOUNDRY_PROJECT_ENDPOINT,
    credential=credential,
    headers_policy=HeadersPolicy(base_headers=isolation_headers),
)

agent = FoundryAgent(
    project_client=project_client,
    agent_name="my-hosted-agent",
    allow_preview=True,
)

session = agent.get_session(session_id)
result = await agent.run("Hello", session=session)  # 400 Bad Request

Expected Behavior

The isolation headers should be forwarded to the Responses API endpoint.

Actual Behavior

HTTP/1.1 400 Bad Request
{
  "error": {
    "code": "bad_request",
    "message": "Agent endpoint requires user isolation key header 'x-ms-user-isolation-key' but it was not present in the request."
  }
}

Root Cause

In RawFoundryAgent.__init__, the client is created without default_headers:

client_kwargs: dict[str, Any] = {
    "project_endpoint": project_endpoint,
    "agent_name": agent_name,
    "agent_version": agent_version,
    "credential": credential,
    "project_client": project_client,
    "allow_preview": allow_preview,
    "env_file_path": env_file_path,
    "env_file_encoding": env_file_encoding,
}
client = actual_client_type(**client_kwargs)

The underlying RawFoundryAgentChatClient.__init__ does accept default_headers and forwards it to both project_client.get_openai_client(default_headers=...) and the parent RawOpenAIChatClient. But RawFoundryAgent / FoundryAgent never thread it through.

Suggested Fix

Add default_headers as an optional parameter to RawFoundryAgent.__init__ and FoundryAgent.__init__, and include it in client_kwargs:

# In RawFoundryAgent.__init__:
client_kwargs: dict[str, Any] = {
    ...
    "default_headers": default_headers,  # Add this
}

Workaround

Use client_type to create a subclass that injects headers:

from agent_framework_foundry._agent import _FoundryAgentChatClient

def _make_header_injecting_client(headers):
    class _Client(_FoundryAgentChatClient):
        def __init__(self, **kwargs):
            merged = dict(headers)
            if kwargs.get("default_headers"):
                merged.update(kwargs["default_headers"])
            kwargs["default_headers"] = merged
            super().__init__(**kwargs)
    return _Client

agent = FoundryAgent(
    project_client=project_client,
    agent_name="my-hosted-agent",
    allow_preview=True,
    client_type=_make_header_injecting_client(isolation_headers),
)

Environment

  • agent-framework version: 1.6.0
    • agent-framework-foundry version: 1.6.0
      • Python: 3.12
        • OS: macOS

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions