* renamed AzureAIINferenceEmbeddings and lazy load azure-cosmos and env var rename * updated coverage * fix readme
7.1 KiB
status, contact, date, deciders, consulted
| status | contact | date | deciders | consulted |
|---|---|---|---|---|
| accepted | eavanvalkenburg | 2026-03-20 | eavanvalkenburg, sphenry, chetantoshnival | taochenosu, moonbox3, dmytrostruk, giles17, alliscode |
Provider-Leading Client Design & OpenAI Package Extraction
Context and Problem Statement
The agent-framework-core package currently bundles OpenAI and Azure OpenAI client implementations along with their dependencies (openai, azure-identity, azure-ai-projects, packaging). This makes core heavier than necessary for users who don't use OpenAI, and it conflates the core abstractions with a specific provider implementation. Additionally, the current class naming (OpenAIResponsesClient, OpenAIChatClient) is based on the underlying OpenAI API names rather than what users actually want to do, making discoverability harder for newcomers.
Decision Drivers
- Lightweight core: Core should only contain abstractions, middleware infrastructure, and telemetry — no provider-specific code or dependencies.
- Discoverability-first: Import namespaces should guide users to the right client.
from agent_framework.openai import ...should surface all OpenAI-related clients;from agent_framework.azure import ...should surface Foundry, Azure AI, and other Azure-specific classes. - Provider-leading naming: The primary client name should reflect the provider, not the underlying API. The Responses API is now the recommended default for OpenAI, so its client should be called
OpenAIChatClient(notOpenAIResponsesClient). - Clean separation of concerns: Azure-specific deprecated wrappers belong in the azure-ai package, not in the OpenAI package.
Considered Options
- Keep OpenAI in core: Simpler but keeps core heavy; doesn't help discoverability.
- Extract OpenAI with Azure wrappers in the OpenAI package: Keeps Azure OpenAI wrappers alongside OpenAI code, but pollutes the OpenAI package with Azure concerns.
- Extract OpenAI, place Azure wrappers in azure-ai: Clean separation; the OpenAI package has zero Azure dependencies; deprecated Azure wrappers live in a single file in azure-ai for easy future deletion.
Decision Outcome
Chosen option: "Extract OpenAI, place Azure wrappers in azure-ai", because it achieves the lightest core, cleanest OpenAI package, and the most maintainable deprecation path.
Key changes:
- New
agent-framework-openaipackage with dependencies onagent-framework-core,openai, andpackagingonly. - Class renames:
OpenAIResponsesClient→OpenAIChatClient(Responses API),OpenAIChatClient→OpenAIChatCompletionClient(Chat Completions API). Old names remain as deprecated aliases. - Deprecated classes:
OpenAIAssistantsClient, allAzureOpenAI*Clientclasses,AzureAIClient,AzureAIAgentClient, andAzureAIProjectAgentProviderare marked deprecated. - New
FoundryChatClientin azure-ai for Azure AI Foundry Responses API access, built onRawFoundryChatClient(RawOpenAIChatClient). - All deprecated
AzureOpenAI*classes consolidated into a single file (_deprecated_azure_openai.py) in the azure-ai package for clean future deletion. - Core's
agent_framework.openaiandagent_framework.azurenamespaces become lazy-loading gateways, preserving backward-compatible import paths while removing hard dependencies. - Unified
modelparameter replacesmodel_id(OpenAI),deployment_name(Azure OpenAI), andmodel_deployment_name(Azure AI) across all client constructors. The termmodelis intentionally generic: it naturally maps to an OpenAI model name and to an Azure OpenAI deployment name, making it straightforward to useOpenAIChatClientwith either OpenAI or Azure OpenAI backends (viaAsyncAzureOpenAI). Environment variables are similarly unified (e.g.,OPENAI_MODELinstead of separateOPENAI_CHAT_MODEL_ID/OPENAI_CHAT_COMPLETION_MODEL_ID). FoundryAgentreplaces the pattern ofAgent(client=AzureAIClient(...))for connecting to pre-configured agents in Azure AI Foundry (PromptAgents and HostedAgents). The underlyingRawFoundryAgentChatClientis an implementation detail — most users interact only withFoundryAgent.AzureAIAgentClientis separately deprecated as it refers to the V1 Agents Service API. See below for design rationale.
Foundry Agent Design: FoundryAgentClient vs FoundryAgent
The existing AzureAIClient combines two concerns: CRUD lifecycle management (creating/deleting agents on the service) and runtime communication (sending messages via the Responses API). The new design removes CRUD entirely — users connect to agents that already exist in Foundry.
Two approaches were considered:
Option A — FoundryAgentClient only (public ChatClient):
Users compose Agent(client=FoundryAgentClient(...), tools=[...]). This follows the universal Agent(client=X) pattern used by every other provider. However, a "client" that wraps a named remote agent (with agent_name as a constructor param) is semantically odd — clients typically wrap a model endpoint, not a specific agent.
Option B — FoundryAgent (Agent subclass) + private _FoundryAgentChatClient and public RawFoundryAgentChatClient:
Users write FoundryAgent(agent_name="my-agent", ...) for the common case. Internally, FoundryAgent creates a _FoundryAgentChatClient and passes it to the standard Agent base class. For advanced customization, users pass client_type=RawFoundryAgentChatClient (or a custom subclass) to control the client middleware layers. The Agent(client=RawFoundryAgentChatClient(...)) composition pattern still works for users who prefer it.
Chosen option: Option B, because:
- The common case (
FoundryAgent(...)) is a single object with no boilerplate. client_type=gives full control over client middleware without parameter duplication — the agent forwards connection params to the client internally.RawFoundryAgent(RawAgent)andFoundryAgent(Agent)mirror the establishedRawAgent/Agentpattern.- Runtime validation (only
FunctionToolallowed) lives inRawFoundryAgentChatClient._prepare_options, ensuring it applies regardless of how the client is used — throughFoundryAgent,Agent(client=...), or any custom composition.
Public classes:
RawFoundryAgentChatClient(RawOpenAIChatClient)— Responses API client that injects agent reference and validates tools. Extension point for custom client middleware.RawFoundryAgent(RawAgent)— Agent without agent-level middleware/telemetry.FoundryAgent(AgentTelemetryLayer, AgentMiddlewareLayer, RawFoundryAgent)— Recommended production agent.
Internal (private):
_FoundryAgentChatClient— Full client with function invocation, chat middleware, and telemetry layers. Created automatically byFoundryAgent; users customize viaclient_type=RawFoundryAgentChatClientor a custom subclass.
Deprecated:
AzureAIClient— replaced byFoundryAgent(which usesFoundryAgentClientinternally).AzureAIAgentClient— refers to V1 Agents Service API, no direct replacement.AzureAIProjectAgentProvider— replaced byFoundryAgent.