From 4cd76bf2b08b6f640253f5363a45a45c9db85179 Mon Sep 17 00:00:00 2001 From: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com> Date: Mon, 29 Sep 2025 01:43:00 -0700 Subject: [PATCH] Small fixes (#969) --- .../packages/main/agent_framework/_clients.py | 17 +++++++-- .../samples/getting_started/agents/README.md | 21 ++++++----- .../azure_ai/azure_ai_with_existing_agent.py | 2 +- .../multimodal_input/azure_chat_multimodal.py | 7 ++-- .../openai_chat_multimodal.py | 35 +++++++++++-------- 5 files changed, 53 insertions(+), 29 deletions(-) diff --git a/python/packages/main/agent_framework/_clients.py b/python/packages/main/agent_framework/_clients.py index fcebe612ce..e98c0e54ed 100644 --- a/python/packages/main/agent_framework/_clients.py +++ b/python/packages/main/agent_framework/_clients.py @@ -212,6 +212,17 @@ class BaseChatClient(AFBaseModel, ABC): """Turn the allowed input into a list of chat messages.""" return prepare_messages(messages) + def _filter_internal_kwargs(self, kwargs: dict[str, Any]) -> dict[str, Any]: + """Filter out internal framework parameters that shouldn't be passed to chat client implementations. + + Args: + kwargs: The original kwargs dictionary. + + Returns: + A filtered kwargs dictionary without internal parameters. + """ + return {k: v for k, v in kwargs.items() if not k.startswith("_")} + @staticmethod def _normalize_tools( tools: ToolProtocol @@ -360,7 +371,8 @@ class BaseChatClient(AFBaseModel, ABC): prepped_messages = self.prepare_messages(messages) self._prepare_tool_choice(chat_options=chat_options) - return await self._inner_get_response(messages=prepped_messages, chat_options=chat_options, **kwargs) + filtered_kwargs = self._filter_internal_kwargs(kwargs) + return await self._inner_get_response(messages=prepped_messages, chat_options=chat_options, **filtered_kwargs) async def get_streaming_response( self, @@ -440,8 +452,9 @@ class BaseChatClient(AFBaseModel, ABC): prepped_messages = self.prepare_messages(messages) self._prepare_tool_choice(chat_options=chat_options) + filtered_kwargs = self._filter_internal_kwargs(kwargs) async for update in self._inner_get_streaming_response( - messages=prepped_messages, chat_options=chat_options, **kwargs + messages=prepped_messages, chat_options=chat_options, **filtered_kwargs ): yield update diff --git a/python/samples/getting_started/agents/README.md b/python/samples/getting_started/agents/README.md index 15dfee08da..e8c5f42e9c 100644 --- a/python/samples/getting_started/agents/README.md +++ b/python/samples/getting_started/agents/README.md @@ -1,6 +1,6 @@ # Agent Examples -This folder contains examples demonstrating how to create and use agents with different chat clients from the Agent Framework. Each sub-folder focuses on a specific provider and client type, showing various capabilities like function tools, code interpreter, thread management, and more. +This folder contains examples demonstrating how to create and use agents with different chat clients from the Agent Framework. Each sub-folder focuses on a specific provider and client type, showing various capabilities like function tools, code interpreter, thread management, structured outputs, image processing, web search, Model Context Protocol (MCP) integration, and more. ## Examples by Provider @@ -8,29 +8,34 @@ This folder contains examples demonstrating how to create and use agents with di | Folder | Description | |--------|-------------| -| **[`azure_ai/`](azure_ai/)** | Create agents using Azure AI Foundry Agent Service | +| **[`azure_ai/`](azure_ai/)** | Create agents using Azure AI Foundry Agent Service with various tools including function tools, code interpreter, MCP integration, and thread management | ### Microsoft Copilot Studio Examples | Folder | Description | |--------|-------------| -| **[`copilotstudio/`](copilotstudio/)** | Create agents using Microsoft Copilot Studio | +| **[`copilotstudio/`](copilotstudio/)** | Create agents using Microsoft Copilot Studio with streaming and non-streaming responses, authentication handling, and explicit configuration options | ### Azure OpenAI Examples | Folder | Description | |--------|-------------| -| **[`azure_openai/`](azure_openai/)** | Create agents using Azure OpenAI APIs | +| **[`azure_openai/`](azure_openai/)** | Create agents using Azure OpenAI APIs with multiple client types (Assistants, Chat, and Responses clients) supporting function tools, code interpreter, thread management, and more | ### OpenAI Examples | Folder | Description | |--------|-------------| -| **[`openai/`](openai/)** | Create agents using OpenAI APIs | +| **[`openai/`](openai/)** | Create agents using OpenAI APIs with comprehensive examples including Assistants, Chat, and Responses clients featuring function tools, code interpreter, file search, web search, MCP integration, image analysis/generation, structured outputs, reasoning, and thread management | -### Custom Client Examples +### Anthropic Examples | Folder | Description | |--------|-------------| -| **[`custom_client/`](custom_client/)** | Create agents using a custom chat client or a custom agent | -| **[`anthropic/`](anthropic/)** | Create agents using Anthropic APIs | +| **[`anthropic/`](anthropic/)** | Create agents using Anthropic models through OpenAI Chat Client configuration, demonstrating tool calling capabilities | + +### Custom Implementation Examples + +| Folder | Description | +|--------|-------------| +| **[`custom/`](custom/)** | Create custom agents and chat clients by extending the base framework classes, showing complete control over agent behavior and backend integration | diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_existing_agent.py b/python/samples/getting_started/agents/azure_ai/azure_ai_with_existing_agent.py index 7dd2f81801..fd9ff42e22 100644 --- a/python/samples/getting_started/agents/azure_ai/azure_ai_with_existing_agent.py +++ b/python/samples/getting_started/agents/azure_ai/azure_ai_with_existing_agent.py @@ -37,7 +37,7 @@ async def main() -> None: async with ChatAgent( # passing in the client is optional here, so if you take the agent_id from the portal # you can use it directly without the two lines above. - chat_client=AzureAIAgentClient(client=client, agent_id=created_agent.id), + chat_client=AzureAIAgentClient(project_client=client, agent_id=created_agent.id), instructions="You are a helpful weather agent.", tools=get_weather, ) as agent: diff --git a/python/samples/getting_started/multimodal_input/azure_chat_multimodal.py b/python/samples/getting_started/multimodal_input/azure_chat_multimodal.py index cbea8657c1..ec31d8176d 100644 --- a/python/samples/getting_started/multimodal_input/azure_chat_multimodal.py +++ b/python/samples/getting_started/multimodal_input/azure_chat_multimodal.py @@ -6,11 +6,12 @@ import base64 import requests from agent_framework import ChatMessage, DataContent, Role, TextContent from agent_framework.azure import AzureOpenAIChatClient +from azure.identity import AzureCliCredential -async def test_image(): +async def test_image() -> None: """Test image analysis with Azure.""" - client = AzureOpenAIChatClient() + client = AzureOpenAIChatClient(credential=AzureCliCredential()) # Fetch image from httpbin image_url = "https://httpbin.org/image/jpeg" @@ -27,7 +28,7 @@ async def test_image(): print(f"Image Response: {response}") -async def main(): +async def main() -> None: print("=== Testing Azure Multimodal ===") await test_image() diff --git a/python/samples/getting_started/multimodal_input/openai_chat_multimodal.py b/python/samples/getting_started/multimodal_input/openai_chat_multimodal.py index 27cc46908c..39af7a7575 100644 --- a/python/samples/getting_started/multimodal_input/openai_chat_multimodal.py +++ b/python/samples/getting_started/multimodal_input/openai_chat_multimodal.py @@ -2,12 +2,14 @@ import asyncio import base64 -import requests import struct + +import requests from agent_framework import ChatMessage, DataContent, Role, TextContent from agent_framework.openai import OpenAIChatClient -async def test_image(): + +async def test_image() -> None: """Test image analysis with OpenAI.""" client = OpenAIChatClient(ai_model_id="gpt-4o") @@ -19,26 +21,27 @@ async def test_image(): message = ChatMessage( role=Role.USER, - contents=[ - TextContent(text="What's in this image?"), - DataContent(uri=image_uri, media_type="image/jpeg") - ] + contents=[TextContent(text="What's in this image?"), DataContent(uri=image_uri, media_type="image/jpeg")], ) response = await client.get_response(message) print(f"Image Response: {response}") -async def test_audio(): + +async def test_audio() -> None: """Test audio analysis with OpenAI.""" client = OpenAIChatClient(ai_model_id="gpt-4o-audio-preview") # Create minimal WAV file (0.1 seconds of silence) wav_header = ( - b'RIFF' + struct.pack(' None: print("=== Testing OpenAI Multimodal ===") await test_image() await test_audio() + if __name__ == "__main__": asyncio.run(main())