Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Last updated: 2025-12-04
> [!IMPORTANT]
> Disclaimer: This repository contains a demo of `Zava AI Shopping Assistant`, an enhanced multi-agent system implementing Agent-to-Agent (A2A) protocol for e-commerce. It features a fully automated `"Zero-Touch" deployment` pipeline orchestrated by Terraform, which `provisions infrastructure, ingests data, creates specialized AI agents with delegation patterns in MSFT Foundry, and deploys the complete A2A application stack.` Please refer [TechWorkshop L300: AI Apps and Agents](https://microsoft.github.io/TechWorkshop-L300-AI-Apps-and-agents/), and if needed contact Microsoft directly: [Microsoft Sales and Support](https://support.microsoft.com/contactus?ContactUsExperienceEntryPointAssetId=S.HP.SMC-HOME) for more guidance. There are tons of free resources out there, all eager to support!

> E.g

<img width="1905" height="1086" alt="image" src="https://github.com/user-attachments/assets/5cd2776f-4606-45c2-9482-53ff2d4df74e" />

> [!IMPORTANT]
Expand Down Expand Up @@ -116,6 +118,8 @@ graph TD
- Deploys AI Models (`gpt-4o-mini`, `text-embedding-3-small`).
- Sets up A2A protocol infrastructure including event queues and monitoring.

> E.g

<img width="1859" height="900" alt="image" src="https://github.com/user-attachments/assets/cd24ab7f-5ddd-46de-b266-0d0a24c45803" />

2. **A2A Framework Deployment**:
Expand All @@ -128,10 +132,14 @@ graph TD
- Sets up a Python virtual environment.
- Ingests `product_catalog.csv` into Cosmos DB with A2A event notifications.

> E.g

<https://github.com/user-attachments/assets/41bf0976-0ca8-47fe-a2fa-8750bcc6f848>

- Creates and populates an Azure AI Search index with vector embeddings through A2A coordination.

> E.g

<https://github.com/user-attachments/assets/37c4a8cd-73e1-4392-8755-fb018481d8cb>

4. **Enhanced Agent Creation & A2A Registration**:
Expand All @@ -145,7 +153,9 @@ graph TD
- Configures delegation relationships between Product Manager and specialized agents.
- Saves the unique Agent IDs, delegation endpoints, and A2A configuration to the `.env` file.

<img width="1907" height="990" alt="image" src="https://github.com/user-attachments/assets/4234ead4-16e0-4bec-bbfd-3b8891d113b0" />
> E.g

<img width="1881" height="1000" alt="image" src="https://github.com/user-attachments/assets/59a9dcaf-9291-403c-b8b0-1195c1375aac" />

5. **Application Deployment**:
- Builds the Docker container with A2A protocol support in the cloud (ACR Build).
Expand All @@ -161,6 +171,8 @@ graph TD
- Visit `https://<your-app-name>.azurewebsites.net`.
- You should see the Zava chat interface with A2A protocol support.

> E.g

<https://github.com/user-attachments/assets/a1139528-6b37-4ac2-a1cb-771788ff45a4>

2. **Verify A2A Protocol Endpoints**:
Expand All @@ -175,6 +187,8 @@ graph TD
- Core agents: Cora, Interior Design, Inventory, Loyalty, Cart Manager
- Product Management Specialist with delegation capabilities

> E.g

<https://github.com/user-attachments/assets/3c562ccd-cff3-4a30-b9f8-44111fb71113>

4. **Test Enhanced A2A Interactions**: For example:
Expand All @@ -188,7 +202,7 @@ graph TD

<!-- START BADGE -->
<div align="center">
<img src="https://img.shields.io/badge/Total%20views-1624-limegreen" alt="Total views">
<p>Refresh Date: 2025-12-03</p>
<img src="https://img.shields.io/badge/Total%20views-1696-limegreen" alt="Total views">
<p>Refresh Date: 2025-12-04</p>
</div>
<!-- END BADGE -->
4 changes: 2 additions & 2 deletions TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ terraform apply

<!-- START BADGE -->
<div align="center">
<img src="https://img.shields.io/badge/Total%20views-1624-limegreen" alt="Total views">
<p>Refresh Date: 2025-12-03</p>
<img src="https://img.shields.io/badge/Total%20views-1696-limegreen" alt="Total views">
<p>Refresh Date: 2025-12-04</p>
</div>
<!-- END BADGE -->
9 changes: 8 additions & 1 deletion src/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@ FROM python:3.11-slim

WORKDIR /app

# Set environment variables to avoid encoding issues
ENV PYTHONUNBUFFERED=1
ENV PYTHONIOENCODING=utf-8

# Copy requirements first for better caching
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Install dependencies with better error handling
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY . .
Expand Down
6 changes: 3 additions & 3 deletions src/a2a/.env_automation
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ A2A_PORT=8001
A2A_LOG_LEVEL=INFO

# Base application URL for monitoring
BASE_APP_URL=https://zava-51c07969-app.azurewebsites.net
BASE_APP_URL=https://zava-89c29415-app.azurewebsites.net

# Azure monitoring integration
APPLICATION_INSIGHTS_CONNECTION_STRING=InstrumentationKey=3ecb7f2d-bf9b-4c15-973f-39e820e44b10;IngestionEndpoint=https://westus3-1.in.applicationinsights.azure.com/;LiveEndpoint=https://westus3.livediagnostics.monitor.azure.com/;ApplicationId=c47cdc80-ebeb-4b09-a7f5-4f9b6c9502dc
LOG_ANALYTICS_WORKSPACE_ID=d3733137-0fd4-48ea-ad35-e3d066ec4d0b
APPLICATION_INSIGHTS_CONNECTION_STRING=InstrumentationKey=db468090-243d-4b9c-8e5a-063f0e5f9ca6;IngestionEndpoint=https://westus3-1.in.applicationinsights.azure.com/;LiveEndpoint=https://westus3.livediagnostics.monitor.azure.com/;ApplicationId=f1a5d58e-12b6-4618-a3c9-c9ede48ab925
LOG_ANALYTICS_WORKSPACE_ID=fcb95690-218c-4e99-a3be-a552f4cf877d

# Automation features
ENABLE_PROCESS_MANAGEMENT=true
Expand Down
2 changes: 1 addition & 1 deletion src/a2a/status_automation.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ if () {

# Check automation endpoint
try {
= Invoke-RestMethod -Uri "https://zava-51c07969-app.azurewebsites.net/a2a/automation/status" -TimeoutSec 5
= Invoke-RestMethod -Uri "https://zava-89c29415-app.azurewebsites.net/a2a/automation/status" -TimeoutSec 5
Write-Host "Automation Status: "
} catch {
Write-Host "Automation endpoint not accessible"
Expand Down
5 changes: 1 addition & 4 deletions src/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,5 @@ websockets==13.1
jinja2==3.1.4
python-multipart==0.0.12
orjson==3.10.7
pydantic==2.10.4
pydantic==2.9.2
Pillow>=10.4.0

# Microsoft Agent Framework for A2A Protocol (Preview)
agent-framework-azure-ai --pre
2 changes: 0 additions & 2 deletions src/requirements_minimal.txt

This file was deleted.

4 changes: 2 additions & 2 deletions terraform-infrastructure/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ graph TD;

<!-- START BADGE -->
<div align="center">
<img src="https://img.shields.io/badge/Total%20views-1624-limegreen" alt="Total views">
<p>Refresh Date: 2025-12-03</p>
<img src="https://img.shields.io/badge/Total%20views-1696-limegreen" alt="Total views">
<p>Refresh Date: 2025-12-04</p>
</div>
<!-- END BADGE -->
176 changes: 114 additions & 62 deletions terraform-infrastructure/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,116 @@ resource "azurerm_container_registry_webhook" "webhook" {
]
}

# Standalone Docker Image Build - Always runs to ensure ACR has the required image
resource "null_resource" "docker_image_build" {
# Trigger rebuild when:
# 1. Dockerfile changes
# 2. Application source code changes
# 3. Requirements.txt changes
# 4. ACR or app changes
# 5. Force rebuild on every apply (always_run ensures terraform always executes the provisioner)
triggers = {
dockerfile_hash = local.dockerfile_hash
app_source_hash = local.app_source_hash
requirements_hash = fileexists("../src/requirements.txt") ? filesha256("../src/requirements.txt") : "missing"
acr_id = azurerm_container_registry.acr.id
always_run = timestamp() # Forces provisioner to run on every apply
}

depends_on = [
azurerm_container_registry.acr
]

provisioner "local-exec" {
command = <<-EOT
Write-Host ""
Write-Host "=========================================="
Write-Host "Building & Pushing Docker Image to ACR"
Write-Host "=========================================="
Write-Host ""

$ErrorActionPreference = "Continue" # Don't stop on warnings
cd ..
$srcPath = "src"

Write-Host "Starting Docker build and push to ACR..."
Write-Host "Registry: ${local.registry_name}"
Write-Host "Image: zava-chat-app:latest"
Write-Host "Dockerfile: $srcPath/Dockerfile"
Write-Host "Source Path: $srcPath"
Write-Host ""

# Set encoding for Azure CLI
$env:PYTHONIOENCODING = "utf-8"
chcp 65001 > $null

Write-Host "Executing ACR build command..."
Write-Host ""

try {
# Build and push image
az acr build `
--resource-group ${azurerm_resource_group.rg.name} `
--registry ${local.registry_name} `
--image zava-chat-app:latest `
--file "$srcPath\Dockerfile" `
"$srcPath" `
--no-logs

if ($LASTEXITCODE -eq 0) {
Write-Host ""
Write-Host "[SUCCESS] Docker image successfully built and pushed to ACR"
Write-Host ""
Write-Host "Image details:"
Write-Host " Registry: ${local.registry_name}.azurecr.io"
Write-Host " Repository: zava-chat-app"
Write-Host " Tag: latest"
Write-Host ""

# Wait for image to be available
Write-Host "Waiting for image to be available in registry..."
Start-Sleep -Seconds 10

# Verify image exists in ACR
Write-Host "Verifying image in ACR..."
$imgCheck = az acr repository show --name ${local.registry_name} --image zava-chat-app:latest --query "name" -o tsv 2>$null

if ($LASTEXITCODE -eq 0 -and $imgCheck -eq "zava-chat-app") {
Write-Host "[VERIFIED] Image confirmed in ACR registry"
Write-Host ""
exit 0
} else {
Write-Host "[WARNING] Image verification failed but build succeeded"
Write-Host "This may be a timing issue. Image should be available shortly."
Write-Host ""
exit 0
}
} else {
Write-Host ""
Write-Host "[ERROR] ACR build failed with exit code: $LASTEXITCODE"
Write-Host ""
Write-Host "Troubleshooting steps:"
Write-Host " 1. Check requirements.txt for dependency conflicts"
Write-Host " 2. Verify Dockerfile paths are correct"
Write-Host " 3. Manual build command:"
Write-Host " az acr build --resource-group ${azurerm_resource_group.rg.name} --registry ${local.registry_name} --image zava-chat-app:latest --file $srcPath\Dockerfile $srcPath"
Write-Host ""
exit 1
}
} catch {
Write-Host ""
Write-Host "[ERROR] Exception during build: $_"
Write-Host "Manual build command:"
Write-Host "az acr build --resource-group ${azurerm_resource_group.rg.name} --registry ${local.registry_name} --image zava-chat-app:latest --file $srcPath\Dockerfile $srcPath"
Write-Host ""
exit 1
}
EOT
interpreter = ["PowerShell", "-Command"]
working_dir = path.module
}
}

resource "azurerm_service_plan" "appserviceplan" {
name = local.app_service_plan
resource_group_name = azurerm_resource_group.rg.name
Expand Down Expand Up @@ -373,7 +483,8 @@ resource "azurerm_linux_web_app" "app" {

depends_on = [
azurerm_container_registry.acr,
null_resource.ai_model_deployments
null_resource.ai_model_deployments,
null_resource.docker_image_build
]
}

Expand Down Expand Up @@ -1677,68 +1788,9 @@ resource "null_resource" "deploy_multi_agents" {
}

Write-Host ""
Write-Host "Triggering container rebuild with agent configuration..."
cd ..
$srcPath = "src"
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$env:PYTHONIOENCODING = "utf-8"

Write-Host "Building container image in Azure Container Registry..."
Write-Host "This may take 2-3 minutes..."

# Build with logs enabled to see progress
$buildSuccess = $false
try {
az acr build `
--resource-group ${azurerm_resource_group.rg.name} `
--registry ${local.registry_name} `
--image zava-chat-app:latest `
--file "$srcPath\Dockerfile" `
"$srcPath"

if ($LASTEXITCODE -eq 0) {
Write-Host "[SUCCESS] ACR build completed successfully"
$buildSuccess = $true
} else {
Write-Host "[ERROR] ACR build failed with exit code: $LASTEXITCODE"
}
} catch {
Write-Host "[ERROR] ACR build exception: $_"
}

# Verify image exists
Write-Host ""
Write-Host "Verifying image in ACR..."
$imageExists = $false
for ($attempt = 1; $attempt -le 3; $attempt++) {
try {
$imgCheck = az acr repository show --name ${local.registry_name} --image zava-chat-app:latest --query "name" -o tsv 2>&1
if ($LASTEXITCODE -eq 0 -and $imgCheck -eq "zava-chat-app") {
Write-Host "[OK] Image verified in ACR: zava-chat-app:latest"
$imageExists = $true
break
}
} catch { }
if ($attempt -lt 3) {
Write-Host "Image not found yet, waiting 10s... (attempt $attempt/3)"
Start-Sleep -Seconds 10
}
}

if (-not $imageExists) {
Write-Host "[CRITICAL] Image not found in ACR after build. Web App cannot start."
Write-Host "Please check ACR build logs in Azure Portal."
exit 0 # Non-blocking but logged
}

# Web App will automatically pull image using managed identity (AcrPull role)
# No need to set ACR credentials - managed identity handles authentication
Write-Host ""
Write-Host "[INFO] Web App configured to use managed identity for ACR access"
Write-Host "[INFO] Webhook will trigger automatic deployment on image push"

Write-Host "Docker image already built by standalone resource."
Write-Host ""
Write-Host "Restarting Web App to pull new image..."
Write-Host "Restarting Web App to ensure latest configuration..."
az webapp restart --resource-group ${azurerm_resource_group.rg.name} --name ${local.web_app_name} | Out-Null
Write-Host "[OK] Web App restarted"
Write-Host ""
Expand Down