77 Role )
88from agent_framework_azure_ai import \
99 AzureAIClient # Provided by agent_framework
10- from azure .ai .projects .models import ConnectionType
10+ from azure .ai .projects .models import (
11+ PromptAgentDefinition ,
12+ AzureAISearchAgentTool ,
13+ AzureAISearchToolResource ,
14+ AISearchIndexResource ,
15+ )
1116from common .config .app_config import config
1217from common .database .database_base import DatabaseBase
1318from common .models .messages_af import TeamConfiguration
@@ -65,19 +70,23 @@ def __init__(
6570 self ._use_azure_search = self ._is_azure_search_requested ()
6671 self .use_reasoning = use_reasoning
6772
68- # Placeholder for server-created Azure AI agent id (if Azure Search path)
73+ # Placeholder for server-created Azure AI agent id/version (if Azure Search path)
6974 self ._azure_server_agent_id : Optional [str ] = None
75+ self ._azure_server_agent_version : Optional [str ] = None
7076
7177 # -------------------------
7278 # Mode detection
7379 # -------------------------
7480 def _is_azure_search_requested (self ) -> bool :
7581 """Determine if Azure AI Search raw tool path should be used."""
82+ print (f"[DEBUG _is_azure_search_requested] Agent={ self .agent_name } , search={ self .search } " )
7683 if not self .search :
84+ print (f"[DEBUG _is_azure_search_requested] Agent={ self .agent_name } : No search config, returning False" )
7785 return False
7886 # Minimal heuristic: presence of required attributes
7987
8088 has_index = hasattr (self .search , "index_name" ) and bool (self .search .index_name )
89+ print (f"[DEBUG _is_azure_search_requested] Agent={ self .agent_name } : has_index={ has_index } , index_name={ getattr (self .search , 'index_name' , None )} " )
8190 if has_index :
8291 self .logger .info (
8392 "Azure AI Search requested (connection_id=%s, index=%s)." ,
@@ -113,14 +122,17 @@ async def _collect_tools(self) -> List:
113122 # -------------------------
114123 async def _create_azure_search_enabled_client (self , chatClient = None ) -> Optional [AzureAIClient ]:
115124 """
116- Create a server-side Azure AI agent with Azure AI Search raw tool.
125+ Create a server-side Azure AI agent with Azure AI Search tool using create_version.
126+
127+ This uses the AIProjectClient.agents.create_version() approach with:
128+ - PromptAgentDefinition for agent configuration
129+ - AzureAISearchAgentTool with AzureAISearchToolResource for search capability
130+ - AISearchIndexResource for index configuration with project_connection_id
117131
118132 Requirements:
119- - An Azure AI Project Connection (type=AZURE_AI_SEARCH) that contains either:
120- a) API key + endpoint, OR
121- b) Managed Identity (RBAC enabled on the Search service with Search Service Contributor + Search Index Data Reader).
133+ - An Azure AI Project Connection for Azure AI Search
122134 - search_config.index_name must exist in the Search service.
123-
135+ - search_config.connection_name should match the AI Project connection name
124136
125137 Returns:
126138 AzureAIClient | None
@@ -134,92 +146,106 @@ async def _create_azure_search_enabled_client(self, chatClient=None) -> Optional
134146 self .logger .error ("Search configuration missing." )
135147 return None
136148
137- desired_connection_name = getattr (self .search , "connection_name" , None )
149+ # Get connection name - this is used as project_connection_id in create_version
150+ connection_name = getattr (self .search , "connection_name" , None )
151+ if not connection_name :
152+ # Fallback to environment variable
153+ connection_name = config .AZURE_AI_SEARCH_CONNECTION_NAME
154+ self .logger .info ("Using connection_name from environment: %s" , connection_name )
155+
138156 index_name = getattr (self .search , "index_name" , "" )
139157 query_type = getattr (self .search , "search_query_type" , "simple" )
158+ top_k = getattr (self .search , "top_k" , 5 )
140159
141160 if not index_name :
142161 self .logger .error (
143162 "index_name not provided in search_config; aborting Azure Search path."
144163 )
145164 return None
146165
147- resolved_connection_id = None
148-
149- try :
150- async for connection in self .project_client .connections .list ():
151- if connection .type == ConnectionType .AZURE_AI_SEARCH :
152-
153- if (
154- desired_connection_name
155- and connection .name == desired_connection_name
156- ):
157- resolved_connection_id = connection .id
158- break
159- # Fallback: if no specific connection requested and none resolved yet, take the first
160- if not desired_connection_name and not resolved_connection_id :
161- resolved_connection_id = connection .id
162- # Do not break yet; we log but allow chance to find a name match later. If not, this stays.
163-
164- if not resolved_connection_id :
165- self .logger .error (
166- "No Azure AI Search connection resolved. " "connection_name=%s" ,
167- desired_connection_name ,
168- )
169- # return None
170-
171- self .logger .info (
172- "Using Azure AI Search connection (id=%s, requested_name=%s)." ,
173- resolved_connection_id ,
174- desired_connection_name ,
166+ if not connection_name :
167+ self .logger .error (
168+ "connection_name not provided; aborting Azure Search path."
175169 )
176- except Exception as ex :
177- self .logger .error ("Failed to enumerate connections: %s" , ex )
178170 return None
179171
180- # Create agent with raw tool
172+ self .logger .info (
173+ "Creating Azure AI Search agent with create_version: connection_name=%s, index=%s, query_type=%s, top_k=%s" ,
174+ connection_name ,
175+ index_name ,
176+ query_type ,
177+ top_k ,
178+ )
179+
180+ # Create agent using create_version with PromptAgentDefinition and AzureAISearchAgentTool
181+ # This approach matches the Knowledge Mining Solution Accelerator pattern
181182 try :
182- azure_agent = await self .client .create_agent (
183- model = self .model_deployment_name ,
184- name = self .agent_name ,
185- instructions = (
186- f"{ self .agent_instructions } "
187- "Always use the Azure AI Search tool and configured index for knowledge retrieval."
183+ enhanced_instructions = (
184+ f"{ self .agent_instructions } "
185+ "Always use the Azure AI Search tool and configured index for knowledge retrieval."
186+ )
187+
188+ print (f"[DEBUG] Creating agent '{ self .agent_name } ' with instructions (first 200 chars): { enhanced_instructions [:200 ]} ..." )
189+ print (f"[DEBUG] Agent model: { self .model_deployment_name } " )
190+ print (f"[DEBUG] Search config: connection={ connection_name } , index={ index_name } , query_type={ query_type } , top_k={ top_k } " )
191+
192+ azure_agent = await self .project_client .agents .create_version (
193+ agent_name = self .agent_name ,
194+ definition = PromptAgentDefinition (
195+ model = self .model_deployment_name ,
196+ instructions = enhanced_instructions ,
197+ tools = [
198+ AzureAISearchAgentTool (
199+ azure_ai_search = AzureAISearchToolResource (
200+ indexes = [
201+ AISearchIndexResource (
202+ project_connection_id = connection_name ,
203+ index_name = index_name ,
204+ query_type = query_type ,
205+ top_k = top_k ,
206+ )
207+ ]
208+ )
209+ )
210+ ],
188211 ),
189- tools = [{"type" : "azure_ai_search" }],
190- tool_resources = {
191- "azure_ai_search" : {
192- "indexes" : [
193- {
194- "index_connection_id" : resolved_connection_id ,
195- "index_name" : index_name ,
196- "query_type" : query_type ,
197- }
198- ]
199- }
200- },
201212 )
213+
202214 self ._azure_server_agent_id = azure_agent .id
215+ self ._azure_server_agent_version = azure_agent .version
203216 self .logger .info (
204- "Created Azure server agent with Azure AI Search tool (agent_id=%s, index=%s, query_type=%s)." ,
217+ "Created Azure AI Search agent via create_version (name=%s, id=%s, version=%s, connection=%s, index=%s, query_type=%s, top_k=%s)." ,
218+ azure_agent .name ,
205219 azure_agent .id ,
220+ azure_agent .version ,
221+ connection_name ,
206222 index_name ,
207223 query_type ,
224+ top_k ,
208225 )
226+ print (f"[DEBUG] Created agent via create_version: name={ azure_agent .name } , id={ azure_agent .id } , version={ azure_agent .version } " )
227+ print (f"[DEBUG] Agent definition: { azure_agent .definition } " )
228+ print (f"[DEBUG] Agent instructions from definition: { getattr (azure_agent .definition , 'instructions' , 'N/A' )} " )
209229
230+ # Wrap in AzureAIClient using agent_name and agent_version (NOT agent_id)
231+ # AzureAIClient constructor: agent_name, agent_version, project_endpoint, credential
210232 chat_client = AzureAIClient (
211- project_client = self .project_client ,
212- agent_id = azure_agent .id ,
233+ project_endpoint = self .project_endpoint ,
234+ agent_name = azure_agent .name ,
235+ agent_version = azure_agent .version , # Use the specific version we just created
213236 credential = self .creds ,
214237 )
215238 return chat_client
239+
216240 except Exception as ex :
217241 self .logger .error (
218- "Failed to create Azure Search enabled agent (connection_id =%s, index=%s): %s" ,
219- resolved_connection_id ,
242+ "Failed to create Azure Search enabled agent via create_version (connection =%s, index=%s): %s" ,
243+ connection_name ,
220244 index_name ,
221245 ex ,
222246 )
247+ import traceback
248+ traceback .print_exc ()
223249 return None
224250
225251 # -------------------------
0 commit comments