Python: [BREAKING] Python: Provider-leading client design & OpenAI package extraction (#4818)

* Python: Provider-leading client design & OpenAI package extraction

Major refactoring of the Python Agent Framework client architecture:

- Extract OpenAI clients into new `agent-framework-openai` package
- Core package no longer depends on openai, azure-identity, azure-ai-projects
- Rename clients for discoverability: OpenAIResponsesClient → OpenAIChatClient,
  OpenAIChatClient → OpenAIChatCompletionClient
- Unify `model_id`/`deployment_name`/`model_deployment_name` → `model` param
- New FoundryChatClient for Azure AI Foundry Responses API
- New FoundryAgent/FoundryAgentClient for connecting to pre-configured Foundry agents
- Remove OpenAIBase/OpenAIConfigMixin from non-deprecated client MRO
- Deprecate AzureOpenAI* clients, AzureAIClient, OpenAIAssistantsClient
- Reorganize samples: azure_openai+azure_ai+azure_ai_agent → azure/
- ADR-0020: Provider-Leading Client Design

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: missing Agent imports in samples, .model_id → .model in foundry_local sample

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: CI failures — mypy errors, coverage targets, sample imports

- azure-ai mypy: add type ignores for TypedDict total=, model arg, forward ref
- Coverage: replace core.azure/openai targets with openai package target
- project_provider: add type annotation for opts dict

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: populate openai .pyi stub, fix broken README links, coverage targets

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fixes

* updated observabilitty

* reset azure init.pyi

* fix errors

* updated adr number

* fix foundry local

* fixed not renamed docstrings and comments, and added deprecated markers to old classes

* fix tests and pyprojects

* fix test vars

* updated function tests

* update durable

* updated test setup for functions

* Fix Foundry auth in workflow samples

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Stabilize Python integration workflows

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update hosting samples for Foundry

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Trigger full CI rerun

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Trigger CI rerun again

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* trigger rerun

* trigger rerun

* fix for litellm

* undo durabletask changes

* Move Foundry APIs into foundry namespace

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix Foundry pyproject formatting

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Split provider samples by Foundry surface

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Restore hosting sample requirements

Also fix the Foundry Local sample link after the provider sample move.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* updated tests

* udpated foundry integration tests

* removed dist from azurefunctions tests

* Use separate Foundry clients for concurrent agents

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix client setup in azfunc and durable

* disabled two tests

* updated setup for some function and durable tests

* improved azure openai setup with new clients

* ignore deprecated

* fixes

* skip 11

* remove openai assistants int tests

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Eduard van Valkenburg
2026-03-25 10:56:29 +01:00
committed by GitHub
Unverified
parent 4b533608b6
commit 5e056b672e
485 changed files with 9784 additions and 12084 deletions
@@ -7,13 +7,13 @@ This agent uses the Responses API which supports:
- Audio inputs
- And other multimodal content
The Chat Completions API (AzureOpenAIChatClient) does NOT support PDF uploads.
The Chat Completions API (FoundryChatClient) does NOT support PDF uploads.
Use this agent when you need to process documents or other file types.
Required environment variables:
- AZURE_OPENAI_ENDPOINT: Your Azure OpenAI endpoint
- AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME: Deployment name for Responses API
(falls back to AZURE_OPENAI_CHAT_DEPLOYMENT_NAME if not set)
- FOUNDRY_MODEL: Deployment name for Responses API
(falls back to FOUNDRY_MODEL if not set)
- AZURE_OPENAI_API_KEY: Your API key (or use Azure CLI auth)
"""
@@ -22,7 +22,7 @@ import os
from typing import Annotated
from agent_framework import Agent, tool
from agent_framework.azure import AzureOpenAIResponsesClient
from agent_framework.foundry import FoundryChatClient
from dotenv import load_dotenv
# Load environment variables from .env file
@@ -32,8 +32,8 @@ logger = logging.getLogger(__name__)
# Get deployment name - try responses-specific env var first, fall back to chat deployment
_deployment_name = os.environ.get(
"AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME",
os.environ.get("AZURE_OPENAI_CHAT_DEPLOYMENT_NAME", ""),
"FOUNDRY_MODEL",
os.environ.get("FOUNDRY_MODEL", ""),
)
# Get endpoint - try responses-specific env var first, fall back to default
@@ -89,8 +89,8 @@ agent = Agent(
For PDFs, you can read and understand the text, tables, and structure.
For images, you can describe what you see and extract any text.
""",
client=AzureOpenAIResponsesClient(
deployment_name=_deployment_name,
client=FoundryChatClient(
model=_deployment_name,
endpoint=_endpoint,
api_version="2025-03-01-preview", # Required for Responses API
),
@@ -117,7 +117,7 @@ def main():
logger.info("")
logger.info("Required environment variables:")
logger.info(" - AZURE_OPENAI_ENDPOINT")
logger.info(" - AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME")
logger.info(" - FOUNDRY_MODEL")
logger.info(" - AZURE_OPENAI_API_KEY (or use Azure CLI auth)")
logger.info("")
@@ -9,7 +9,7 @@ import os
from typing import Annotated
from agent_framework import Agent, tool
from agent_framework.azure import AzureAIAgentClient
from agent_framework.foundry import FoundryChatClient
from azure.identity.aio import AzureCliCredential
from dotenv import load_dotenv
from pydantic import Field
@@ -51,9 +51,9 @@ def get_forecast(
# Agent instance following Agent Framework conventions
agent = Agent(
name="FoundryWeatherAgent",
client=AzureAIAgentClient(
project_endpoint=os.environ.get("AZURE_AI_PROJECT_ENDPOINT"),
model_deployment_name=os.environ.get("FOUNDRY_MODEL_DEPLOYMENT_NAME"),
client=FoundryChatClient(
project_endpoint=os.environ.get("FOUNDRY_PROJECT_ENDPOINT"),
model_model=os.environ.get("FOUNDRY_MODEL_DEPLOYMENT_NAME"),
credential=AzureCliCredential(),
),
instructions="""
@@ -18,8 +18,8 @@ from agent_framework import (
handler,
tool,
)
from agent_framework.azure import AzureOpenAIChatClient
from agent_framework.devui import serve
from agent_framework.foundry import FoundryChatClient
from dotenv import load_dotenv
from typing_extensions import Never
@@ -79,9 +79,9 @@ def main():
logger = logging.getLogger(__name__)
# Create Azure OpenAI chat client
client = AzureOpenAIChatClient(
client = FoundryChatClient(
api_key=os.environ.get("AZURE_OPENAI_API_KEY"),
deployment_name=os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT_NAME"],
model=os.environ["FOUNDRY_MODEL"],
endpoint=os.environ.get("AZURE_OPENAI_ENDPOINT"),
api_version=os.environ.get("AZURE_OPENAI_API_VERSION", "2024-10-21"),
)
@@ -20,7 +20,7 @@ from agent_framework import (
function_middleware,
tool,
)
from agent_framework.azure import AzureOpenAIChatClient
from agent_framework.foundry import FoundryChatClient
from agent_framework_devui import register_cleanup
from dotenv import load_dotenv
@@ -152,7 +152,7 @@ agent = Agent(
and forecasts for any location. Always be helpful and provide detailed
weather information when asked.
""",
client=AzureOpenAIChatClient(
client=FoundryChatClient(
api_key=os.environ.get("AZURE_OPENAI_API_KEY", ""),
),
tools=[get_weather, get_forecast, send_email],
@@ -17,8 +17,8 @@ Both paths converge at Summarizer for final report.
import os
from typing import Any
from agent_framework import AgentExecutorResponse, WorkflowBuilder
from agent_framework.azure import AzureOpenAIChatClient
from agent_framework import Agent, AgentExecutorResponse, WorkflowBuilder
from agent_framework.foundry import FoundryChatClient
from dotenv import load_dotenv
from pydantic import BaseModel
@@ -63,10 +63,11 @@ def is_approved(message: Any) -> bool:
# Create Azure OpenAI chat client
client = AzureOpenAIChatClient(api_key=os.environ.get("AZURE_OPENAI_API_KEY", ""))
client = FoundryChatClient(api_key=os.environ.get("AZURE_OPENAI_API_KEY", ""))
# Create Writer agent - generates content
writer = client.as_agent(
writer = Agent(
client=client,
name="Writer",
instructions=(
"You are an excellent content writer. "
@@ -76,7 +77,8 @@ writer = client.as_agent(
)
# Create Reviewer agent - evaluates and provides structured feedback
reviewer = client.as_agent(
reviewer = Agent(
client=client,
name="Reviewer",
instructions=(
"You are an expert content reviewer. "
@@ -94,7 +96,8 @@ reviewer = client.as_agent(
)
# Create Editor agent - improves content based on feedback
editor = client.as_agent(
editor = Agent(
client=client,
name="Editor",
instructions=(
"You are a skilled editor. "
@@ -105,7 +108,8 @@ editor = client.as_agent(
)
# Create Publisher agent - formats content for publication
publisher = client.as_agent(
publisher = Agent(
client=client,
name="Publisher",
instructions=(
"You are a publishing agent. "
@@ -115,7 +119,8 @@ publisher = client.as_agent(
)
# Create Summarizer agent - creates final publication report
summarizer = client.as_agent(
summarizer = Agent(
client=client,
name="Summarizer",
instructions=(
"You are a summarizer agent. "