1
1
import json
2
2
import logging
3
3
import 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 )
5
7
6
8
import 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
-
14
9
# Import the new AppConfig instance
15
10
from app_config import config
16
11
from context .cosmos_memory_kernel import CosmosMemoryContext
17
12
from 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
25
19
26
20
# Default formatting instructions used across agents
27
21
DEFAULT_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__(
65
59
endpoint = None , # Set as needed
66
60
api_version = None , # Set as needed
67
61
token = None , # Set as needed
62
+ model = config .AZURE_OPENAI_DEPLOYMENT_NAME ,
68
63
agent_name = agent_name ,
69
64
system_prompt = system_message ,
70
65
client = client ,
@@ -79,7 +74,7 @@ def __init__(
79
74
self ._tools = tools
80
75
self ._system_message = system_message
81
76
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
83
78
84
79
# Required properties for AgentGroupChat compatibility
85
80
self .name = agent_name # This is crucial for AgentGroupChat to identify agents
@@ -97,24 +92,6 @@ def default_system_message(agent_name=None) -> str:
97
92
name = agent_name
98
93
return f"You are an AI assistant named { name } . Help the user by providing accurate and helpful information."
99
94
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
-
118
95
async def handle_action_request (self , action_request : ActionRequest ) -> str :
119
96
"""Handle an action request from another agent or the system.
120
97
@@ -160,7 +137,7 @@ async def handle_action_request(self, action_request: ActionRequest) -> str:
160
137
# thread = self.client.agents.get_thread(
161
138
# thread=step.session_id
162
139
# ) # AzureAIAgentThread(thread_id=step.session_id)
163
- async_generator = self ._agent . invoke (
140
+ async_generator = self .invoke (
164
141
messages = f"{ str (self ._chat_history )} \n \n Please perform this action" ,
165
142
thread = thread ,
166
143
)
@@ -264,3 +241,83 @@ def save_state(self) -> Mapping[str, Any]:
264
241
def load_state (self , state : Mapping [str , Any ]) -> None :
265
242
"""Load the state of this agent."""
266
243
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