Python: Fix AI Search Tool Sample and improve AI Search Exceptions (#1206)

* Python: Fix AI Search Tool Sample and improve AI Search Exceptions

* Python: Fix AI Search Tool Test

---------

Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
This commit is contained in:
Hassan Warsi
2025-10-10 11:46:57 -07:00
committed by GitHub
Unverified
parent e032fe3993
commit 350cdfc1cd
9 changed files with 33 additions and 20 deletions
@@ -949,7 +949,7 @@ class AzureAIAgentClient(BaseChatClient):
azs_conn_id = await self.project_client.connections.get_default(
ConnectionType.AZURE_AI_SEARCH
)
except HttpResponseError as err:
except ValueError as err:
raise ServiceInitializationError(
"No default Azure AI Search connection found in the Azure AI Project. "
"Please create one or provide vector store inputs for the file search tool.",
@@ -1067,8 +1067,8 @@ async def test_azure_ai_chat_client_prep_tools_file_search_no_connection(mock_ai
file_search_tool = HostedFileSearchTool(additional_properties={"index_name": "test-index"})
# Mock connections.get_default to raise HttpResponseError
mock_ai_project_client.connections.get_default = AsyncMock(side_effect=HttpResponseError("No connection found"))
# Mock connections.get_default to raise ValueError
mock_ai_project_client.connections.get_default = AsyncMock(side_effect=ValueError("No connection found"))
with pytest.raises(ServiceInitializationError, match="No default Azure AI Search connection found"):
await chat_client._prep_tools([file_search_tool]) # type: ignore
@@ -53,9 +53,7 @@ async def main():
resolver = A2ACardResolver(httpx_client=http_client, base_url=a2a_agent_host)
# Get agent card
agent_card = await resolver.get_agent_card(
relative_card_path="/.well-known/agent.json"
)
agent_card = await resolver.get_agent_card(relative_card_path="/.well-known/agent.json")
print(f"Found agent: {agent_card.name} - {agent_card.description}")
# Create A2A agent instance
@@ -43,9 +43,7 @@ async def main() -> None:
):
agent = chat_client.create_agent(
name="CodingAgent",
instructions=(
"You are a helpful assistant that can write and execute Python code to solve problems."
),
instructions=("You are a helpful assistant that can write and execute Python code to solve problems."),
tools=HostedCodeInterpreterTool(),
)
query = "Generate the factorial of 100 using python code, show the code and execute it."
@@ -63,12 +63,24 @@ async def main() -> None:
response = await agent.run(user_input)
print(f"# Agent: {response.text}")
# 5. Cleanup: Delete the vector store and file
try:
if vector_store:
await client.project_client.agents.vector_stores.delete(vector_store.id)
if file:
await client.project_client.agents.files.delete(file.id)
except Exception:
# Ignore cleanup errors to avoid masking issues
pass
finally:
# 5. Cleanup: Delete the vector store and file
# 6. Cleanup: Delete the vector store and file in case of eariler failure to prevent orphaned resources.
# Refreshing the client is required since chat agent closes it
client = AzureAIAgentClient(async_credential=AzureCliCredential())
try:
if vector_store is not None:
if vector_store:
await client.project_client.agents.vector_stores.delete(vector_store.id)
if file is not None:
if file:
await client.project_client.agents.files.delete(file.id)
except Exception:
# Ignore cleanup errors to avoid masking issues
@@ -261,11 +261,15 @@ class PolicyEngine(Executor):
@handler
async def handle_policy_request(
self, request: PolicyCheckRequest, ctx: WorkflowContext[RequestResponse[PolicyCheckRequest, Any] | PolicyCheckRequest]
self,
request: PolicyCheckRequest,
ctx: WorkflowContext[RequestResponse[PolicyCheckRequest, Any] | PolicyCheckRequest],
) -> None:
"""Handle POLICY requests from sub-workflows and apply rules."""
policy_request = request
print(f"🛡️ POLICY interceptor checking: {policy_request.amount} {policy_request.resource_type}, policy={policy_request.policy_type}")
print(
f"🛡️ POLICY interceptor checking: {policy_request.amount} {policy_request.resource_type}, policy={policy_request.policy_type}"
)
quota_limit = self.quota.get(policy_request.resource_type, 0)
@@ -182,7 +182,7 @@ class SmartEmailOrchestrator(Executor):
async def handle_domain_request(
self,
request: DomainCheckRequest,
ctx: WorkflowContext[RequestResponse[DomainCheckRequest, bool] | DomainCheckRequest]
ctx: WorkflowContext[RequestResponse[DomainCheckRequest, bool] | DomainCheckRequest],
) -> None:
"""Handle requests from sub-workflows."""
print(f"🔍 Parent intercepting domain check for: {request.domain}")
@@ -190,11 +190,7 @@ class SmartEmailOrchestrator(Executor):
if request.domain in self.approved_domains:
print(f"✅ Domain '{request.domain}' is pre-approved locally!")
# Send response back to sub-workflow
response = RequestResponse(
data=True,
original_request=request,
request_id=request.request_id
)
response = RequestResponse(data=True, original_request=request, request_id=request.request_id)
await ctx.send_message(response, target_id=request.source_executor_id)
else:
print(f"❓ Domain '{request.domain}' unknown, forwarding to external service...")
@@ -65,6 +65,7 @@ class CommonEvents(Enum):
EXIT_REQUESTED = "ExitRequested"
START_PROCESS = "StartProcess"
######################################################################
# region Semantic Kernel Process Framework path
######################################################################
@@ -153,6 +154,7 @@ async def run_semantic_kernel_process_example() -> None:
assert c_step_state.state.current_cycle == 3 # nosec
print(f"Final State Check: CStepState current cycle: {c_step_state.state.current_cycle}")
######################################################################
# region Agent Framework workflow path
######################################################################
@@ -50,6 +50,7 @@ class ProcessEvents(Enum):
OUTPUT_READY_PUBLIC = "OutputReadyPublic"
OUTPUT_READY_INTERNAL = "OutputReadyInternal"
######################################################################
# region Semantic Kernel nested process path
######################################################################
@@ -152,6 +153,7 @@ async def run_semantic_kernel_nested_process() -> None:
raise RuntimeError("RepeatStep state missing")
assert repeat_state.state.last_message == "Test Test Test Test" # nosec
######################################################################
# region Agent Framework nested workflow path
######################################################################
@@ -260,6 +262,7 @@ async def run_agent_framework_nested_workflow(initial_message: str) -> Sequence[
return results
######################################################################
# endregion
######################################################################