Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions python/packages/azure-ai/agent_framework_azure_ai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import importlib.metadata

from ._chat_client import AzureAIAgentClient, AzureAISettings
from ._chat_client_v2 import AzureAIAgentClientV2
from ._client import AzureAIClient

try:
__version__ = importlib.metadata.version(__name__)
Expand All @@ -12,7 +12,7 @@

__all__ = [
"AzureAIAgentClient",
"AzureAIAgentClientV2",
"AzureAIClient",
"AzureAISettings",
"__version__",
]
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@
logger = get_logger("agent_framework.azure")


TAzureAIAgentClient = TypeVar("TAzureAIAgentClient", bound="AzureAIAgentClientV2")
TAzureAIClient = TypeVar("TAzureAIClient", bound="AzureAIClient")


@use_function_invocation
@use_observability
@use_chat_middleware
class AzureAIAgentClientV2(OpenAIBaseResponsesClient):
"""Azure AI Agent Chat client."""
class AzureAIClient(OpenAIBaseResponsesClient):
"""Azure AI Agent client."""

OTEL_PROVIDER_NAME: ClassVar[str] = "azure.ai" # type: ignore[reportIncompatibleVariableOverride, misc]

Expand Down Expand Up @@ -121,12 +121,6 @@ def __init__(
"or 'AZURE_AI_PROJECT_ENDPOINT' environment variable."
)

if not azure_ai_settings.model_deployment_name:
raise ServiceInitializationError(
"Azure AI model deployment name is required. Set via 'model_deployment_name' parameter "
"or 'AZURE_AI_MODEL_DEPLOYMENT_NAME' environment variable."
)

