From 80ccd206e104a934ca34e7294cd8445da842149a Mon Sep 17 00:00:00 2001 From: eavanvalkenburg Date: Fri, 9 Jan 2026 09:50:31 +0100 Subject: [PATCH 1/4] fix Python: kwargs are not passed to _prepare_thread_and_messages in ChatAgent.run Fixes #3118 --- python/packages/core/agent_framework/_agents.py | 2 +- python/packages/core/agent_framework/_tools.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/python/packages/core/agent_framework/_agents.py b/python/packages/core/agent_framework/_agents.py index aadd1be40a..f260b1a6d3 100644 --- a/python/packages/core/agent_framework/_agents.py +++ b/python/packages/core/agent_framework/_agents.py @@ -834,7 +834,7 @@ async def run( """ input_messages = self._normalize_messages(messages) thread, run_chat_options, thread_messages = await self._prepare_thread_and_messages( - thread=thread, input_messages=input_messages + thread=thread, input_messages=input_messages, **kwargs ) normalized_tools: list[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] = ( # type:ignore[reportUnknownVariableType] [] if tools is None else tools if isinstance(tools, list) else [tools] diff --git a/python/packages/core/agent_framework/_tools.py b/python/packages/core/agent_framework/_tools.py index 07b11811f3..d72e9bb6dc 100644 --- a/python/packages/core/agent_framework/_tools.py +++ b/python/packages/core/agent_framework/_tools.py @@ -783,8 +783,10 @@ async def invoke( else: logger.info(f"Function {self.name} succeeded.") if OBSERVABILITY_SETTINGS.SENSITIVE_DATA_ENABLED: # type: ignore[name-defined] + from ._types import prepare_function_call_results + try: - json_result = json.dumps(result) + json_result = prepare_function_call_results(result) except (TypeError, OverflowError): span.set_attribute(OtelAttr.TOOL_RESULT, "") logger.debug("Function result: ") From 28f2e4ce315f894fd1a50f47d3cd7868b9a5c00b Mon Sep 17 00:00:00 2001 From: eavanvalkenburg Date: Fri, 9 Jan 2026 10:40:29 +0100 Subject: [PATCH 2/4] fix Python: [Bug]: model_id versus model_deployment_name is confusing in Azure AI Agents Fixes #3147 --- .../azure-ai/agent_framework_azure_ai/_client.py | 7 +++++++ .../core/agent_framework/openai/_responses_client.py | 11 +++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/python/packages/azure-ai/agent_framework_azure_ai/_client.py b/python/packages/azure-ai/agent_framework_azure_ai/_client.py index 2e8edc7e47..666c472ab7 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/_client.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/_client.py @@ -421,6 +421,13 @@ async def _prepare_options( return run_options + @override + def _check_model_presence(self, run_options): + if not run_options.get("model"): + if not self.model_id: + raise ValueError("model_deployment_name must be a non-empty string") + run_options["model"] = self.model_id + def _transform_input_for_azure_ai(self, input_items: list[dict[str, Any]]) -> list[dict[str, Any]]: """Transform input items to match Azure AI Projects expected schema. diff --git a/python/packages/core/agent_framework/openai/_responses_client.py b/python/packages/core/agent_framework/openai/_responses_client.py index 579452ef62..cad40cb162 100644 --- a/python/packages/core/agent_framework/openai/_responses_client.py +++ b/python/packages/core/agent_framework/openai/_responses_client.py @@ -401,10 +401,7 @@ async def _prepare_options( run_options["input"] = request_input # 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 + self._check_model_presence(run_options) # translations between ChatOptions and Responses API translations = { @@ -466,6 +463,12 @@ async def _prepare_options( return run_options + def _check_model_presence(self, run_options): + 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 + def _get_current_conversation_id(self, chat_options: ChatOptions, **kwargs: Any) -> str | None: """Get the current conversation ID from chat options or kwargs.""" return chat_options.conversation_id or kwargs.get("conversation_id") From 53cce3a3b9dc432fb0671cb0ad060fa474acbb86 Mon Sep 17 00:00:00 2001 From: eavanvalkenburg Date: Fri, 9 Jan 2026 11:03:38 +0100 Subject: [PATCH 3/4] add types --- python/packages/azure-ai/agent_framework_azure_ai/_client.py | 2 +- .../packages/core/agent_framework/openai/_responses_client.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/packages/azure-ai/agent_framework_azure_ai/_client.py b/python/packages/azure-ai/agent_framework_azure_ai/_client.py index 666c472ab7..774ac20b2b 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/_client.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/_client.py @@ -422,7 +422,7 @@ async def _prepare_options( return run_options @override - def _check_model_presence(self, run_options): + def _check_model_presence(self, run_options: dict[str, Any]): if not run_options.get("model"): if not self.model_id: raise ValueError("model_deployment_name must be a non-empty string") diff --git a/python/packages/core/agent_framework/openai/_responses_client.py b/python/packages/core/agent_framework/openai/_responses_client.py index cad40cb162..29ea27df57 100644 --- a/python/packages/core/agent_framework/openai/_responses_client.py +++ b/python/packages/core/agent_framework/openai/_responses_client.py @@ -463,7 +463,7 @@ async def _prepare_options( return run_options - def _check_model_presence(self, run_options): + def _check_model_presence(self, run_options: dict[str, Any]): if not run_options.get("model"): if not self.model_id: raise ValueError("model_id must be a non-empty string") From fcb5d369cc8692c71bdce5b309ee603d60690864 Mon Sep 17 00:00:00 2001 From: eavanvalkenburg Date: Fri, 9 Jan 2026 11:29:31 +0100 Subject: [PATCH 4/4] fixed type and docstring --- .../azure-ai/agent_framework_azure_ai/_client.py | 2 +- .../core/agent_framework/azure/_responses_client.py | 13 +++++++++++++ .../agent_framework/openai/_responses_client.py | 6 +++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/python/packages/azure-ai/agent_framework_azure_ai/_client.py b/python/packages/azure-ai/agent_framework_azure_ai/_client.py index 774ac20b2b..0c7b9c9782 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/_client.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/_client.py @@ -422,7 +422,7 @@ async def _prepare_options( return run_options @override - def _check_model_presence(self, run_options: dict[str, Any]): + def _check_model_presence(self, run_options: dict[str, Any]) -> None: if not run_options.get("model"): if not self.model_id: raise ValueError("model_deployment_name must be a non-empty string") diff --git a/python/packages/core/agent_framework/azure/_responses_client.py b/python/packages/core/agent_framework/azure/_responses_client.py index 3f6140eeeb..c967a6d1b8 100644 --- a/python/packages/core/agent_framework/azure/_responses_client.py +++ b/python/packages/core/agent_framework/azure/_responses_client.py @@ -1,5 +1,6 @@ # Copyright (c) Microsoft. All rights reserved. +import sys from collections.abc import Mapping from typing import Any, TypeVar from urllib.parse import urljoin @@ -18,6 +19,11 @@ AzureOpenAISettings, ) +if sys.version_info >= (3, 12): + from typing import override # type: ignore # pragma: no cover +else: + from typing_extensions import override # type: ignore[import] # pragma: no cover + TAzureOpenAIResponsesClient = TypeVar("TAzureOpenAIResponsesClient", bound="AzureOpenAIResponsesClient") @@ -144,3 +150,10 @@ def __init__( client=async_client, instruction_role=instruction_role, ) + + @override + def _check_model_presence(self, run_options: dict[str, Any]) -> None: + if not run_options.get("model"): + if not self.model_id: + raise ValueError("deployment_name must be a non-empty string") + run_options["model"] = self.model_id diff --git a/python/packages/core/agent_framework/openai/_responses_client.py b/python/packages/core/agent_framework/openai/_responses_client.py index 29ea27df57..08c17c2619 100644 --- a/python/packages/core/agent_framework/openai/_responses_client.py +++ b/python/packages/core/agent_framework/openai/_responses_client.py @@ -463,7 +463,11 @@ async def _prepare_options( return run_options - def _check_model_presence(self, run_options: dict[str, Any]): + def _check_model_presence(self, run_options: dict[str, Any]) -> None: + """Check if the 'model' param is present, and if not raise a Error. + + Since AzureAIClients use a different param for this, this method is overridden in those clients. + """ if not run_options.get("model"): if not self.model_id: raise ValueError("model_id must be a non-empty string")