Skip to content

Commit 00cf047

Browse files
authored
Merge pull request #532 from microsoft/macae-v3-dev-marktayl
fix: P2 Bugs: 24003, 23959, 23504
2 parents dae3a10 + 2fb2567 commit 00cf047

File tree

4 files changed

+79
-38
lines changed

4 files changed

+79
-38
lines changed

data/agent_teams/marketing.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"use_reasoning": false,
3838
"index_name": "",
3939
"index_foundry_name": "",
40-
"coding_tools": true
40+
"coding_tools": false
4141
},
4242
{
4343
"input_key": "",

data/agent_teams/retail.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"use_reasoning": false,
3838
"index_name": "macae-index",
3939
"index_foundry_name": "",
40-
"coding_tools": true
40+
"coding_tools": false
4141
},
4242
{
4343
"input_key": "",

src/backend/v3/magentic_agents/foundry_agent.py

Lines changed: 76 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
import asyncio
44
import logging
5-
from typing import List, Optional
5+
from typing import Awaitable, List, Optional
66

77
from 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
1010
from v3.magentic_agents.common.lifecycle import AzureAgentBase
1111
from 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+
183225
async def create_foundry_agent(agent_name:str,
184226
agent_description:str,
185227
agent_instructions:str,

src/backend/v3/orchestration/human_approval_manager.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ def __init__(self, *args, **kwargs):
6262
"""
6363

6464
final_append = """
65-
The final answer should not include any offers of further conversation or assistance. The application will not all further interaction with the user.
66-
The final answer should be a complete and final response to the user's original request.
65+
DO NOT EVER OFFER TO HELP FURTHER IN THE FINAL ANSWER! Just provide the final answer and end with a polite closing.
6766
"""
6867

6968
# kwargs["task_ledger_facts_prompt"] = ORCHESTRATOR_TASK_LEDGER_FACTS_PROMPT + facts_append

0 commit comments

Comments
 (0)