11import json
22import logging
33import os
4- from typing import Any , Awaitable , Callable , Dict , List , Mapping , Optional , Union
4+ from abc import ABC , abstractmethod
5+ from typing import (Any , Awaitable , Callable , Dict , List , Mapping , Optional ,
6+ Union )
57
68import semantic_kernel as sk
7- from semantic_kernel .agents .azure_ai .azure_ai_agent import AzureAIAgent
8- from semantic_kernel .functions import KernelFunction
9- from semantic_kernel .functions .kernel_arguments import KernelArguments
10- from semantic_kernel .functions .kernel_function_decorator import kernel_function
11- from semantic_kernel .agents import AzureAIAgentThread
12-
13-
149# Import the new AppConfig instance
1510from app_config import config
1611from context .cosmos_memory_kernel import CosmosMemoryContext
1712from event_utils import track_event_if_configured
18- from models .messages_kernel import (
19- ActionRequest ,
20- ActionResponse ,
21- AgentMessage ,
22- Step ,
23- StepStatus ,
24- )
13+ from models .messages_kernel import (ActionRequest , ActionResponse ,
14+ AgentMessage , Step , StepStatus )
15+ from semantic_kernel .agents .azure_ai .azure_ai_agent import AzureAIAgent
16+ from semantic_kernel .functions import KernelFunction
17+ from semantic_kernel .functions .kernel_arguments import KernelArguments
18+ from semantic_kernel .functions .kernel_function_decorator import kernel_function
2519
2620# Default formatting instructions used across agents
2721DEFAULT_FORMATTING_INSTRUCTIONS = "Instructions: returning the output of this function call verbatim to the user in markdown. Then write AGENT SUMMARY: and then include a summary of what you did."
@@ -65,6 +59,7 @@ def __init__(
6559 endpoint = None , # Set as needed
6660 api_version = None , # Set as needed
6761 token = None , # Set as needed
62+ model = config .AZURE_OPENAI_DEPLOYMENT_NAME ,
6863 agent_name = agent_name ,
6964 system_prompt = system_message ,
7065 client = client ,
@@ -79,7 +74,7 @@ def __init__(
7974 self ._tools = tools
8075 self ._system_message = system_message
8176 self ._chat_history = [{"role" : "system" , "content" : self ._system_message }]
82- self ._agent = None # Will be initialized in async_init
77+ # self._agent = None # Will be initialized in async_init
8378
8479 # Required properties for AgentGroupChat compatibility
8580 self .name = agent_name # This is crucial for AgentGroupChat to identify agents
@@ -97,24 +92,6 @@ def default_system_message(agent_name=None) -> str:
9792 name = agent_name
9893 return f"You are an AI assistant named { name } . Help the user by providing accurate and helpful information."
9994
100- async def async_init (self ):
101- """Asynchronously initialize the agent after construction.
102-
103- This method must be called after creating the agent to complete initialization.
104- """
105- logging .info (f"Initializing agent: { self ._agent_name } " )
106- # Create Azure AI Agent or fallback
107- if not self ._agent :
108- self ._agent = await config .create_azure_ai_agent (
109- agent_name = self ._agent_name ,
110- instructions = self ._system_message ,
111- tools = self ._tools ,
112- )
113- else :
114- logging .info (f"Agent { self ._agent_name } already initialized." )
115- # Tools are registered with the kernel via get_tools_from_config
116- return self
117-
11895 async def handle_action_request (self , action_request : ActionRequest ) -> str :
11996 """Handle an action request from another agent or the system.
12097
@@ -160,7 +137,7 @@ async def handle_action_request(self, action_request: ActionRequest) -> str:
160137 # thread = self.client.agents.get_thread(
161138 # thread=step.session_id
162139 # ) # AzureAIAgentThread(thread_id=step.session_id)
163- async_generator = self ._agent . invoke (
140+ async_generator = self .invoke (
164141 messages = f"{ str (self ._chat_history )} \n \n Please perform this action" ,
165142 thread = thread ,
166143 )
@@ -264,3 +241,83 @@ def save_state(self) -> Mapping[str, Any]:
264241 def load_state (self , state : Mapping [str , Any ]) -> None :
265242 """Load the state of this agent."""
266243 self ._memory_store .load_state (state ["memory" ])
244+
245+ @classmethod
246+ @abstractmethod
247+ async def create (cls , ** kwargs ) -> "BaseAgent" :
248+ """Create an instance of the agent."""
249+ pass
250+
251+ @staticmethod
252+ async def _create_azure_ai_agent_definition (
253+ agent_name : str ,
254+ instructions : str ,
255+ tools : Optional [List [KernelFunction ]] = None ,
256+ client = None ,
257+ response_format = None ,
258+ temperature : float = 0.0 ,
259+ ):
260+ """
261+ Creates a new Azure AI Agent with the specified name and instructions using AIProjectClient.
262+ If an agent with the given name (assistant_id) already exists, it tries to retrieve it first.
263+
264+ Args:
265+ kernel: The Semantic Kernel instance
266+ agent_name: The name of the agent (will be used as assistant_id)
267+ instructions: The system message / instructions for the agent
268+ agent_type: The type of agent (defaults to "assistant")
269+ tools: Optional tool definitions for the agent
270+ tool_resources: Optional tool resources required by the tools
271+ response_format: Optional response format to control structured output
272+ temperature: The temperature setting for the agent (defaults to 0.0)
273+
274+ Returns:
275+ A new AzureAIAgent definition or an existing one if found
276+ """
277+ try :
278+ # Get the AIProjectClient
279+ if client is None :
280+ client = config .get_ai_project_client ()
281+
282+ # # First try to get an existing agent with this name as assistant_id
283+ try :
284+ agent_id = None
285+ agent_list = await client .agents .list_agents ()
286+ for agent in agent_list .data :
287+ if agent .name == agent_name :
288+ agent_id = agent .id
289+ break
290+ # If the agent already exists, we can use it directly
291+ # Get the existing agent definition
292+ if agent_id is not None :
293+ logging .info (f"Agent with ID { agent_id } exists." )
294+
295+ existing_definition = await client .agents .get_agent (agent_id )
296+
297+ return existing_definition
298+ except Exception as e :
299+ # The Azure AI Projects SDK throws an exception when the agent doesn't exist
300+ # (not returning None), so we catch it and proceed to create a new agent
301+ if "ResourceNotFound" in str (e ) or "404" in str (e ):
302+ logging .info (
303+ f"Agent with ID { agent_name } not found. Will create a new one."
304+ )
305+ else :
306+ # Log unexpected errors but still try to create a new agent
307+ logging .warning (
308+ f"Unexpected error while retrieving agent { agent_name } : { str (e )} . Attempting to create new agent."
309+ )
310+
311+ # Create the agent using the project client with the agent_name as both name and assistantId
312+ agent_definition = await client .agents .create_agent (
313+ model = config .AZURE_OPENAI_DEPLOYMENT_NAME ,
314+ name = agent_name ,
315+ instructions = instructions ,
316+ temperature = temperature ,
317+ response_format = response_format ,
318+ )
319+
320+ return agent_definition
321+ except Exception as exc :
322+ logging .error ("Failed to create Azure AI Agent: %s" , exc )
323+ raise
0 commit comments