diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-01.md b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-01.md
index ad37a4839..6f4e83fe2 100644
--- a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-01.md
+++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-01.md
@@ -98,14 +98,16 @@ Select the assigned organization, then open the pinned microhack repository.
-
+
You then need to fork the repository before you can create a Codespace. To fork the repository, click the Fork button in the top-right corner of the repository page and follow the prompts:
-
+
+
Select the organization as owner and use a unique name for the repository name to avoid conflicts with other forks. For example, you can append your lab username to the repository name (e.g., `microhack-labuser-0001`):
+
Finally, you should see your forked repository with the unique name you provided and all files and folders from the original repository:
@@ -118,13 +120,13 @@ From the repository page, select **Code**, then open the **Codespaces** tab. Sel
-For Dev container configuration, select **Azure / AI / Predictive Maintenance**, then select **Create codespace**:
+For **Dev container configuration**, select **Azure / AI / Predictive Maintenance**, then select **Create codespace**:
Wait for the container setup to finish, then select the **Trust folders & Continue** button and confirm that the repository files are visible in the Explorer and that the integrated terminal opens without errors.
-
+
Open a terminal in the Codespace and verify that the required tools are installed:
@@ -144,6 +146,8 @@ Sign in to Azure from the Codespace terminal follow the link shown to authentica
az login --use-device-code
```
+In the **Select a subscription and tenant** terminal prompt hit enter to use the default Azure subscription
+
### 4. Retrieve environment configuration
From the repository root, run the setup script with the resource group name provided in your Hackbox under **Resource Group Name**:
@@ -186,6 +190,17 @@ az storage blob list \
The expected result is `5` wiki articles, one per machine type.
+### 6. Validate the Machine API
+
+Confirm that the provisioned Machine API in API Management can retrieve the seeded machine data:
+
+```bash
+# Get all machines
+curl -fsSL "$APIM_GATEWAY_URL/machine" -H "Ocp-Apim-Subscription-Key: $APIM_SUBSCRIPTION_KEY" -H "Accept: application/json"
+```
+
+You should receive a JSON response containing the factory machines. You will use this API when building the agents in Challenge 2.
+
## 🚀 Go Further
Review the [solution architecture](../README.md#architecture) and identify which Azure resource each of the five agents will use in the upcoming challenges.
diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-02.md b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-02.md
index f2c226a87..f869e817a 100644
--- a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-02.md
+++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-02.md
@@ -2,9 +2,6 @@
**[Home](../README.md)** | [Previous challenge](challenge-01.md) | [Next challenge](challenge-03.md)
-> [!TIP]
-> Stuck on a step? See the [Challenge 2 walkthrough](../walkthrough/challenge-02/solution-02.md) for exact commands, expected output, and a validation checklist.
-
## 🎯 Objective
The goals for this challenge are:
@@ -145,9 +142,6 @@ Machine and threshold information is typically stored in a central system and ex
The Machine API and Maintenance API are already available in API Management and contain endpoints for getting details about a specific machine and thresholds for certain machine types. Try the APIs:
```bash
-# Get all machines
-curl -fsSL "$APIM_GATEWAY_URL/machine" -H "Ocp-Apim-Subscription-Key: $APIM_SUBSCRIPTION_KEY" -H "Accept: application/json"
-
# Get a specific machine
curl -fsSL "$APIM_GATEWAY_URL/machine/machine-001" -H "Ocp-Apim-Subscription-Key: $APIM_SUBSCRIPTION_KEY" -H "Accept: application/json"
diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-03.md b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-03.md
index 3c9c1b25b..5d383b5a1 100644
--- a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-03.md
+++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-03.md
@@ -2,9 +2,6 @@
**[Home](../README.md)** | [Previous challenge](challenge-02.md) | [Next challenge](challenge-04.md)
-> [!TIP]
-> Stuck on a step? See the [Challenge 3 walkthrough](../walkthrough/challenge-03/solution-03.md) for exact commands, expected output, and a validation checklist.
-
## 🎯 Objective
The goals for this challenge are:
diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-04.md b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-04.md
index 9df7afb1c..8ec390c74 100644
--- a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-04.md
+++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-04.md
@@ -2,9 +2,6 @@
**[Home](../README.md)** | [Previous challenge](challenge-03.md) | [Next challenge](challenge-05.md)
-> [!TIP]
-> Stuck on a step? See the [Challenge 4 walkthrough](../walkthrough/challenge-04/solution-04.md) for exact commands, expected output, and a validation checklist.
-
## 🎯 Objective
The goals for this challenge are:
diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-05.md b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-05.md
index e1b3b6b8f..617ed02a9 100644
--- a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-05.md
+++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-05.md
@@ -2,9 +2,6 @@
**[Home](../README.md)** | [Previous challenge](challenge-04.md) | [Next: Wrap-up](finish.md)
-> [!TIP]
-> Stuck on a step? See the [Challenge 5 walkthrough](../walkthrough/challenge-05/solution-05.md) for exact commands, expected output, and a validation checklist.
-
## 🎯 Objective
The goals for this challenge are:
@@ -104,6 +101,10 @@ This challenge uses the **Sequential** pattern — see [Conclusion and Reflectio
### Task 1: Start Aspire
+The Python app uses its own virtual environment with Python 3.13, pinned by
+`src/agent-workflow/app/.python-version`. This is separate from the workshop's
+Python 3.11 environment; `uv` selects the pinned interpreter automatically.
+
```bash
cd src/agent-workflow
aspire run
diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/labautomation/README.md b/03-Azure/01-04-AI/08_Predictive_Maintenance/labautomation/README.md
index 87861e6c5..8adf91e55 100644
--- a/03-Azure/01-04-AI/08_Predictive_Maintenance/labautomation/README.md
+++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/labautomation/README.md
@@ -16,6 +16,9 @@ labautomation/
`-- get-keys.sh # Participant-run script: resolves resource names/keys into a repo-root .env
```
+The generated `.env` uses `AZURE_AI_PROJECT_ENDPOINT` for the Foundry project endpoint
+across the agents and workflow.
+
## What `main.bicep` provisions
- Storage account with a `machine-wiki` blob container (knowledge base articles).
diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.gitignore b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.gitignore
new file mode 100644
index 000000000..732f7db1a
--- /dev/null
+++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.gitignore
@@ -0,0 +1 @@
+!.python-version
diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.python-version b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.python-version
new file mode 100644
index 000000000..24ee5b1be
--- /dev/null
+++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.python-version
@@ -0,0 +1 @@
+3.13
diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/agents.py b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/agents.py
index 4118be45c..2c6fc52bb 100644
--- a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/agents.py
+++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/agents.py
@@ -38,7 +38,7 @@ def extract_work_order_id(text: str) -> str | None:
logger.info(f"COSMOS_ENDPOINT set: {bool(os.getenv('COSMOS_ENDPOINT'))}")
logger.info(f"COSMOS_DATABASE set: {bool(os.getenv('COSMOS_DATABASE'))}")
logger.info(
- f"AI_FOUNDRY_PROJECT_ENDPOINT set: {bool(os.getenv('AI_FOUNDRY_PROJECT_ENDPOINT'))}")
+ f"AZURE_AI_PROJECT_ENDPOINT set: {bool(os.getenv('AZURE_AI_PROJECT_ENDPOINT'))}")
# =============================================================================
@@ -141,8 +141,7 @@ async def execute(self, context: RequestContext, event_queue: EventQueue) -> Non
cosmos_key = os.getenv("COSMOS_KEY")
database_name = os.getenv(
"COSMOS_DATABASE_NAME") or os.getenv("COSMOS_DATABASE")
- project_endpoint = os.getenv("AI_FOUNDRY_PROJECT_ENDPOINT") or os.getenv(
- "AZURE_AI_PROJECT_ENDPOINT")
+ project_endpoint = os.getenv("AZURE_AI_PROJECT_ENDPOINT")
deployment_name = os.getenv("MODEL_DEPLOYMENT_NAME", "gpt-5.4")
if not all([cosmos_endpoint, cosmos_key, database_name, project_endpoint]):
@@ -305,8 +304,7 @@ async def execute(self, context: RequestContext, event_queue: EventQueue) -> Non
cosmos_key = os.getenv("COSMOS_KEY")
database_name = os.getenv(
"COSMOS_DATABASE_NAME") or os.getenv("COSMOS_DATABASE")
- project_endpoint = os.getenv("AI_FOUNDRY_PROJECT_ENDPOINT") or os.getenv(
- "AZURE_AI_PROJECT_ENDPOINT")
+ project_endpoint = os.getenv("AZURE_AI_PROJECT_ENDPOINT")
deployment_name = os.getenv("MODEL_DEPLOYMENT_NAME", "gpt-5.4")
if not all([cosmos_endpoint, cosmos_key, database_name, project_endpoint]):
diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/maintenance_scheduler_agent.py b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/maintenance_scheduler_agent.py
index 66e1041b2..f38a1bf5a 100644
--- a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/maintenance_scheduler_agent.py
+++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/maintenance_scheduler_agent.py
@@ -300,11 +300,11 @@ async def main():
print("=== Predictive Maintenance Agent ===\n")
- # Load configuration (use AI_FOUNDRY_PROJECT_ENDPOINT for consistency with other challenge scripts)
+ # Load configuration
cosmos_endpoint = os.getenv("COSMOS_ENDPOINT")
cosmos_key = os.getenv("COSMOS_KEY")
database_name = os.getenv("COSMOS_DATABASE_NAME")
- foundry_project_endpoint = os.getenv("AI_FOUNDRY_PROJECT_ENDPOINT")
+ foundry_project_endpoint = os.getenv("AZURE_AI_PROJECT_ENDPOINT")
deployment_name = os.getenv("MODEL_DEPLOYMENT_NAME", "gpt-5.4")
otel_exporter_endpoint = os.getenv(
"OTEL_EXPORTER_OTLP_ENDPOINT")
@@ -312,7 +312,7 @@ async def main():
# Validate
if not all([cosmos_endpoint, cosmos_key, database_name, foundry_project_endpoint]):
print("Error: Missing required environment variables.")
- print("Required: COSMOS_ENDPOINT, COSMOS_KEY, COSMOS_DATABASE_NAME, AI_FOUNDRY_PROJECT_ENDPOINT")
+ print("Required: COSMOS_ENDPOINT, COSMOS_KEY, COSMOS_DATABASE_NAME, AZURE_AI_PROJECT_ENDPOINT")
return
if otel_exporter_endpoint:
diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/parts_ordering_agent.py b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/parts_ordering_agent.py
index 10e36cab4..1c2648cb8 100644
--- a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/parts_ordering_agent.py
+++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/parts_ordering_agent.py
@@ -283,14 +283,14 @@ async def main():
cosmos_endpoint = os.getenv("COSMOS_ENDPOINT")
cosmos_key = os.getenv("COSMOS_KEY")
database_name = os.getenv("COSMOS_DATABASE_NAME")
- foundry_project_endpoint = os.getenv("AI_FOUNDRY_PROJECT_ENDPOINT")
+ foundry_project_endpoint = os.getenv("AZURE_AI_PROJECT_ENDPOINT")
deployment_name = os.getenv("MODEL_DEPLOYMENT_NAME", "gpt-5.4")
otel_exporter_endpoint = os.getenv(
"OTEL_EXPORTER_OTLP_ENDPOINT")
if not all([cosmos_endpoint, cosmos_key, database_name, foundry_project_endpoint]):
print("Error: Missing required environment variables.")
- print("Required: COSMOS_ENDPOINT, COSMOS_KEY, COSMOS_DATABASE_NAME, AI_FOUNDRY_PROJECT_ENDPOINT")
+ print("Required: COSMOS_ENDPOINT, COSMOS_KEY, COSMOS_DATABASE_NAME, AZURE_AI_PROJECT_ENDPOINT")
return
if otel_exporter_endpoint: