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 }  )
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 }  
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 )}  
222+                 )
223+ 
224+ 
183225async  def  create_foundry_agent (agent_name :str ,
184226                               agent_description :str , 
185227                               agent_instructions :str ,
0 commit comments