# Use provided credential
if not async_credential:
raise ServiceInitializationError("Azure credential is required when project_client is not provided.")
Expand All @@ -139,7 +133,6 @@ def __init__(

# Initialize parent
super().__init__(
model_id=azure_ai_settings.model_deployment_name, # type: ignore
**kwargs,
)

Expand Down

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion python/packages/core/agent_framework/azure/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

_IMPORTS: dict[str, tuple[str, str]] = {
"AzureAIAgentClient": ("agent_framework_azure_ai", "azure-ai"),
"AzureAIAgentClientV2": ("agent_framework_azure_ai", "azure-ai"),
"AzureAIClient": ("agent_framework_azure_ai", "azure-ai"),
"AzureOpenAIAssistantsClient": ("agent_framework.azure._assistants_client", "core"),
"AzureOpenAIChatClient": ("agent_framework.azure._chat_client", "core"),
"AzureAISettings": ("agent_framework_azure_ai", "azure-ai"),
Expand Down
4 changes: 2 additions & 2 deletions python/packages/core/agent_framework/azure/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright (c) Microsoft. All rights reserved.

from agent_framework_azure_ai import AzureAIAgentClient, AzureAIAgentClientV2, AzureAISettings
from agent_framework_azure_ai import AzureAIAgentClient, AzureAIClient, AzureAISettings

from agent_framework.azure._assistants_client import AzureOpenAIAssistantsClient
from agent_framework.azure._chat_client import AzureOpenAIChatClient
Expand All @@ -10,7 +10,7 @@ from agent_framework.azure._shared import AzureOpenAISettings

__all__ = [
"AzureAIAgentClient",
"AzureAIAgentClientV2",
"AzureAIClient",
"AzureAISettings",
"AzureOpenAIAssistantsClient",
"AzureOpenAIChatClient",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,8 @@ async def prepare_options(

# model id
if not run_options.get("model"):
if not self.model_id:
raise ValueError("model_id must be a non-empty string")
run_options["model"] = self.model_id

# messages
Expand Down
10 changes: 5 additions & 5 deletions python/packages/core/agent_framework/openai/_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,18 @@ class OpenAIBase(SerializationMixin):

INJECTABLE: ClassVar[set[str]] = {"client"}

def __init__(self, *, model_id: str, client: AsyncOpenAI | None = None, **kwargs: Any) -> None:
def __init__(self, *, model_id: str | None = None, client: AsyncOpenAI | None = None, **kwargs: Any) -> None:
"""Initialize OpenAIBase.

Keyword Args:
client: The AsyncOpenAI client instance.
model_id: The AI model ID to use (non-empty, whitespace stripped).
model_id: The AI model ID to use.
**kwargs: Additional keyword arguments.
"""
if not model_id or not model_id.strip():
raise ValueError("model_id must be a non-empty string")
self.client = client
self.model_id = model_id.strip()
self.model_id = None
if model_id:
self.model_id = model_id.strip()

# Call super().__init__() to continue MRO chain (e.g., BaseChatClient)
# Extract known kwargs that belong to other base classes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2075,27 +2075,27 @@ def test_create_response_content_image_generation_fallback():
assert f"data:image/png;base64,{unrecognized_base64}" == content.uri


def test_prepare_options_store_parameter_handling() -> None:
async def test_prepare_options_store_parameter_handling() -> None:
client = OpenAIResponsesClient(model_id="test-model", api_key="test-key")
messages = [ChatMessage(role="user", text="Test message")]

test_conversation_id = "test-conversation-123"
chat_options = ChatOptions(store=True, conversation_id=test_conversation_id)
options = client._prepare_options(messages, chat_options) # type: ignore
options = await client.prepare_options(messages, chat_options) # type: ignore
assert options["store"] is True
assert options["previous_response_id"] == test_conversation_id

chat_options = ChatOptions(store=False, conversation_id="")
options = client._prepare_options(messages, chat_options) # type: ignore
options = await client.prepare_options(messages, chat_options) # type: ignore
assert options["store"] is False

chat_options = ChatOptions(store=None, conversation_id=None)
options = client._prepare_options(messages, chat_options) # type: ignore
options = await client.prepare_options(messages, chat_options) # type: ignore
assert options["store"] is False
assert "previous_response_id" not in options

chat_options = ChatOptions()
options = client._prepare_options(messages, chat_options) # type: ignore
options = await client.prepare_options(messages, chat_options) # type: ignore
assert options["store"] is False
assert "previous_response_id" not in options

Expand Down
20 changes: 9 additions & 11 deletions python/samples/getting_started/agents/azure_ai/azure_ai_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
from random import randint
from typing import Annotated

from agent_framework.azure import AzureAIAgentClient
from agent_framework.azure import AzureAIClient
from azure.identity.aio import AzureCliCredential
from pydantic import Field

"""
Azure AI Agent Basic Example

This sample demonstrates basic usage of AzureAIAgentClient to create agents with automatic
lifecycle management. Shows both streaming and non-streaming responses with function tools.
This sample demonstrates basic usage of AzureAIAgentClient.
Shows both streaming and non-streaming responses with function tools.
"""


Expand All @@ -28,14 +28,13 @@ async def non_streaming_example() -> None:
"""Example of non-streaming response (get the complete result at once)."""
print("=== Non-streaming Response Example ===")

# Since no Agent ID is provided, the agent will be automatically created
# and deleted after getting a response
# Since no Agent ID is provided, the agent will be automatically created.
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
async with (
AzureCliCredential() as credential,
AzureAIAgentClient(async_credential=credential).create_agent(
name="WeatherAgent",
AzureAIClient(async_credential=credential).create_agent(
name="BasicWeatherAgent",
instructions="You are a helpful weather agent.",
tools=get_weather,
) as agent,
Expand All @@ -50,14 +49,13 @@ async def streaming_example() -> None:
"""Example of streaming response (get results as they are generated)."""
print("=== Streaming Response Example ===")

# Since no Agent ID is provided, the agent will be automatically created
# and deleted after getting a response
# Since no Agent ID is provided, the agent will be automatically created.
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
async with (
AzureCliCredential() as credential,
AzureAIAgentClient(async_credential=credential).create_agent(
name="WeatherAgent",
AzureAIClient(async_credential=credential).create_agent(
name="BasicWeatherAgent",
instructions="You are a helpful weather agent.",
tools=get_weather,
) as agent,
Expand Down
Loading