22
33import asyncio
44import logging
5- from typing import List , Optional
5+ from typing import Awaitable , List , Optional
66
77from azure .ai .agents .models import (AzureAISearchTool , BingGroundingTool ,
88 CodeInterpreterToolDefinition )
9- from semantic_kernel .agents import AzureAIAgent # pylint: disable=E0611
9+ from semantic_kernel .agents import Agent , AzureAIAgent # pylint: disable=E0611
1010from v3 .magentic_agents .common .lifecycle import AzureAgentBase
1111from v3 .magentic_agents .models .agent_models import MCPConfig , SearchConfig
1212
@@ -43,6 +43,7 @@ def __init__(self, agent_name: str,
4343 if self .model_deployment_name in ["o3" , "o4-mini" ]:
4444 raise ValueError ("The current version of Foundry agents do not support reasoning models." )
4545
46+ # Uncomment to enable bing grounding capabilities (requires Bing connection in Foundry and uncommenting other code)
4647 # async def _make_bing_tool(self) -> Optional[BingGroundingTool]:
4748 # """Create Bing search tool for web search."""
4849 # if not all([self.client, self.bing.connection_name]):
@@ -119,19 +120,24 @@ async def _collect_tools_and_resources(self) -> tuple[List, dict]:
119120 return tools , tool_resources
120121
121122 async def _after_open (self ) -> None :
122-
123- # Collect all tools
124- tools , tool_resources = await self ._collect_tools_and_resources ()
125-
126- # Create agent definition with all tools
127- definition = await self .client .agents .create_agent (
128- model = self .model_deployment_name ,
129- name = self .agent_name ,
130- description = self .agent_description ,
131- instructions = self .agent_instructions ,
132- tools = tools ,
133- tool_resources = tool_resources
134- )
123+ """Initialize the AzureAIAgent with the collected tools and MCP plugin."""
124+
125+ # Try to get existing agent definition from Foundry
126+ definition = await self ._get_azure_ai_agent_definition (self .agent_name )
127+ # If not found in Foundry, create a new one
128+ if definition is None :
129+ # Collect all tools
130+ tools , tool_resources = await self ._collect_tools_and_resources ()
131+
132+ # Create agent definition with all tools
133+ definition = await self .client .agents .create_agent (
134+ model = self .model_deployment_name ,
135+ name = self .agent_name ,
136+ description = self .agent_description ,
137+ instructions = self .agent_instructions ,
138+ tools = tools ,
139+ tool_resources = tool_resources
140+ )
135141
136142 # Add MCP plugins if available
137143 plugins = [self .mcp_plugin ] if self .mcp_plugin else []
@@ -146,25 +152,25 @@ async def _after_open(self) -> None:
146152 self .logger .error ("Failed to create AzureAIAgent: %s" , ex )
147153 raise
148154
149- # After self._agent creation in _after_open:
150- # Diagnostics
151- try :
152- tool_names = [t .get ("function" , {}).get ("name" ) for t in (definition .tools or []) if isinstance (t , dict )]
153- self .logger .info (
154- "Foundry agent '%s' initialized. Azure tools: %s | MCP plugin: %s" ,
155- self .agent_name ,
156- tool_names ,
157- getattr (self .mcp_plugin , 'name' , None )
158- )
159- if not tool_names and not plugins :
160- self .logger .warning (
161- "Foundry agent '%s' has no Azure tool definitions and no MCP plugin. "
162- "Subsequent tool calls may fail." , self .agent_name
163- )
164- except Exception as diag_ex :
165- self .logger .warning ("Diagnostics collection failed: %s" , diag_ex )
166-
167- self .logger .info ("%s initialized with %d tools and %d plugins" , self .agent_name , len (tools ), len (plugins ))
155+ # # After self._agent creation in _after_open:
156+ # # Diagnostics
157+ # try:
158+ # tool_names = [t.get("function", {}).get("name") for t in (definition.tools or []) if isinstance(t, dict)]
159+ # self.logger.info(
160+ # "Foundry agent '%s' initialized. Azure tools: %s | MCP plugin: %s",
161+ # self.agent_name,
162+ # tool_names,
163+ # getattr(self.mcp_plugin, 'name', None)
164+ # )
165+ # if not tool_names and not plugins:
166+ # self.logger.warning(
167+ # "Foundry agent '%s' has no Azure tool definitions and no MCP plugin. "
168+ # "Subsequent tool calls may fail.", self.agent_name
169+ # )
170+ # except Exception as diag_ex:
171+ # self.logger.warning("Diagnostics collection failed: %s", diag_ex)
172+
173+ # self.logger.info("%s initialized with %d tools and %d plugins", self.agent_name, len(tools), len(plugins))
168174
169175 async def fetch_run_details (self , thread_id : str , run_id : str ):
170176 """Fetch and log run details after a failure."""
@@ -180,6 +186,42 @@ async def fetch_run_details(self, thread_id: str, run_id: str):
180186 except Exception as ex :
181187 self .logger .error ("Could not fetch run details: %s" , ex )
182188
189+ async def _get_azure_ai_agent_definition (self , agent_name : str )-> Awaitable [Agent | None ]:
190+ """
191+ Gets an Azure AI Agent with the specified name and instructions using AIProjectClient if it is already created.
192+ """
193+ # # First try to get an existing agent with this name as assistant_id
194+ try :
195+ agent_id = None
196+ agent_list = self .client .agents .list_agents ()
197+ async for agent in agent_list :
198+ if agent .name == agent_name :
199+ agent_id = agent .id
200+ break
201+ # If the agent already exists, we can use it directly
202+ # Get the existing agent definition
203+ if agent_id is not None :
204+ logging .info (f"Agent with ID { agent_id } exists." )
205+
206+ existing_definition = await self .client .agents .get_agent (agent_id )
207+
208+ return existing_definition
209+ else :
210+ return None
211+ except Exception as e :
212+ # The Azure AI Projects SDK throws an exception when the agent doesn't exist
213+ # (not returning None), so we catch it and proceed to create a new agent
214+ if "ResourceNotFound" in str (e ) or "404" in str (e ):
215+ logging .info (
216+ f"Agent with ID { agent_name } not found. Will create a new one."
217+ )
218+ else :
219+ # Log unexpected errors but still try to create a new agent
220+ logging .warning (
221+ f"Unexpected error while retrieving agent { agent_name } : { str (e )} . Attempting to create new agent."
222+ )
223+
224+
183225async def create_foundry_agent (agent_name :str ,
184226 agent_description :str ,
185227 agent_instructions :str ,
0 commit comments