Python: add(azure-ai): support reasoning config for AzureAIClient (#3403)

* add(azure-ai): support reasoning config for AzureAIClient

* Update sample

* Merge main

* improvements

* improve sample
This commit is contained in:
Evan Mattson
2026-01-23 18:37:23 +09:00
committed by GitHub
Unverified
parent a97bc322ac
commit 7b8777d1fc
5 changed files with 152 additions and 7 deletions
@@ -22,12 +22,7 @@ from agent_framework.observability import use_instrumentation
from agent_framework.openai import OpenAIResponsesOptions
from agent_framework.openai._responses_client import OpenAIBaseResponsesClient
from azure.ai.projects.aio import AIProjectClient
from azure.ai.projects.models import (
MCPTool,
PromptAgentDefinition,
PromptAgentDefinitionText,
RaiConfig,
)
from azure.ai.projects.models import MCPTool, PromptAgentDefinition, PromptAgentDefinitionText, RaiConfig, Reasoning
from azure.core.credentials_async import AsyncTokenCredential
from azure.core.exceptions import ResourceNotFoundError
from pydantic import ValidationError
@@ -51,12 +46,15 @@ else:
logger = get_logger("agent_framework.azure")
class AzureAIProjectAgentOptions(OpenAIResponsesOptions):
class AzureAIProjectAgentOptions(OpenAIResponsesOptions, total=False):
"""Azure AI Project Agent options."""
rai_config: RaiConfig
"""Configuration for Responsible AI (RAI) content filtering and safety features."""
reasoning: Reasoning # type: ignore[misc]
"""Configuration for enabling reasoning capabilities (requires azure.ai.projects.models.Reasoning)."""
TAzureAIClientOptions = TypeVar(
"TAzureAIClientOptions",
@@ -343,6 +341,10 @@ class AzureAIClient(OpenAIBaseResponsesClient[TAzureAIClientOptions], Generic[TA
args["temperature"] = run_options["temperature"]
if "top_p" in run_options:
args["top_p"] = run_options["top_p"]
if "reasoning" in run_options:
args["reasoning"] = run_options["reasoning"]
if "rai_config" in run_options:
args["rai_config"] = run_options["rai_config"]
# response_format is accessed from chat_options or additional_properties
# since the base class excludes it from run_options
@@ -408,6 +410,7 @@ class AzureAIClient(OpenAIBaseResponsesClient[TAzureAIClientOptions], Generic[TA
"top_p",
"text",
"text_format",
"reasoning",
]
for property in exclude:
@@ -195,6 +195,7 @@ class AzureAIProjectAgentProvider(Generic[TOptions_co]):
opts = dict(default_options) if default_options else {}
response_format = opts.get("response_format")
rai_config = opts.get("rai_config")
reasoning = opts.get("reasoning")
args: dict[str, Any] = {"model": resolved_model}
@@ -206,6 +207,8 @@ class AzureAIProjectAgentProvider(Generic[TOptions_co]):
)
if rai_config:
args["rai_config"] = rai_config
if reasoning:
args["reasoning"] = reasoning
# Normalize tools and separate MCP tools from other tools
normalized_tools = normalize_tools(tools)
@@ -251,6 +251,50 @@ async def test_provider_create_agent_with_rai_config(
assert definition.rai_config is mock_rai_config
async def test_provider_create_agent_with_reasoning(
mock_project_client: MagicMock,
azure_ai_unit_test_env: dict[str, str],
) -> None:
"""Test AzureAIProjectAgentProvider.create_agent passes reasoning from default_options."""
with patch("agent_framework_azure_ai._project_provider.AzureAISettings") as mock_settings:
mock_settings.return_value.project_endpoint = azure_ai_unit_test_env["AZURE_AI_PROJECT_ENDPOINT"]
mock_settings.return_value.model_deployment_name = azure_ai_unit_test_env["AZURE_AI_MODEL_DEPLOYMENT_NAME"]
provider = AzureAIProjectAgentProvider(project_client=mock_project_client)
# Mock agent creation response
mock_agent_version = MagicMock(spec=AgentVersionDetails)
mock_agent_version.id = "agent-id"
mock_agent_version.name = "test-agent"
mock_agent_version.version = "1.0"
mock_agent_version.description = None
mock_agent_version.definition = MagicMock(spec=PromptAgentDefinition)
mock_agent_version.definition.model = "gpt-5.2"
mock_agent_version.definition.instructions = None
mock_agent_version.definition.temperature = None
mock_agent_version.definition.top_p = None
mock_agent_version.definition.tools = []
mock_project_client.agents.create_version = AsyncMock(return_value=mock_agent_version)
# Create a mock Reasoning-like object
mock_reasoning = MagicMock()
mock_reasoning.effort = "medium"
mock_reasoning.summary = "concise"
# Call create_agent with reasoning in default_options
await provider.create_agent(
name="test-agent",
model="gpt-5.2",
default_options={"reasoning": mock_reasoning},
)
# Verify reasoning was passed to PromptAgentDefinition
call_args = mock_project_client.agents.create_version.call_args
definition = call_args[1]["definition"]
assert definition.reasoning is mock_reasoning
async def test_provider_get_agent_with_name(mock_project_client: MagicMock) -> None:
"""Test AzureAIProjectAgentProvider.get_agent with name parameter."""
provider = AzureAIProjectAgentProvider(project_client=mock_project_client)