diff --git a/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/infra/main.bicep b/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/infra/main.bicep index 9a960c95d..a8336b9b5 100644 --- a/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/infra/main.bicep +++ b/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/infra/main.bicep @@ -35,6 +35,7 @@ var searchManager = '7ca78c08-252a-4471-8644-bb5ff32d4ba0' var foundryUser = '53ca6127-db72-4b80-b1b0-d745d6d5456d' var foundryProjectManager = 'eadc314b-1a2d-4efa-be10-5d325db5065e' var modelUser = '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' +var logAnalyticsReader = '73c42c96-874c-492b-b04d-ab87d138a893' var lakeContainers = ['lake-raw', 'regulatory-knowledge'] resource logs 'Microsoft.OperationalInsights/workspaces@2023-09-01' = { @@ -104,6 +105,21 @@ resource embedding 'Microsoft.CognitiveServices/accounts/deployments@2025-06-01' } } +// Agent traces (the Traces tab) are stored in Application Insights, connected to the project. +resource tracing 'Microsoft.CognitiveServices/accounts/projects/connections@2025-06-01' = { + parent: project + name: 'appinsights' + dependsOn: [embedding] + properties: { + category: 'AppInsights' + target: insights.id + authType: 'ApiKey' + isSharedToAll: true + credentials: { key: insights.properties.ConnectionString } + metadata: { ApiType: 'Azure', ResourceId: insights.id } + } +} + resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = { name: 'stregintel${resourceSuffix}' location: location @@ -168,6 +184,19 @@ resource participantModels 'Microsoft.Authorization/roleAssignments@2022-04-01' properties: { principalId: id, principalType: 'User', roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', modelUser) } }] +// The Traces tab queries Application Insights and its Log Analytics workspace as the signed-in user. +resource participantTraces 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for id in participantObjectIds: { + name: guid(insights.id, id, logAnalyticsReader) + scope: insights + properties: { principalId: id, principalType: 'User', roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', logAnalyticsReader) } +}] + +resource participantLogs 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for id in participantObjectIds: { + name: guid(logs.id, id, logAnalyticsReader) + scope: logs + properties: { principalId: id, principalType: 'User', roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', logAnalyticsReader) } +}] + resource participantBlobs 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for id in participantObjectIds: { name: guid(storage.id, id, blobContributor) scope: storage diff --git a/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/labautomation/README.md b/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/labautomation/README.md index 7b14bb830..597020afa 100644 --- a/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/labautomation/README.md +++ b/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/labautomation/README.md @@ -13,7 +13,7 @@ This folder follows the [scaffolding prompt](../.github/prompts/scaffold-lab-aut | Embedding model `text-embedding-3-small` (GlobalStandard, capacity 30) | Used by Foundry IQ to index the lake | | Storage account with private containers `lake-raw` and `regulatory-knowledge` | The regulatory lake. Shared keys and public blob access are disabled; access is by Entra ID only. Tagged `SecurityControl: Ignore` (parameter `storageTags`) so that tenant automation in managed subscriptions does not disable public network access, which Cloud Shell and the Search indexer need | | Azure AI Search (Basic, semantic ranker free plan) with a system-assigned identity | Foundry IQ knowledge base | -| Log Analytics and Application Insights | Monitoring | +| Log Analytics and Application Insights, connected to the project (connection `appinsights`) | Agent traces for the **Traces** tab, including the runs from the Challenge 6 agent chain | Role assignments, all scoped to the attendee's own resources: @@ -22,6 +22,7 @@ Role assignments, all scoped to the attendee's own resources: | Attendee | Foundry User, **Foundry Project Manager** (to add the knowledge connection) | Project | | Attendee | Cognitive Services OpenAI User | Foundry account | | Attendee | Storage Blob Data Contributor | Storage account | +| Attendee | Log Analytics Reader (to read agent traces) | Application Insights and its Log Analytics workspace | | Attendee | Search Service Contributor, Search Index Data Contributor | Search service | | Search identity | Storage Blob Data Reader; Cognitive Services OpenAI User | Storage account; Foundry account | | Project identity | Search Index Data Reader, Search Index Data Contributor, Search Service Contributor; Cognitive Services OpenAI User | Search service (Foundry IQ connects with the project managed identity because Search API keys are disabled); Foundry account | diff --git a/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/tests/test_content.py b/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/tests/test_content.py index 75af4cef8..8b5fd41a7 100644 --- a/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/tests/test_content.py +++ b/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/tests/test_content.py @@ -123,6 +123,7 @@ def test_template_role_ids_are_real_built_in_roles(): "53ca6127-db72-4b80-b1b0-d745d6d5456d": "Foundry User", "eadc314b-1a2d-4efa-be10-5d325db5065e": "Foundry Project Manager", "5e0bd9bd-7b93-4f28-af87-19fc36ad61bd": "Cognitive Services OpenAI User", + "73c42c96-874c-492b-b04d-ab87d138a893": "Log Analytics Reader", } template = (LAB / "infra" / "main.bicep").read_text(encoding="utf-8") used = set(re.findall(r"'([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})'", template)) diff --git a/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/walkthrough/challenge-06/solution-06.md b/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/walkthrough/challenge-06/solution-06.md index dc1096d57..56e343977 100644 --- a/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/walkthrough/challenge-06/solution-06.md +++ b/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/walkthrough/challenge-06/solution-06.md @@ -79,5 +79,6 @@ This is why the assistant only ever proposes: a person reviews the briefing and | `DefaultAzureCredential failed` | Run `az login --use-device-code` in the Codespace terminal | | Azure Storage permission error | Wrong subscription or account name; check `az account show` | | `rate_limit_exceeded` (429) | Several medium-reasoning agents ran at once and used the deployment's tokens per minute | Wait a minute and run again; use `--limit 1` | +| **Traces** says *Create or connect an App Insights resource* | The project has no Application Insights connection. The lab automation creates one (`appinsights`); in an older lab, select **Connect** and choose the lab's Application Insights. Only runs after connecting are traced. | | `The workflow returned no briefing` | Open Traces for the three agents; usually one agent without `caldova-regulatory-kb` under Knowledge, or still with Web search | | Codespace setup failed | Rebuild the container; if it fails again, use the local devcontainer and report the log to the facilitator |