Skip to content

Commit b1b528e

Browse files
Python: [BREAKING] Remove deprecated kwargs compatibility paths (microsoft#4858)
* [BREAKING] Remove deprecated kwargs compatibility paths Remove the deprecated kwargs compatibility shims across core agents, clients, tools, middleware, and telemetry. Keep workflow kwargs behavior intact in this branch and follow up separately in microsoft#4850. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix PR CI fallout for kwargs removal Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * updates * Fix Azure AI CI fallout Remove the stale _get_current_conversation_id override from the Azure AI client after the OpenAI base helper was deleted. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fixed new classes * Fix Assistants deprecated import gating Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix integration replay regressions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Switch multi-agent hosting samples to Azure chat completions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify Azure multi-agent sample config Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent ca6cdd1 commit b1b528e

52 files changed

Lines changed: 1136 additions & 971 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/python-integration-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ jobs:
210210
OPENAI_API_KEY: ${{ secrets.OPENAI__APIKEY }}
211211
AZURE_OPENAI_ENDPOINT: ${{ vars.AZUREOPENAI__ENDPOINT }}
212212
AZURE_OPENAI_DEPLOYMENT_NAME: ${{ vars.AZUREOPENAI__RESPONSESDEPLOYMENTNAME }}
213+
AZURE_OPENAI_CHAT_DEPLOYMENT_NAME: ${{ vars.AZUREOPENAI__CHATDEPLOYMENTNAME }}
213214
FOUNDRY_PROJECT_ENDPOINT: ${{ vars.FOUNDRY_PROJECT_ENDPOINT }}
214215
FOUNDRY_MODEL: ${{ vars.FOUNDRY_MODEL }}
215216
FUNCTIONS_WORKER_RUNTIME: "python"

.github/workflows/python-merge-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ jobs:
341341
OPENAI_API_KEY: ${{ secrets.OPENAI__APIKEY }}
342342
AZURE_OPENAI_ENDPOINT: ${{ vars.AZUREOPENAI__ENDPOINT }}
343343
AZURE_OPENAI_DEPLOYMENT_NAME: ${{ vars.AZUREOPENAI__RESPONSESDEPLOYMENTNAME }}
344+
AZURE_OPENAI_CHAT_DEPLOYMENT_NAME: ${{ vars.AZUREOPENAI__CHATDEPLOYMENTNAME }}
344345
FOUNDRY_PROJECT_ENDPOINT: ${{ vars.FOUNDRY_PROJECT_ENDPOINT }}
345346
FOUNDRY_MODEL: ${{ vars.FOUNDRY_MODEL }}
346347
FUNCTIONS_WORKER_RUNTIME: "python"

python/packages/a2a/tests/test_a2a_agent.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ def test_get_uri_data_invalid_uri() -> None:
366366
def test_parse_contents_from_a2a_conversion(a2a_agent: A2AAgent) -> None:
367367
"""Test A2A parts to contents conversion."""
368368

369-
agent = A2AAgent(name="Test Agent", client=MockA2AClient(), _http_client=None)
369+
agent = A2AAgent(name="Test Agent", client=MockA2AClient(), http_client=None)
370370

371371
# Create A2A parts
372372
parts = [Part(root=TextPart(text="First part")), Part(root=TextPart(text="Second part"))]
@@ -485,7 +485,7 @@ async def test_context_manager_no_cleanup_when_no_http_client() -> None:
485485

486486
mock_a2a_client = MagicMock()
487487

488-
agent = A2AAgent(client=mock_a2a_client, _http_client=None)
488+
agent = A2AAgent(client=mock_a2a_client, http_client=None)
489489

490490
# This should not raise any errors
491491
async with agent:
@@ -495,7 +495,7 @@ async def test_context_manager_no_cleanup_when_no_http_client() -> None:
495495
def test_prepare_message_for_a2a_with_multiple_contents() -> None:
496496
"""Test conversion of Message with multiple contents."""
497497

498-
agent = A2AAgent(client=MagicMock(), _http_client=None)
498+
agent = A2AAgent(client=MagicMock(), http_client=None)
499499

500500
# Create message with multiple content types
501501
message = Message(
@@ -523,7 +523,7 @@ def test_prepare_message_for_a2a_with_multiple_contents() -> None:
523523
def test_prepare_message_for_a2a_forwards_context_id() -> None:
524524
"""Test conversion of Message preserves context_id without duplicating it in metadata."""
525525

526-
agent = A2AAgent(client=MagicMock(), _http_client=None)
526+
agent = A2AAgent(client=MagicMock(), http_client=None)
527527

528528
message = Message(
529529
role="user",
@@ -540,7 +540,7 @@ def test_prepare_message_for_a2a_forwards_context_id() -> None:
540540
def test_parse_contents_from_a2a_with_data_part() -> None:
541541
"""Test conversion of A2A DataPart."""
542542

543-
agent = A2AAgent(client=MagicMock(), _http_client=None)
543+
agent = A2AAgent(client=MagicMock(), http_client=None)
544544

545545
# Create DataPart
546546
data_part = Part(root=DataPart(data={"key": "value", "number": 42}, metadata={"source": "test"}))
@@ -556,7 +556,7 @@ def test_parse_contents_from_a2a_with_data_part() -> None:
556556

557557
def test_parse_contents_from_a2a_unknown_part_kind() -> None:
558558
"""Test error handling for unknown A2A part kind."""
559-
agent = A2AAgent(client=MagicMock(), _http_client=None)
559+
agent = A2AAgent(client=MagicMock(), http_client=None)
560560

561561
# Create a mock part with unknown kind
562562
mock_part = MagicMock()
@@ -569,7 +569,7 @@ def test_parse_contents_from_a2a_unknown_part_kind() -> None:
569569
def test_prepare_message_for_a2a_with_hosted_file() -> None:
570570
"""Test conversion of Message with HostedFileContent to A2A message."""
571571

572-
agent = A2AAgent(client=MagicMock(), _http_client=None)
572+
agent = A2AAgent(client=MagicMock(), http_client=None)
573573

574574
# Create message with hosted file content
575575
message = Message(
@@ -595,7 +595,7 @@ def test_prepare_message_for_a2a_with_hosted_file() -> None:
595595
def test_parse_contents_from_a2a_with_hosted_file_uri() -> None:
596596
"""Test conversion of A2A FilePart with hosted file URI back to UriContent."""
597597

598-
agent = A2AAgent(client=MagicMock(), _http_client=None)
598+
agent = A2AAgent(client=MagicMock(), http_client=None)
599599

600600
# Create FilePart with hosted file URI (simulating what A2A would send back)
601601
file_part = Part(

python/packages/azure-ai/agent_framework_azure_ai/_agent_provider.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,16 +445,17 @@ def _to_chat_agent_from_agent(
445445

446446
# Merge tools: convert agent's hosted tools + user-provided function tools
447447
merged_tools = self._merge_tools(agent.tools, provided_tools)
448+
merged_default_options: dict[str, Any] = dict(default_options) if default_options is not None else {}
449+
merged_default_options.setdefault("model_id", agent.model)
448450

449451
return Agent( # type: ignore[return-value]
450452
client=client,
451453
id=agent.id,
452454
name=agent.name,
453455
description=agent.description,
454456
instructions=agent.instructions,
455-
model_id=agent.model,
456457
tools=merged_tools,
457-
default_options=default_options, # type: ignore[arg-type]
458+
default_options=cast(Any, merged_default_options),
458459
middleware=middleware,
459460
context_providers=context_providers,
460461
)

python/packages/azure-ai/agent_framework_azure_ai/_client.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -603,11 +603,6 @@ def _transform_input_for_azure_ai(self, input_items: list[dict[str, Any]]) -> li
603603

604604
return transformed
605605

606-
@override
607-
def _get_current_conversation_id(self, options: Mapping[str, Any], **kwargs: Any) -> str | None:
608-
"""Get the current conversation ID from chat options or kwargs."""
609-
return options.get("conversation_id") or kwargs.get("conversation_id") or self.conversation_id
610-
611606
@override
612607
def _parse_response_from_openai(
613608
self,

python/packages/azure-ai/agent_framework_azure_ai/_deprecated_azure_openai.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424
from agent_framework._tools import FunctionInvocationConfiguration, FunctionInvocationLayer
2525
from agent_framework._types import Annotation, Content
2626
from agent_framework.observability import ChatTelemetryLayer, EmbeddingTelemetryLayer
27-
from agent_framework_openai._assistants_client import OpenAIAssistantsClient, OpenAIAssistantsOptions
27+
from agent_framework_openai._assistants_client import (
28+
OpenAIAssistantsClient, # type: ignore[reportDeprecated]
29+
OpenAIAssistantsOptions,
30+
)
2831
from agent_framework_openai._chat_client import OpenAIChatOptions, RawOpenAIChatClient
2932
from agent_framework_openai._chat_completion_client import OpenAIChatCompletionOptions, RawOpenAIChatCompletionClient
3033
from agent_framework_openai._embedding_client import OpenAIEmbeddingOptions, RawOpenAIEmbeddingClient
@@ -673,7 +676,8 @@ def _parse_text_from_openai(self, choice: Choice | ChunkChoice) -> Content | Non
673676
"Use OpenAIAssistantsClient (also deprecated) or migrate to OpenAIChatClient."
674677
)
675678
class AzureOpenAIAssistantsClient(
676-
OpenAIAssistantsClient[AzureOpenAIAssistantsOptionsT], Generic[AzureOpenAIAssistantsOptionsT]
679+
OpenAIAssistantsClient[AzureOpenAIAssistantsOptionsT], # type: ignore[reportDeprecated]
680+
Generic[AzureOpenAIAssistantsOptionsT],
677681
):
678682
"""Deprecated Azure OpenAI Assistants client. Use OpenAIAssistantsClient or migrate to OpenAIChatClient."""
679683

python/packages/azure-ai/agent_framework_azure_ai/_project_provider.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import logging
66
import sys
77
from collections.abc import Callable, Mapping, MutableMapping, Sequence
8-
from typing import Any, Generic
8+
from typing import Any, Generic, cast
99

1010
from agent_framework import (
1111
AGENT_FRAMEWORK_USER_AGENT,
@@ -398,16 +398,17 @@ def _to_chat_agent_from_details(
398398
# from_azure_ai_tools converts hosted tools (MCP, code interpreter, file search, web search)
399399
# but function tools need the actual implementations from provided_tools
400400
merged_tools = self._merge_tools(details.definition.tools, provided_tools)
401+
merged_default_options: dict[str, Any] = dict(default_options) if default_options is not None else {}
402+
merged_default_options.setdefault("model_id", details.definition.model)
401403

402404
return Agent( # type: ignore[return-value]
403405
client=client,
404406
id=details.id,
405407
name=details.name,
406408
description=details.description,
407409
instructions=details.definition.instructions,
408-
model_id=details.definition.model,
409410
tools=merged_tools,
410-
default_options=default_options, # type: ignore[arg-type]
411+
default_options=cast(Any, merged_default_options),
411412
middleware=middleware,
412413
context_providers=context_providers,
413414
)

python/packages/azure-ai/tests/azure_openai/test_azure_responses_client.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,9 @@ async def test_integration_client_agent_existing_session():
477477
) as first_agent:
478478
# Start a conversation and capture the session
479479
session = first_agent.create_session()
480-
first_response = await first_agent.run("My hobby is photography. Remember this.", session=session, store=True)
480+
first_response = await first_agent.run(
481+
"My hobby is photography. Remember this.", session=session, options={"store": True}
482+
)
481483

482484
assert isinstance(first_response, AgentResponse)
483485
assert first_response.text is not None
@@ -492,7 +494,9 @@ async def test_integration_client_agent_existing_session():
492494
instructions="You are a helpful assistant with good memory.",
493495
) as second_agent:
494496
# Reuse the preserved session
495-
second_response = await second_agent.run("What is my hobby?", session=preserved_session)
497+
second_response = await second_agent.run(
498+
"What is my hobby?", session=preserved_session, options={"store": True}
499+
)
496500

497501
assert isinstance(second_response, AgentResponse)
498502
assert second_response.text is not None

python/packages/claude/agent_framework_claude/_agent.py

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import sys
88
from collections.abc import AsyncIterable, Awaitable, Callable, MutableMapping, Sequence
99
from pathlib import Path
10-
from typing import TYPE_CHECKING, Any, ClassVar, Generic, Literal, overload
10+
from typing import TYPE_CHECKING, Any, ClassVar, Generic, Literal, cast, overload
1111

1212
from agent_framework import (
1313
AgentMiddlewareTypes,
@@ -584,7 +584,7 @@ def _finalize_response(self, updates: Sequence[AgentResponseUpdate]) -> AgentRes
584584
return AgentResponse.from_updates(updates, value=structured_output)
585585

586586
@overload
587-
def run(
587+
def run( # type: ignore[override]
588588
self,
589589
messages: AgentRunInputs | None = None,
590590
*,
@@ -595,7 +595,7 @@ def run(
595595
) -> Awaitable[AgentResponse[Any]]: ...
596596

597597
@overload
598-
def run(
598+
def run( # type: ignore[override]
599599
self,
600600
messages: AgentRunInputs | None = None,
601601
*,
@@ -747,3 +747,71 @@ class ClaudeAgent(AgentTelemetryLayer, RawClaudeAgent[OptionsT], Generic[Options
747747
response = await agent.run("Hello!")
748748
print(response.text)
749749
"""
750+
751+
@overload # type: ignore[override]
752+
def run(
753+
self,
754+
messages: AgentRunInputs | None = None,
755+
*,
756+
stream: Literal[False] = ...,
757+
session: AgentSession | None = None,
758+
middleware: Sequence[AgentMiddlewareTypes] | None = None,
759+
options: OptionsT | None = None,
760+
tools: ToolTypes | Callable[..., Any] | Sequence[ToolTypes | Callable[..., Any]] | None = None,
761+
compaction_strategy: Any = None,
762+
tokenizer: Any = None,
763+
function_invocation_kwargs: dict[str, Any] | None = None,
764+
client_kwargs: dict[str, Any] | None = None,
765+
**kwargs: Any,
766+
) -> Awaitable[AgentResponse[Any]]: ...
767+
768+
@overload # type: ignore[override]
769+
def run(
770+
self,
771+
messages: AgentRunInputs | None = None,
772+
*,
773+
stream: Literal[True],
774+
session: AgentSession | None = None,
775+
middleware: Sequence[AgentMiddlewareTypes] | None = None,
776+
options: OptionsT | None = None,
777+
tools: ToolTypes | Callable[..., Any] | Sequence[ToolTypes | Callable[..., Any]] | None = None,
778+
compaction_strategy: Any = None,
779+
tokenizer: Any = None,
780+
function_invocation_kwargs: dict[str, Any] | None = None,
781+
client_kwargs: dict[str, Any] | None = None,
782+
**kwargs: Any,
783+
) -> ResponseStream[AgentResponseUpdate, AgentResponse[Any]]: ...
784+
785+
def run( # pyright: ignore[reportIncompatibleMethodOverride] # type: ignore[override]
786+
self,
787+
messages: AgentRunInputs | None = None,
788+
*,
789+
stream: bool = False,
790+
session: AgentSession | None = None,
791+
middleware: Sequence[AgentMiddlewareTypes] | None = None,
792+
options: OptionsT | None = None,
793+
tools: ToolTypes | Callable[..., Any] | Sequence[ToolTypes | Callable[..., Any]] | None = None,
794+
compaction_strategy: Any = None,
795+
tokenizer: Any = None,
796+
function_invocation_kwargs: dict[str, Any] | None = None,
797+
client_kwargs: dict[str, Any] | None = None,
798+
**kwargs: Any,
799+
) -> Awaitable[AgentResponse[Any]] | ResponseStream[AgentResponseUpdate, AgentResponse[Any]]:
800+
"""Run the Claude agent with telemetry enabled."""
801+
super_run = cast(
802+
"Callable[..., Awaitable[AgentResponse[Any]] | ResponseStream[AgentResponseUpdate, AgentResponse[Any]]]",
803+
super().run,
804+
)
805+
return super_run(
806+
messages=messages,
807+
stream=stream,
808+
session=session,
809+
middleware=middleware,
810+
options=options,
811+
tools=tools,
812+
compaction_strategy=compaction_strategy,
813+
tokenizer=tokenizer,
814+
function_invocation_kwargs=function_invocation_kwargs,
815+
client_kwargs=client_kwargs,
816+
**kwargs,
817+
)

0 commit comments

Comments
 (0)