From 4ca7c9991a12c34f51f9af66f8ad0c6b9dcb8e70 Mon Sep 17 00:00:00 2001 From: GitHub Actions Bot <> Date: Tue, 26 Aug 2025 18:00:09 +0000 Subject: [PATCH 01/34] Created WhatTheHack template stub --- xxx-AgenticAIApps/Coach/Lectures.pptx | Bin 0 -> 196287 bytes xxx-AgenticAIApps/Coach/README.md | 87 ++++++++++++++++ xxx-AgenticAIApps/Coach/Solution-00.md | 20 ++++ xxx-AgenticAIApps/Coach/Solution-01.md | 20 ++++ xxx-AgenticAIApps/Coach/Solution-02.md | 20 ++++ xxx-AgenticAIApps/Coach/Solution-03.md | 20 ++++ xxx-AgenticAIApps/Coach/Solution-04.md | 20 ++++ xxx-AgenticAIApps/Coach/Solution-05.md | 20 ++++ xxx-AgenticAIApps/Coach/Solution-06.md | 20 ++++ xxx-AgenticAIApps/Coach/Solution-07.md | 20 ++++ xxx-AgenticAIApps/Coach/Solution-08.md | 20 ++++ xxx-AgenticAIApps/Coach/Solution-09.md | 20 ++++ xxx-AgenticAIApps/Coach/Solutions/.gitkeep | 0 xxx-AgenticAIApps/README.md | 48 +++++++++ xxx-AgenticAIApps/Student/Challenge-00.md | 100 +++++++++++++++++++ xxx-AgenticAIApps/Student/Challenge-01.md | 99 ++++++++++++++++++ xxx-AgenticAIApps/Student/Challenge-02.md | 99 ++++++++++++++++++ xxx-AgenticAIApps/Student/Challenge-03.md | 99 ++++++++++++++++++ xxx-AgenticAIApps/Student/Challenge-04.md | 99 ++++++++++++++++++ xxx-AgenticAIApps/Student/Challenge-05.md | 99 ++++++++++++++++++ xxx-AgenticAIApps/Student/Challenge-06.md | 99 ++++++++++++++++++ xxx-AgenticAIApps/Student/Challenge-07.md | 99 ++++++++++++++++++ xxx-AgenticAIApps/Student/Challenge-08.md | 99 ++++++++++++++++++ xxx-AgenticAIApps/Student/Challenge-09.md | 99 ++++++++++++++++++ xxx-AgenticAIApps/Student/Resources/.gitkeep | 0 25 files changed, 1326 insertions(+) create mode 100644 xxx-AgenticAIApps/Coach/Lectures.pptx create mode 100644 xxx-AgenticAIApps/Coach/README.md create mode 100644 xxx-AgenticAIApps/Coach/Solution-00.md create mode 100644 xxx-AgenticAIApps/Coach/Solution-01.md create mode 100644 xxx-AgenticAIApps/Coach/Solution-02.md create mode 100644 xxx-AgenticAIApps/Coach/Solution-03.md create mode 100644 xxx-AgenticAIApps/Coach/Solution-04.md create mode 100644 xxx-AgenticAIApps/Coach/Solution-05.md create mode 100644 xxx-AgenticAIApps/Coach/Solution-06.md create mode 100644 xxx-AgenticAIApps/Coach/Solution-07.md create mode 100644 xxx-AgenticAIApps/Coach/Solution-08.md create mode 100644 xxx-AgenticAIApps/Coach/Solution-09.md create mode 100644 xxx-AgenticAIApps/Coach/Solutions/.gitkeep create mode 100644 xxx-AgenticAIApps/README.md create mode 100644 xxx-AgenticAIApps/Student/Challenge-00.md create mode 100644 xxx-AgenticAIApps/Student/Challenge-01.md create mode 100644 xxx-AgenticAIApps/Student/Challenge-02.md create mode 100644 xxx-AgenticAIApps/Student/Challenge-03.md create mode 100644 xxx-AgenticAIApps/Student/Challenge-04.md create mode 100644 xxx-AgenticAIApps/Student/Challenge-05.md create mode 100644 xxx-AgenticAIApps/Student/Challenge-06.md create mode 100644 xxx-AgenticAIApps/Student/Challenge-07.md create mode 100644 xxx-AgenticAIApps/Student/Challenge-08.md create mode 100644 xxx-AgenticAIApps/Student/Challenge-09.md create mode 100644 xxx-AgenticAIApps/Student/Resources/.gitkeep diff --git a/xxx-AgenticAIApps/Coach/Lectures.pptx b/xxx-AgenticAIApps/Coach/Lectures.pptx new file mode 100644 index 0000000000000000000000000000000000000000..34cfe52f45a056e33791ebf176cee017e41362e0 GIT binary patch literal 196287 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�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%0A2O;OS!shB_ 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 J40sEG@;^hlltKUi literal 0 HcmV?d00001 diff --git a/xxx-AgenticAIApps/Coach/README.md b/xxx-AgenticAIApps/Coach/README.md new file mode 100644 index 0000000000..5b01b77354 --- /dev/null +++ b/xxx-AgenticAIApps/Coach/README.md @@ -0,0 +1,87 @@ +# What The Hack - AgenticAIApps - Coach Guide + +## Introduction + +Welcome to the coach's guide for the AgenticAIApps What The Hack. Here you will find links to specific guidance for coaches for each of the challenges. + +This hack includes an optional [lecture presentation](Lectures.pptx) that features short presentations to introduce key topics associated with each challenge. It is recommended that the host present each short presentation before attendees kick off that challenge. + +**NOTE:** If you are a Hackathon participant, this is the answer guide. Don't cheat yourself by looking at these during the hack! Go learn something. :) + +## Coach's Guides + +- Challenge 00: **[Prerequisites - Ready, Set, GO!](./Solution-00.md)** + - Prepare your workstation to work with Azure. +- Challenge 01: **[Title of Challenge](./Solution-01.md)** + - Description of challenge +- Challenge 02: **[Title of Challenge](./Solution-02.md)** + - Description of challenge +- Challenge 03: **[Title of Challenge](./Solution-03.md)** + - Description of challenge +- Challenge 04: **[Title of Challenge](./Solution-04.md)** + - Description of challenge +- Challenge 05: **[Title of Challenge](./Solution-05.md)** + - Description of challenge +- Challenge 06: **[Title of Challenge](./Solution-06.md)** + - Description of challenge +- Challenge 07: **[Title of Challenge](./Solution-07.md)** + - Description of challenge +- Challenge 08: **[Title of Challenge](./Solution-08.md)** + - Description of challenge +- Challenge 09: **[Title of Challenge](./Solution-09.md)** + - Description of challenge + +## Coach Prerequisites + +This hack has pre-reqs that a coach is responsible for understanding and/or setting up BEFORE hosting an event. Please review the [What The Hack Hosting Guide](https://aka.ms/wthhost) for information on how to host a hack event. + +The guide covers the common preparation steps a coach needs to do before any What The Hack event, including how to properly configure Microsoft Teams. + +### Student Resources + +Before the hack, it is the Coach's responsibility to download and package up the contents of the `/Student/Resources` folder of this hack into a "Resources.zip" file. The coach should then provide a copy of the Resources.zip file to all students at the start of the hack. + +Always refer students to the [What The Hack website](https://aka.ms/wth) for the student guide: [https://aka.ms/wth](https://aka.ms/wth) + +**NOTE:** Students should **not** be given a link to the What The Hack repo before or during a hack. The student guide does **NOT** have any links to the Coach's guide or the What The Hack repo on GitHub. + +### Additional Coach Prerequisites (Optional) + +_Please list any additional pre-event setup steps a coach would be required to set up such as, creating or hosting a shared dataset, or deploying a lab environment._ + +## Azure Requirements + +This hack requires students to have access to an Azure subscription where they can create and consume Azure resources. These Azure requirements should be shared with a stakeholder in the organization that will be providing the Azure subscription(s) that will be used by the students. + +_Please list Azure subscription requirements._ + +_For example:_ + +- Azure resources that will be consumed by a student implementing the hack's challenges +- Azure permissions required by a student to complete the hack's challenges. + +## Suggested Hack Agenda (Optional) + +_This section is optional. You may wish to provide an estimate of how long each challenge should take for an average squad of students to complete and/or a proposal of how many challenges a coach should structure each session for a multi-session hack event. For example:_ + +- Sample Day 1 + - Challenge 1 (1 hour) + - Challenge 2 (30 mins) + - Challenge 3 (2 hours) +- Sample Day 2 + - Challenge 4 (45 mins) + - Challenge 5 (1 hour) + - Challenge 6 (45 mins) + +## Repository Contents + +_The default files & folders are listed below. You may add to this if you want to specify what is in additional sub-folders you may add._ + +- `./Coach` + - Coach's Guide and related files +- `./Coach/Solutions` + - Solution files with completed example answers to a challenge +- `./Student` + - Student's Challenge Guide +- `./Student/Resources` + - Resource files, sample code, scripts, etc meant to be provided to students. (Must be packaged up by the coach and provided to students at start of event) diff --git a/xxx-AgenticAIApps/Coach/Solution-00.md b/xxx-AgenticAIApps/Coach/Solution-00.md new file mode 100644 index 0000000000..8ca1a44d71 --- /dev/null +++ b/xxx-AgenticAIApps/Coach/Solution-00.md @@ -0,0 +1,20 @@ +# Challenge 00 - - Coach's Guide + +**[Home](./README.md)** - [Next Solution >](./Solution-01.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-01.md b/xxx-AgenticAIApps/Coach/Solution-01.md new file mode 100644 index 0000000000..01d1e30c27 --- /dev/null +++ b/xxx-AgenticAIApps/Coach/Solution-01.md @@ -0,0 +1,20 @@ +# Challenge 01 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-00.md) - **[Home](./README.md)** - [Next Solution >](./Solution-02.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-02.md b/xxx-AgenticAIApps/Coach/Solution-02.md new file mode 100644 index 0000000000..1ef8ca5035 --- /dev/null +++ b/xxx-AgenticAIApps/Coach/Solution-02.md @@ -0,0 +1,20 @@ +# Challenge 02 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-01.md) - **[Home](./README.md)** - [Next Solution >](./Solution-03.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-03.md b/xxx-AgenticAIApps/Coach/Solution-03.md new file mode 100644 index 0000000000..9591196509 --- /dev/null +++ b/xxx-AgenticAIApps/Coach/Solution-03.md @@ -0,0 +1,20 @@ +# Challenge 03 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-02.md) - **[Home](./README.md)** - [Next Solution >](./Solution-04.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-04.md b/xxx-AgenticAIApps/Coach/Solution-04.md new file mode 100644 index 0000000000..90a770fdb3 --- /dev/null +++ b/xxx-AgenticAIApps/Coach/Solution-04.md @@ -0,0 +1,20 @@ +# Challenge 04 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-03.md) - **[Home](./README.md)** - [Next Solution >](./Solution-05.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-05.md b/xxx-AgenticAIApps/Coach/Solution-05.md new file mode 100644 index 0000000000..811c053840 --- /dev/null +++ b/xxx-AgenticAIApps/Coach/Solution-05.md @@ -0,0 +1,20 @@ +# Challenge 05 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-04.md) - **[Home](./README.md)** - [Next Solution >](./Solution-06.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-06.md b/xxx-AgenticAIApps/Coach/Solution-06.md new file mode 100644 index 0000000000..0100770cfa --- /dev/null +++ b/xxx-AgenticAIApps/Coach/Solution-06.md @@ -0,0 +1,20 @@ +# Challenge 06 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-05.md) - **[Home](./README.md)** - [Next Solution >](./Solution-07.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-07.md b/xxx-AgenticAIApps/Coach/Solution-07.md new file mode 100644 index 0000000000..d0dce03848 --- /dev/null +++ b/xxx-AgenticAIApps/Coach/Solution-07.md @@ -0,0 +1,20 @@ +# Challenge 07 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-06.md) - **[Home](./README.md)** - [Next Solution >](./Solution-08.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-08.md b/xxx-AgenticAIApps/Coach/Solution-08.md new file mode 100644 index 0000000000..dd606228fe --- /dev/null +++ b/xxx-AgenticAIApps/Coach/Solution-08.md @@ -0,0 +1,20 @@ +# Challenge 08 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-07.md) - **[Home](./README.md)** - [Next Solution >](./Solution-09.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-09.md b/xxx-AgenticAIApps/Coach/Solution-09.md new file mode 100644 index 0000000000..432a0bb9ad --- /dev/null +++ b/xxx-AgenticAIApps/Coach/Solution-09.md @@ -0,0 +1,20 @@ +# Challenge 09 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-08.md) - **[Home](./README.md)** + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AgenticAIApps/Coach/Solutions/.gitkeep b/xxx-AgenticAIApps/Coach/Solutions/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xxx-AgenticAIApps/README.md b/xxx-AgenticAIApps/README.md new file mode 100644 index 0000000000..b38bb41725 --- /dev/null +++ b/xxx-AgenticAIApps/README.md @@ -0,0 +1,48 @@ +# What The Hack - AgenticAIApps + +## Introduction + +The IoT Hack of the Century will take you on a whirlwind tour in the world of IoT and how it is being used in the modern world of mineral extraction in exotic locations like the Arctic and the wilds of South Africa. + +## Learning Objectives + +In this hack you will be solving the common business problem that companies in the mineral extraction industry face and how IoT solutions from Azure are brought to bare + +1. Provision an IoT Hub +2. Set up an IoT Edge device +3. Bring Azure Sphere to your solution for scale and resiliency + +## Challenges + +- Challenge 00: **[Prerequisites - Ready, Set, GO!](Student/Challenge-00.md)** + - Prepare your workstation to work with Azure. +- Challenge 01: **[Title of Challenge](Student/Challenge-01.md)** + - Description of challenge +- Challenge 02: **[Title of Challenge](Student/Challenge-02.md)** + - Description of challenge +- Challenge 03: **[Title of Challenge](Student/Challenge-03.md)** + - Description of challenge +- Challenge 04: **[Title of Challenge](Student/Challenge-04.md)** + - Description of challenge +- Challenge 05: **[Title of Challenge](Student/Challenge-05.md)** + - Description of challenge +- Challenge 06: **[Title of Challenge](Student/Challenge-06.md)** + - Description of challenge +- Challenge 07: **[Title of Challenge](Student/Challenge-07.md)** + - Description of challenge +- Challenge 08: **[Title of Challenge](Student/Challenge-08.md)** + - Description of challenge +- Challenge 09: **[Title of Challenge](Student/Challenge-09.md)** + - Description of challenge + +## Prerequisites + +- Your own Azure subscription with Owner access +- Visual Studio Code +- Azure CLI +- An AVNET X231 device + +## Contributors + +- Jane Q. Public +- Joe T. Muppet diff --git a/xxx-AgenticAIApps/Student/Challenge-00.md b/xxx-AgenticAIApps/Student/Challenge-00.md new file mode 100644 index 0000000000..843c24047a --- /dev/null +++ b/xxx-AgenticAIApps/Student/Challenge-00.md @@ -0,0 +1,100 @@ +# Challenge 00 - Prerequisites - Ready, Set, GO! + +**[Home](../README.md)** - [Next Challenge >](./Challenge-01.md) + +**_This is a template for "Challenge Zero" which focuses on getting prerequisites set up for the hack. The italicized text provides hints & examples of what should or should NOT go in each section._** + +**_We have included links to some common What The Hack pre-reqs in this template. All common prerequisite links go to the WTH-CommonPrerequisites page where there are more details on what each tool's purpose is._** + +**_You should remove any common pre-reqs that are not required for your hack. Then add additional pre-reqs that are required for your hack in the Description section below._** + +**_You should remove all italicized & sample text in this template and replace with your content._** + +## Introduction + +Thank you for participating in the AgenticAIApps What The Hack. Before you can hack, you will need to set up some prerequisites. + +## Common Prerequisites + +We have compiled a list of common tools and software that will come in handy to complete most What The Hack Azure-based hacks! + +You might not need all of them for the hack you are participating in. However, if you work with Azure on a regular basis, these are all things you should consider having in your toolbox. + +<!-- If you are editing this template manually, be aware that these links are only designed to work if this Markdown file is in the /xxx-HackName/Student/ folder of your hack. --> + +- [Azure Subscription](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-subscription) +- [Windows Subsystem for Linux](../../000-HowToHack/WTH-Common-Prerequisites.md#windows-subsystem-for-linux) +- [Managing Cloud Resources](../../000-HowToHack/WTH-Common-Prerequisites.md#managing-cloud-resources) + - [Azure Portal](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-portal) + - [Azure CLI](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cli) + - [Note for Windows Users](../../000-HowToHack/WTH-Common-Prerequisites.md#note-for-windows-users) + - [Azure PowerShell CmdLets](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-powershell-cmdlets) + - [Azure Cloud Shell](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cloud-shell) +- [Visual Studio Code](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code) + - [VS Code plugin for ARM Templates](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code-plugins-for-arm-templates) +- [Azure Storage Explorer](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-storage-explorer) + +## Description + +_This section should clearly state any additional prerequisite tools that need to be installed or set up in the Azure environment that the student will hack in._ + +_While ordered lists are generally not welcome in What The Hack challenge descriptions, you can use one here in Challenge Zero IF and only IF the steps you are asking the student to perform are not core to the learning objectives of the hack._ + +_For example, if the hack is on IoT Devices and you want the student to deploy an ARM/Bicep template that sets up the environment they will hack in without them needing to understand how ARM/Bicep templates work, you can provide step-by-step instructions on how to deploy the ARM/Bicep template._ + +_Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack. You should leave the sample text below in that refers to the Resources.zip file._ + +**\*NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resources.zip file provided by the coach.\* + +**\*NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.\* + +_Sample challenge zero text for the IoT Hack Of The Century:_ + +Now that you have the common pre-requisites installed on your workstation, there are prerequisites specifc to this hack. + +Your coach will provide you with a Resources.zip file that contains resources you will need to complete the hack. If you plan to work locally, you should unpack it on your workstation. If you plan to use the Azure Cloud Shell, you should upload it to the Cloud Shell and unpack it there. + +Please install these additional tools: + +- [Azure IoT Tools](https://marketplace.visualstudio.com/items?itemName=vsciot-vscode.azure-iot-tools) extension for Visual Studio Code +- .NET SDK 6.0 or later installed on your development machine. This can be downloaded from [here](https://www.microsoft.com/net/download/all) for multiple platforms. + +In the `/Challenge00/` folder of the Resources.zip file, you will find an ARM template, `setupIoTEnvironment.json` that sets up the initial hack environment in Azure you will work with in subsequent challenges. + +Please deploy the template by running the following Azure CLI commands from the location of the template file: +``` +az group create --name myIoT-rg --location eastus +az group deployment create -g myIoT-rg --name HackEnvironment -f setupIoTEnvironment.json +``` + +## Success Criteria + +_Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach._ + +_The success criteria should not be a list of instructions._ + +_Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."_ + +_Sample success criteria for the IoT prerequisites challenge:_ + +To complete this challenge successfully, you should be able to: + +- Verify that you have a bash shell with the Azure CLI available. +- Verify that the ARM template has deployed the following resources in Azure: + - Azure IoT Hub + - Virtual Network + - Jumpbox VM + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +_Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario._ + +**\*Note:** Use descriptive text for each link instead of just URLs.\* + +_Sample IoT resource links:_ + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) diff --git a/xxx-AgenticAIApps/Student/Challenge-01.md b/xxx-AgenticAIApps/Student/Challenge-01.md new file mode 100644 index 0000000000..fcf81ed831 --- /dev/null +++ b/xxx-AgenticAIApps/Student/Challenge-01.md @@ -0,0 +1,99 @@ +# Challenge 01 - <Title of Challenge> + +[< Previous Challenge](./Challenge-00.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-02.md) + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AgenticAIApps/Student/Challenge-02.md b/xxx-AgenticAIApps/Student/Challenge-02.md new file mode 100644 index 0000000000..459fb175d5 --- /dev/null +++ b/xxx-AgenticAIApps/Student/Challenge-02.md @@ -0,0 +1,99 @@ +# Challenge 02 - <Title of Challenge> + +[< Previous Challenge](./Challenge-01.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-03.md) + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AgenticAIApps/Student/Challenge-03.md b/xxx-AgenticAIApps/Student/Challenge-03.md new file mode 100644 index 0000000000..88656873ba --- /dev/null +++ b/xxx-AgenticAIApps/Student/Challenge-03.md @@ -0,0 +1,99 @@ +# Challenge 03 - <Title of Challenge> + +[< Previous Challenge](./Challenge-02.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-04.md) + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AgenticAIApps/Student/Challenge-04.md b/xxx-AgenticAIApps/Student/Challenge-04.md new file mode 100644 index 0000000000..a032304040 --- /dev/null +++ b/xxx-AgenticAIApps/Student/Challenge-04.md @@ -0,0 +1,99 @@ +# Challenge 04 - <Title of Challenge> + +[< Previous Challenge](./Challenge-03.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-05.md) + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AgenticAIApps/Student/Challenge-05.md b/xxx-AgenticAIApps/Student/Challenge-05.md new file mode 100644 index 0000000000..bc2fa34b49 --- /dev/null +++ b/xxx-AgenticAIApps/Student/Challenge-05.md @@ -0,0 +1,99 @@ +# Challenge 05 - <Title of Challenge> + +[< Previous Challenge](./Challenge-04.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-06.md) + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AgenticAIApps/Student/Challenge-06.md b/xxx-AgenticAIApps/Student/Challenge-06.md new file mode 100644 index 0000000000..59e43d9bae --- /dev/null +++ b/xxx-AgenticAIApps/Student/Challenge-06.md @@ -0,0 +1,99 @@ +# Challenge 06 - <Title of Challenge> + +[< Previous Challenge](./Challenge-05.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-07.md) + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AgenticAIApps/Student/Challenge-07.md b/xxx-AgenticAIApps/Student/Challenge-07.md new file mode 100644 index 0000000000..82cb7e727e --- /dev/null +++ b/xxx-AgenticAIApps/Student/Challenge-07.md @@ -0,0 +1,99 @@ +# Challenge 07 - <Title of Challenge> + +[< Previous Challenge](./Challenge-06.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-08.md) + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AgenticAIApps/Student/Challenge-08.md b/xxx-AgenticAIApps/Student/Challenge-08.md new file mode 100644 index 0000000000..4fffe19429 --- /dev/null +++ b/xxx-AgenticAIApps/Student/Challenge-08.md @@ -0,0 +1,99 @@ +# Challenge 08 - <Title of Challenge> + +[< Previous Challenge](./Challenge-07.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-09.md) + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AgenticAIApps/Student/Challenge-09.md b/xxx-AgenticAIApps/Student/Challenge-09.md new file mode 100644 index 0000000000..8f01390dc7 --- /dev/null +++ b/xxx-AgenticAIApps/Student/Challenge-09.md @@ -0,0 +1,99 @@ +# Challenge 09 - <Title of Challenge> + +[< Previous Challenge](./Challenge-08.md) - **[Home](../README.md)** + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AgenticAIApps/Student/Resources/.gitkeep b/xxx-AgenticAIApps/Student/Resources/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 From b69c6dec6c05b6a1da0af01e7fbf15961f1a29c4 Mon Sep 17 00:00:00 2001 From: esvin2661 <eruiz005@my.wilmu.edu> Date: Tue, 26 Aug 2025 13:26:37 -0500 Subject: [PATCH 02/34] support for code spaces --- .../xxx-AgenticAIApps/devcontainer.json | 28 +++++++++++++++++++ .../Student/Resources/requirements.txt | 20 +++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 .devcontainer/xxx-AgenticAIApps/devcontainer.json create mode 100644 xxx-AgenticAIApps/Student/Resources/requirements.txt diff --git a/.devcontainer/xxx-AgenticAIApps/devcontainer.json b/.devcontainer/xxx-AgenticAIApps/devcontainer.json new file mode 100644 index 0000000000..0830a73768 --- /dev/null +++ b/.devcontainer/xxx-AgenticAIApps/devcontainer.json @@ -0,0 +1,28 @@ +{ + "name" : "xxx-AgenticAIApps", + "image": "mcr.microsoft.com/devcontainers/python:3.11", + "workspaceFolder": "/workspace/066-OpenAIFundamentals/Student/Resources", + "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached", + "hostRequirements": { + "cpus": 2 + }, + "waitFor": "onCreateCommand", + "updateContentCommand": "python3 -m pip install -r requirements.txt", + "postCreateCommand": "", + "features": { + "ghcr.io/devcontainers/features/azure-cli:1": { + "installBicep": true + } + }, + "customizations": { + "codespaces": { + "openFiles": [] + }, + "vscode": { + "extensions": [ + "ms-toolsai.jupyter", + "ms-python.python" + ] + } + } + } diff --git a/xxx-AgenticAIApps/Student/Resources/requirements.txt b/xxx-AgenticAIApps/Student/Resources/requirements.txt new file mode 100644 index 0000000000..4963271651 --- /dev/null +++ b/xxx-AgenticAIApps/Student/Resources/requirements.txt @@ -0,0 +1,20 @@ +azure-ai-agents==1.0.2 +azure-ai-projects==1.0.0 +azure-core==1.35.0 +azure-identity==1.23.1 +azure-storage-blob==12.26.0 +certifi==2025.8.3 +cffi==1.17.1 +charset-normalizer==3.4.2 +cryptography==45.0.5 +idna==3.10 +isodate==0.7.2 +msal==1.33.0 +msal-extensions==1.3.1 +pycparser==2.22 +PyJWT==2.10.1 +requests==2.32.4 +six==1.17.0 +typing_extensions==4.14.1 +urllib3==2.5.0 +azure-monitor-query==1.0.0b4 \ No newline at end of file From c5412ea4a84ac2f83885fea227a23304596b8deb Mon Sep 17 00:00:00 2001 From: esvin2661 <eruiz005@my.wilmu.edu> Date: Tue, 26 Aug 2025 13:32:10 -0500 Subject: [PATCH 03/34] update codespace --- .devcontainer/xxx-AgenticAIApps/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/xxx-AgenticAIApps/devcontainer.json b/.devcontainer/xxx-AgenticAIApps/devcontainer.json index 0830a73768..d68c02c016 100644 --- a/.devcontainer/xxx-AgenticAIApps/devcontainer.json +++ b/.devcontainer/xxx-AgenticAIApps/devcontainer.json @@ -1,7 +1,7 @@ { "name" : "xxx-AgenticAIApps", "image": "mcr.microsoft.com/devcontainers/python:3.11", - "workspaceFolder": "/workspace/066-OpenAIFundamentals/Student/Resources", + "workspaceFolder": "/workspace/xxx-AgenticAIApps/Student/Resources", "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached", "hostRequirements": { "cpus": 2 From ab9859f74bc5f4d90c1354d6b53a512663392a79 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <eruiz005@wilmu.edu> Date: Thu, 16 Oct 2025 05:47:07 -0400 Subject: [PATCH 04/34] Update Coach Solutions and Guide --- xxx-AgenticAIApps/Coach/README.md | 13 ++ xxx-AgenticAIApps/Coach/Solution-00.md | 126 +++++++++++++-- xxx-AgenticAIApps/Coach/Solution-01.md | 196 +++++++++++++++++++++-- xxx-AgenticAIApps/Coach/Solution-02.md | 152 ++++++++++++++++-- xxx-AgenticAIApps/Coach/Solution-03.md | 138 +++++++++++++++-- xxx-AgenticAIApps/Coach/Solution-04.md | 134 ++++++++++++++-- xxx-AgenticAIApps/Coach/Solution-05.md | 135 ++++++++++++++-- xxx-AgenticAIApps/Coach/Solution-06.md | 153 ++++++++++++++++-- xxx-AgenticAIApps/Coach/Solution-07.md | 183 ++++++++++++++++++++-- xxx-AgenticAIApps/Coach/Solution-08.md | 206 +++++++++++++++++++++++-- xxx-AgenticAIApps/Coach/Solution-09.md | 20 --- 11 files changed, 1330 insertions(+), 126 deletions(-) diff --git a/xxx-AgenticAIApps/Coach/README.md b/xxx-AgenticAIApps/Coach/README.md index 5b01b77354..5c1b64670d 100644 --- a/xxx-AgenticAIApps/Coach/README.md +++ b/xxx-AgenticAIApps/Coach/README.md @@ -8,6 +8,10 @@ This hack includes an optional [lecture presentation](Lectures.pptx) that featur **NOTE:** If you are a Hackathon participant, this is the answer guide. Don't cheat yourself by looking at these during the hack! Go learn something. :) +## Learning Objectives + +This project is designed to teach participants how to build agentic applications using Azure’s AI ecosystem. It begins with setting up a cloud-native development environment through GitHub Codespaces and Azure AI Foundry, eliminating local setup and streamlining access to cloud resources. Learners will orchestrate intelligent agents using Semantic Kernel, implement secure communication protocols like Agent2Agent (A2A), and deploy multi-agent workflows with live metric integration via Azure Monitor. The experience is grounded in hands-on development with Python, and optionally enhanced with a Flask-based UI for visualizing agent interactions. By the end, participants will be equipped to design, deploy, and manage scalable, secure, and collaborative AI agents in real-world scenarios. + ## Coach's Guides - Challenge 00: **[Prerequisites - Ready, Set, GO!](./Solution-00.md)** @@ -37,6 +41,12 @@ This hack has pre-reqs that a coach is responsible for understanding and/or sett The guide covers the common preparation steps a coach needs to do before any What The Hack event, including how to properly configure Microsoft Teams. +**Required Prerequisites:** +- Python (Version 3.7 or higher, Python 3.13 preferred) +- Pip (package installer for Python) +- Active Azure Subscription +- Azure Developer CLI + ### Student Resources Before the hack, it is the Coach's responsibility to download and package up the contents of the `/Student/Resources` folder of this hack into a "Resources.zip" file. The coach should then provide a copy of the Resources.zip file to all students at the start of the hack. @@ -85,3 +95,6 @@ _The default files & folders are listed below. You may add to this if you want t - Student's Challenge Guide - `./Student/Resources` - Resource files, sample code, scripts, etc meant to be provided to students. (Must be packaged up by the coach and provided to students at start of event) + +## Contributors +- Esvin RUiz diff --git a/xxx-AgenticAIApps/Coach/Solution-00.md b/xxx-AgenticAIApps/Coach/Solution-00.md index 8ca1a44d71..156ce11038 100644 --- a/xxx-AgenticAIApps/Coach/Solution-00.md +++ b/xxx-AgenticAIApps/Coach/Solution-00.md @@ -1,20 +1,122 @@ -# Challenge 00 - <Title of Challenge> - Coach's Guide +# Challenge 00 - <Azure AI Foundry Onboarding & Environment Prep> - Coach's Guide -**[Home](./README.md)** - [Next Solution >](./Solution-01.md) +**[Home](./README.md)** - [Next Solution >](./Solution-00.md) + +```markdown +# Challenge 00 - Azure AI Foundry Onboarding & Environment Prep - Coach's Guide + +**[Home](./README.md)** - [Next Solution >](./Solution-00.md) ## Notes & Guidance -This is the only section you need to include. +This guide walks you through setting up your development environment and Azure subscription for working with Azure AI Foundry. It is designed to help coaches and participants prepare their cloud-based workspace for the challenges ahead. + +### Prerequisites + +- Python (Version 3.7 or higher, Python 3.13 preferred) +- Pip (package installer for Python) +- Active Azure Subscription +- Azure Developer CLI + +Reference documentation: +- [Azure AI Foundry Overview](https://learn.microsoft.com/en-us/azure/azure-ai-foundry/overview) + +--- + +### Create Azure AI Foundry Resource in Azure Account + +- Log in to your Azure portal +- Create a new Azure AI Foundry resource +- Note down your resource endpoint URL (you'll need this later) + +--- + +### Set Up GitHub Codespaces + +GitHub Codespaces provides a cloud-hosted development environment that eliminates the need for local setup. + +- Navigate to the project repository: + [Agentic AI Apps GitHub Repository](https://github.com/WhatTheHack/tree/xxx-AgenticAIApps) +- Click the green **Code** button and select **Codespaces > Create codespace on main** +- Wait for the environment to initialize. It will automatically install dependencies and configure your workspace. +- Use the integrated terminal to run commands and interact with Azure resources. +- Authenticate your Codespace CLI session with Azure by running: + + ```bash + az login + ``` + + - This will open a browser window to complete the login process + - Once authenticated, your Codespace CLI will be connected to your Azure subscription + +--- + +### Install Required Packages + +Once your Codespace is ready, open the terminal and run: + +```bash +pip install azure-ai-projects azure-identity +``` + +Verify installation: + +```bash +pip list +``` + +--- + +### Create a Virtual Machine with Permissions + +To support later stages of the project, you'll need a Linux-based virtual machine with read/write permissions. + +- Open the Azure Portal and navigate to **Virtual Machines** +- Click **Create > Virtual Machine** +- Use the following configuration: + - **Resource Group:** Same as your Azure AI Foundry project + - **Virtual Machine Name:** `agentic-vm-test` + - **Region:** West US 2 + - **Availability Zone:** Zone 1 + - **Image:** Ubuntu 22.04 LTS + - **Size:** Standard B2pts v2 (2 vCPUs, 1 GiB memory) + - **Authentication Type:** SSH public key + - **Inbound Ports:** Allow SSH (port 22) +- Click **Next: Disks** and accept the default settings +- Click **Next: Networking** and ensure the VM is assigned a public IP +- Click **Next: Management**, then enable **System Assigned Managed Identity** +- After deployment, go to **Access Control (IAM)** for the VM and assign the **Contributor** role + +> ⚠️ This VM is intended for testing purposes only. Do not use it for production workloads. + +--- + +### Repository Usage Notes + +The [Agentic AI Apps GitHub Repository](https://github.com/WhatTheHack/tree/xxx-AgenticAIApps) contains all the source code and configuration files needed for this challenge. + +- **Codespaces Ready:** Preconfigured for GitHub Codespacesβ€”launch and start coding immediately +- **Project Structure:** Each challenge is organized into its own folder. Start with `Challenge-01` +- **Auto-Setup:** Dependencies install automatically when the Codespace launches +- **Customization:** Modify `.devcontainer` files to adjust the environment +- **Sync with Azure:** Use the terminal to authenticate and interact with Foundry resources + +--- + +## Next Steps: +Your Azure AI Foundry development environment is now fully configured. +You’ve installed the required SDKs, authenticated with Azure, and confirmed that your workspace can register and run agents. + +Tip: Keep your `.env` and Foundry configuration handy β€” you’ll reuse them throughout every subsequent challenge. -Use general non-bulleted text for the beginning of a solution area for this challenge +--- -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets +Proceed to **[Challenge 001 – Semantic Kernel Setup & Configuration](./Solution-001.md)** to: +- Integrate **Semantic Kernel** for planning and reasoning. +- Explore how prompts, skills, and plugins form the cognitive layer of your agents. +- Learn how agents interpret natural language requests and turn them into structured actions. +- Prepare the foundation for multi-agent collaboration in future challenges. -Break things apart with more than one bullet list +--- -- Like this -- One -- Right -- Here +All sections marked with `πŸ”Ή STUDENT MISSING SECTION` are **what students were expected to implement themselves** in the student guide. Coaches can reference these for solution verification. diff --git a/xxx-AgenticAIApps/Coach/Solution-01.md b/xxx-AgenticAIApps/Coach/Solution-01.md index 01d1e30c27..91a54e8db7 100644 --- a/xxx-AgenticAIApps/Coach/Solution-01.md +++ b/xxx-AgenticAIApps/Coach/Solution-01.md @@ -1,20 +1,194 @@ -# Challenge 01 - <Title of Challenge> - Coach's Guide +# Challenge 01 - Semantic Kernel Setup & Configuration – Coach's Guide [< Previous Solution](./Solution-00.md) - **[Home](./README.md)** - [Next Solution >](./Solution-02.md) +--- + ## Notes & Guidance -This is the only section you need to include. +This guide walks coaches and participants through setting up Semantic Kernel using Azure OpenAI services inside GitHub Codespaces. It enables orchestration of intelligent agents for planning and task execution. + +--- + +### Environment Setup + +* Use **GitHub Codespaces** + + * Launch directly from the **Agentic AI Apps** GitHub repository. + * Dependencies install automatically when the Codespace initializes. + +--- + +### Secure Your Credentials + +* Create a `.env` file in your project root and add the following keys: + +```env +OPENAIAPIKEY=your-azure-openai-api-key +OPENAIENDPOINT=your-azure-openai-endpoint +OPENAIDEPLOYMENTNAME=your-model-deployment +OPENAIMODEL_NAME=gpt-4o +AZURE_SUBSCRIPTION_ID=your-subscription-id +AZURE_RESOURCE_GROUP=your-resource-group +AZURE_VM_NAME=your-vm-name +``` + +* Add `.env` to `.gitignore` to protect sensitive credentials. +* Avoid spaces around `=` β€” they prevent variables from loading correctly. + +--- + +### Kernel Initialization + +Create a file called `test_kernel.py`: + +```python +import os +import asyncio +from dotenv import load_dotenv +from semantic_kernel.kernel import Kernel +from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion + +load_dotenv() + +api_key = os.getenv("OPENAIAPIKEY") +endpoint = os.getenv("OPENAIENDPOINT") +deployment_name = os.getenv("OPENAIDEPLOYMENTNAME") + +kernel = Kernel() +kernel.add_service( + AzureChatCompletion( + service_id="chatcompletion", + deployment_name=deployment_name, + endpoint=endpoint, + api_key=api_key + ) +) + +# πŸ”Ή STUDENT MISSING SECTION: Prompt testing +async def run(): + result = await kernel.invoke_prompt_async("What is Semantic Kernel?") + print(result) + +asyncio.run(run()) +``` + +βœ… **Expected Output:** + +``` +"Semantic Kernel is an open-source SDK that lets you build AI-first apps..." +``` + +--- + +### Organize Your Skills + +Create a `skills/` folder to store Semantic Kernel plugins. Each skill should include: + +* `config.json` β€” defines the skill’s name, description, and inputs. +* `skprompt.txt` β€” contains the prompt template or logic. + +This structure lets you modularize functionality and invoke skills dynamically. + +Example skills: + +* `MonitorSkill` +* `AnomalySkill` +* `AzureMonitorSkill` *(new β€” for live data)* + +--- + +### Add a Live Azure Monitor Skill + +Create a file named `azure_monitor_skill.py` in the `skills/` folder: + +```python +import os +from azure.monitor.query import MetricsQueryClient +from azure.identity import DefaultAzureCredential +from dotenv import load_dotenv +from semantic_kernel.skill_definition import sk_function + +load_dotenv() + +class AzureMonitorSkill: + def __init__(self): + self.credential = DefaultAzureCredential() + self.client = MetricsQueryClient(self.credential) + self.subscription_id = os.getenv("AZURE_SUBSCRIPTION_ID") + self.resource_group = os.getenv("AZURE_RESOURCE_GROUP") + self.vm_name = os.getenv("AZURE_VM_NAME") + + # πŸ”Ή STUDENT MISSING SECTION: Function to retrieve CPU metric + @sk_function(name="get_vm_cpu", description="Retrieve current CPU usage for a VM") + def get_vm_cpu(self) -> str: + resource_id = ( + f"/subscriptions/{self.subscription_id}/resourceGroups/" + f"{self.resource_group}/providers/Microsoft.Compute/virtualMachines/{self.vm_name}" + ) + + response = self.client.query_resource( + resource_id=resource_id, + metric_names=["Percentage CPU"], + timespan="PT1H" + ) + + for metric in response.metrics: + if metric.timeseries and metric.timeseries[0].data: + last_point = metric.timeseries[0].data[-1] + if last_point.average is not None: + return f"Current CPU usage: {last_point.average:.2f}%" + + return "No CPU data available." +``` + +Then register it inside your main kernel file (`test_kernel.py`): + +```python +# πŸ”Ή STUDENT MISSING SECTION: Skill registration +from skills.azure_monitor_skill import AzureMonitorSkill + +kernel.import_skill(AzureMonitorSkill(), "azure_monitor") + +async def run(): + cpu_data = await kernel.skills.azure_monitor.get_vm_cpu() + print(cpu_data) +``` + +**Expected Output (example):** + +``` +Current CPU usage: 21.43% +``` + +--- + +### Why This Matters + +By connecting Semantic Kernel to Azure Monitor: + +* Agents can react to **live telemetry** instead of mock anomalies. +* Lays the foundation for Challenge 02, where your **Anomaly Detector Agent** will use these metrics for proactive monitoring. +* Aligns Foundry agents with **real Azure resources**, enabling autonomous cloud management. + +--- + +### Next Steps + +After completing this setup, your agents can interpret, plan, and act on **real data** within your Azure environment. + +--- + +Proceed to **[Challenge 02 – Build the Anomaly Detector Agent (Real Azure Metrics)](./Solution-02.md)** to: + +* Connect your Semantic Kernel agents to **Azure Monitor metrics**. +* Detect real-time anomalies in **CPU, memory, and disk I/O**. +* Trigger optimization and orchestration flows using **live telemetry**. +* Build a foundation for intelligent, self-healing cloud agents. -Use general non-bulleted text for the beginning of a solution area for this challenge +🧩 *Keep your Azure credentials and Foundry session active β€” Challenge 02 builds directly on this configuration.* -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets +--- -Break things apart with more than one bullet list +All sections marked with `πŸ”Ή STUDENT MISSING SECTION` are **what students were expected to implement themselves** in the student guide. Coaches can reference these for solution verification. -- Like this -- One -- Right -- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-02.md b/xxx-AgenticAIApps/Coach/Solution-02.md index 1ef8ca5035..39506e6930 100644 --- a/xxx-AgenticAIApps/Coach/Solution-02.md +++ b/xxx-AgenticAIApps/Coach/Solution-02.md @@ -1,20 +1,148 @@ -# Challenge 02 - <Title of Challenge> - Coach's Guide +````markdown +# Challenge 2 - Build the Anomaly Detector Agent (Real Azure Metrics) - Coach's Guide -[< Previous Solution](./Solution-01.md) - **[Home](./README.md)** - [Next Solution >](./Solution-03.md) +[< Previous Solution](./Solution-02.0.md) - **[Home](../README.md)** - [Next Solution >](./Solution-04.md) ## Notes & Guidance -This is the only section you need to include. +This guide walks coaches and participants through building an agent that monitors real-time Azure metrics and detects anomalies in system performance. It introduces Azure Monitor integration and agentic alerting logic. -Use general non-bulleted text for the beginning of a solution area for this challenge +--- -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets +### Environment Setup -Break things apart with more than one bullet list +- Use GitHub Codespaces + Required packages install automatically when the Codespace initializes: + +```bash +pip install azure-monitor-query azure-identity python-dotenv +```` + +* Create a `.env` file in your project root + Include the following keys: + +```env +AZURESUBSCRIPTIONID=your-subscription-id +AZURERESOURCEGROUP=your-resource-group +AZURERESOURCENAME=your-vm-name +AZURE_METRICS=Percentage CPU,Available Memory Bytes,Disk Read Bytes/sec +``` + +> **Tip:** Add `.env` to `.gitignore` to protect credentials. + +--- + +### Agent Initialization + +Create a file called `anomaly_detector.py` and define the agent: + +```python +import os +from azure.identity import DefaultAzureCredential +from azure.monitor.query import MetricsQueryClient +from azure.monitor.query.models import MetricAggregationType +from azure.ai.foundry import Agent, Message, Thread +from dotenv import load_dotenv +from datetime import timedelta + +load_dotenv() + +class AnomalyDetectorAgent(Agent): + def init(self): + super().init(name="anomaly-detector") + self.client = MetricsQueryClient(credential=DefaultAzureCredential()) + self.resource_id = ( + f"/subscriptions/{os.getenv('AZURESUBSCRIPTIONID')}" + f"/resourceGroups/{os.getenv('AZURERESOURCEGROUP')}" + f"/providers/Microsoft.Compute/virtualMachines/{os.getenv('AZURERESOURCENAME')}" + ) + self.metrics = [m.strip() for m in os.getenv("AZURE_METRICS").split(",")] + + # πŸ”Ή STUDENT MISSING SECTION: Retrieve latest metric + def get_latest_metric(self, metric_name): + response = self.client.query_resource( + resource_uri=self.resource_id, + metric_names=[metric_name], + timespan=timedelta(minutes=5), + aggregations=[MetricAggregationType.AVERAGE] + ) + for metric in response.metrics: + for timeseries in metric.timeseries: + for data in timeseries.data: + if data.average is not None: + return data.average + return None + + # πŸ”Ή STUDENT MISSING SECTION: Run method to check for anomalies + def run(self, thread: Thread, message: Message): + anomalies = [] + for metric in self.metrics: + value = self.get_latest_metric(metric) + print(f"{metric}: {value}") + if value is None: + continue + if ( + ("CPU" in metric and value > 75) or + ("Memory" in metric and value < 1e9) or + ("Disk" in metric and value > 5e7) + ): + anomalies.append(f"{metric} = {value}") + + if anomalies: + alert = "⚠️ Anomalies detected:\n" + "\n".join(anomalies) + thread.send_message(Message(content=alert, role="agent")) + else: + print("No anomalies detected.") +``` + +--- + +### Register and Test the Agent + +#### Register the Agent + +```python +# register_anomaly.py +from azure.ai.foundry import AgentClient +from anomaly_detector import AnomalyDetectorAgent + +client = AgentClient() +agent = AnomalyDetectorAgent() +client.register_agent(agent) +``` + +Run: + +```bash +python register_anomaly.py +``` + +#### Test the Agent + +```python +# test_anomaly.py +from azure.ai.foundry import AgentClient + +client = AgentClient() +thread = client.create_thread() +client.send_message(thread.id, "Run anomaly check", agent_name="anomaly-detector") +``` + +Run: + +```bash +python test_anomaly.py +``` + +Expected output: Real metric values printed and alerts triggered if thresholds are exceeded. + +--- + +### Next Steps + +Proceed to Challenge 03 to build a **Resource Optimizer Agent** that responds to anomalies and simulates Azure-based optimizations. + +--- + +All sections marked with `πŸ”Ή STUDENT MISSING SECTION` are **what students were expected to implement themselves** in the student guide. Coaches can reference these for solution verification. -- Like this -- One -- Right -- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-03.md b/xxx-AgenticAIApps/Coach/Solution-03.md index 9591196509..2e4b8e3340 100644 --- a/xxx-AgenticAIApps/Coach/Solution-03.md +++ b/xxx-AgenticAIApps/Coach/Solution-03.md @@ -1,20 +1,134 @@ -# Challenge 03 - <Title of Challenge> - Coach's Guide +````markdown +# Challenge 03 - Build the Resource Optimizer Agent (Real Azure Integration) - Coach's Guide -[< Previous Solution](./Solution-02.md) - **[Home](./README.md)** - [Next Solution >](./Solution-04.md) +[< Previous Solution](./Solution-02.md) - **[Home](../README.md)** - [Next Solution >](./Solution-04.md) ## Notes & Guidance -This is the only section you need to include. +In this challenge, participants create a **Resource Optimizer Agent** that responds to anomalies detected by the Anomaly Detector Agent and performs simulated or real Azure optimizations. +The agent demonstrates integration between **Semantic Kernel**, **Azure Monitor**, and the **Azure Management SDK**. -Use general non-bulleted text for the beginning of a solution area for this challenge +--- -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets +### Environment Setup + +- Provision a Linux VM (`agentic-vm-test`) with **Contributor permissions** to ensure read/write access. +- Install required SDKs: + +```bash +pip install azure-mgmt-compute azure-identity python-dotenv +```` + +* `.env` file should include: + +```env +AZURESUBSCRIPTIONID=your-subscription-id +AZURERESOURCEGROUP=your-resource-group +AZUREVMNAME=your-vm-name +``` + +> Ensure your VM has **read/write permissions** β€” necessary for optimization actions. + +--- + +### Create the Resource Optimizer Agent + +Create `resource_optimizer.py`: + +```python +import os +from azure.identity import DefaultAzureCredential +from azure.mgmt.compute import ComputeManagementClient +from azure.ai.foundry import Agent, Message, Thread +from dotenv import load_dotenv + +load_dotenv() + +class ResourceOptimizerAgent(Agent): + def init(self): + super().init(name="resource-optimizer") + + # πŸ”Ή STUDENT MISSING SECTION: Initialize Azure credentials & ComputeManagementClient + self.subscription_id = os.getenv("AZURESUBSCRIPTIONID") + self.resource_group = os.getenv("AZURERESOURCEGROUP") + self.vm_name = os.getenv("AZUREVMNAME") + self.credential = DefaultAzureCredential() + self.compute_client = ComputeManagementClient(self.credential, self.subscription_id) + + # πŸ”Ή STUDENT MISSING SECTION: Run method to process anomaly messages + def run(self, thread: Thread, message: Message): + print("Optimizer received:", message.content) + response = "" + + # Example logic: check message content for CPU/memory/disk anomalies + if "CPU" in message.content: + response = self.scale_vm("Standard_DS2_v2") + elif "Memory" in message.content: + response = self.scale_vm("Standard_DS3_v2") + elif "Disk" in message.content: + response = self.scale_vm("Standard_DS4_v2") + else: + response = "No actionable anomalies detected." + + thread.send_message(Message(content=response, role="agent")) + + # πŸ”Ή STUDENT MISSING SECTION: Scale VM method using Azure SDK + def scale_vm(self, new_size): + vm = self.compute_client.virtual_machines.get(self.resource_group, self.vm_name) + vm.hardware_profile.vm_size = new_size + poller = self.compute_client.virtual_machines.begin_create_or_update( + self.resource_group, + self.vm_name, + vm + ) + poller.wait() + return f"VM scaled to {new_size}" +``` + +--- + +### Register and Test the Agent + +#### Register the Agent + +```python +from azure.ai.foundry import AgentClient +from resource_optimizer import ResourceOptimizerAgent + +client = AgentClient() +agent = ResourceOptimizerAgent() +client.register_agent(agent) +``` + +Run: + +```bash +python register_optimizer.py +``` + +#### Test the Agent + +```python +from azure.ai.foundry import AgentClient + +client = AgentClient() +thread = client.create_thread() +client.send_message(thread.id, "⚠️ Anomaly detected: Percentage CPU = 92", agent_name="resource-optimizer") +``` + +Expected behavior: The agent prints the message, identifies the anomaly, and scales the VM according to the logic. + +--- + +### Next Steps + +Once the **Resource Optimizer Agent** is working: + +* Move to Challenge 04 to build an **Alert Manager Agent** that coordinates notifications and alert responses across your system. +* Explore logging, visualization, and orchestration for multi-agent workflows. + +--- + +All sections marked with `πŸ”Ή STUDENT MISSING SECTION` are **what students were expected to implement themselves** in the student guide. Coaches can reference these for solution verification. -Break things apart with more than one bullet list -- Like this -- One -- Right -- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-04.md b/xxx-AgenticAIApps/Coach/Solution-04.md index 90a770fdb3..1201421127 100644 --- a/xxx-AgenticAIApps/Coach/Solution-04.md +++ b/xxx-AgenticAIApps/Coach/Solution-04.md @@ -1,20 +1,130 @@ -# Challenge 04 - <Title of Challenge> - Coach's Guide +````markdown +# Challenge 04 - Build the Alert Manager Agent (Live Azure Integration) - Coach's Guide -[< Previous Solution](./Solution-03.md) - **[Home](./README.md)** - [Next Solution >](./Solution-05.md) +[< Previous Solution](./Solution-03.md) - **[Home](../README.md)** - [Next Solution >](./Solution-05.md) ## Notes & Guidance -This is the only section you need to include. +In this challenge, participants build an **Alert Manager Agent** that notifies stakeholders when anomalies or optimizations occur. +This involves integrating with **Azure Monitor Action Groups** and simulating real-world alert handling within an agentic workflow. -Use general non-bulleted text for the beginning of a solution area for this challenge +--- -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets +### Environment Setup -Break things apart with more than one bullet list +Install required dependencies: + +```bash +pip install azure-monitor-query azure-identity azure-mgmt-monitor python-dotenv +```` + +Update your `.env` file to include alert group settings: + +```env +AZURESUBSCRIPTIONID=your-subscription-id +AZURERESOURCEGROUP=your-resource-group +AZUREACTIONGROUP_NAME=your-action-group-name +``` + +> ⚠️ Ensure you have **Contributor permissions** to the resource group for managing alerts and action groups. + +--- + +### Create the Alert Manager Agent + +Create `alert_manager.py`: + +```python +import os +from azure.identity import DefaultAzureCredential +from azure.mgmt.monitor import MonitorManagementClient +from azure.ai.foundry import Agent, Message, Thread +from dotenv import load_dotenv + +load_dotenv() + +class AlertManagerAgent(Agent): + def init(self): + super().init(name="alert-manager") + + # πŸ”Ή STUDENT MISSING SECTION: Initialize subscription ID, resource group, and Azure Monitor client + self.subscription_id = os.getenv("AZURESUBSCRIPTIONID") + self.resource_group = os.getenv("AZURERESOURCEGROUP") + self.monitor_client = MonitorManagementClient( + credential=DefaultAzureCredential(), + subscription_id=self.subscription_id + ) + + # πŸ”Ή STUDENT MISSING SECTION: Define agent behavior when receiving anomaly or optimization messages + def run(self, thread: Thread, message: Message): + print("Alert Manager received:", message.content) + + if "Anomaly" in message.content or "Optimization" in message.content: + alert_msg = f"🚨 Alert triggered: {message.content}" + thread.send_message(Message(content=alert_msg, role="agent")) + print("Sending alert to Azure Monitor action group…") + self.send_alert(alert_msg) + + # πŸ”Ή STUDENT MISSING SECTION: Implement method to simulate sending alert to Azure Monitor + def send_alert(self, alert_msg): + # Simulated alert sending for demonstration + print(f"Simulated alert sent: {alert_msg}") +``` + +--- + +### Register and Test the Agent + +#### Register the Agent + +```python +# register_alert.py +from azure.ai.foundry import AgentClient +from alert_manager import AlertManagerAgent + +client = AgentClient() +agent = AlertManagerAgent() +client.register_agent(agent) +``` + +Run: + +```bash +python register_alert.py +``` + +#### Test the Agent + +```python +# test_alert.py +from azure.ai.foundry import AgentClient + +client = AgentClient() +thread = client.create_thread() +client.send_message(thread.id, "⚠️ Optimization failed due to high CPU usage", agent_name="alert-manager") +``` + +Run: + +```bash +python test_alert.py +``` + +Expected Output: + +``` +Alert Manager received: ⚠️ Optimization failed due to high CPU usage +🚨 Alert triggered: ⚠️ Optimization failed due to high CPU usage +Simulated alert sent: 🚨 Alert triggered: ⚠️ Optimization failed due to high CPU usage +``` + +--- + +### Next Steps + +Once the Alert Manager Agent is complete, proceed to **Challenge 05**, where students will build the **Agent-to-Agent Communication Layer** that enables collaboration and orchestration among the Anomaly Detector, Resource Optimizer, and Alert Manager agents. + +--- + +All sections marked with `πŸ”Ή STUDENT MISSING SECTION` are **what students were expected to implement themselves** in the student guide. Coaches can reference these for solution verification. -- Like this -- One -- Right -- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-05.md b/xxx-AgenticAIApps/Coach/Solution-05.md index 811c053840..c7d7bcdf3e 100644 --- a/xxx-AgenticAIApps/Coach/Solution-05.md +++ b/xxx-AgenticAIApps/Coach/Solution-05.md @@ -1,20 +1,131 @@ -# Challenge 05 - <Title of Challenge> - Coach's Guide +```markdown +# Challenge 05 - Orchestrate Agent-to-Agent Communication - Coach's Guide -[< Previous Solution](./Solution-04.md) - **[Home](./README.md)** - [Next Solution >](./Solution-06.md) +[< Previous Solution](./Solution-04.md) - **[Home](../README.md)** - [Next Solution >](./Solution-06.md) ## Notes & Guidance -This is the only section you need to include. +This challenge connects all previous agents β€” **Anomaly Detector**, **Resource Optimizer**, and **Alert Manager** β€” into a unified system. +It introduces **message routing**, **shared threads for memory**, and optional **Semantic Kernel planning** for adaptive orchestration. -Use general non-bulleted text for the beginning of a solution area for this challenge +--- -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets +### Environment Setup -Break things apart with more than one bullet list +Install dependencies: + +```bash +pip install python-dotenv azure-ai-foundry +```` + +Ensure all three agents are already registered and available in your workspace. + +--- + +### Orchestrator Initialization + +Create `agent_orchestrator.py`: + +```python +from azure.ai.foundry import AgentClient, Thread +from dotenv import load_dotenv +import os + +load_dotenv() + +class AgentOrchestrator: + def __init__(self): + # πŸ”Ή STUDENT MISSING SECTION: Initialize AgentClient and map agent names + self.client = AgentClient() + self.agents = { + "anomaly": "anomaly-detector", + "optimizer": "resource-optimizer", + "alert": "alert-manager" + } + + # πŸ”Ή STUDENT MISSING SECTION: Create a new communication thread for shared state + def create_thread(self): + return self.client.create_thread() + + # πŸ”Ή STUDENT MISSING SECTION: Define how messages are routed to each agent + def send_to_agent(self, thread: Thread, agent_key: str, message: str): + agent_name = self.agents.get(agent_key) + if not agent_name: + print(f"Unknown agent: {agent_key}") + return + self.client.send_message(thread.id, message, agent_name=agent_name) + + # πŸ”Ή STUDENT MISSING SECTION: Implement orchestration flow between agents + def orchestrate(self): + thread = self.create_thread() + print(" Step 1: Trigger Anomaly Detector") + self.send_to_agent(thread, "anomaly", "Check system metrics") + + print(" Step 2: Trigger Resource Optimizer") + self.send_to_agent(thread, "optimizer", "Respond to detected anomalies") + + print(" Step 3: Trigger Alert Manager") + self.send_to_agent(thread, "alert", "Notify stakeholders of critical issues") + + print(" Orchestration complete.") +``` + +--- + +### Run the Orchestrator + +Create `run_orchestrator.py`: + +```python +from agent_orchestrator import AgentOrchestrator + +orchestrator = AgentOrchestrator() +orchestrator.orchestrate() +``` + +Run the orchestrator: + +```bash +python run_orchestrator.py +``` + +Expected Output: + +``` + Step 1: Trigger Anomaly Detector + Step 2: Trigger Resource Optimizer + Step 3: Trigger Alert Manager + Orchestration complete. +``` + +--- + +### Optional: Semantic Kernel Integration + +For intelligent planning and adaptive execution, you can integrate **Semantic Kernel**: + +```python +from semantickernel import Kernel + +kernel = Kernel() +plan = kernel.create_plan("Detect and respond to system anomalies dynamically") +``` + +This allows your orchestrator to make **context-aware decisions** and support **autonomous collaboration** between agents. + +--- + +### Success Criteria + +Students should demonstrate: + +* The **Anomaly Detector**, **Resource Optimizer**, and **Alert Manager** agents are registered. +* The orchestrator successfully routes messages across agents using a shared thread. +* Execution produces an ordered flow of operations, simulating anomaly detection, optimization, and alerting. +* Optional: Use of **Semantic Kernel** or similar planning logic for intelligent task sequencing. + +--- + +All sections marked with `πŸ”Ή STUDENT MISSING SECTION` are **what students were expected to implement themselves** in the student guide. +Coaches can reference these to verify solution accuracy. -- Like this -- One -- Right -- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-06.md b/xxx-AgenticAIApps/Coach/Solution-06.md index 0100770cfa..49580527a8 100644 --- a/xxx-AgenticAIApps/Coach/Solution-06.md +++ b/xxx-AgenticAIApps/Coach/Solution-06.md @@ -1,20 +1,151 @@ -# Challenge 06 - <Title of Challenge> - Coach's Guide +````markdown +# Challenge 06 - Enable Agent-to-Agent Communication (A2A) - Coach's Guide [< Previous Solution](./Solution-05.md) - **[Home](./README.md)** - [Next Solution >](./Solution-07.md) ## Notes & Guidance -This is the only section you need to include. +In this challenge, participants enable **real-time communication between Azure Agents**, allowing them to exchange context and coordinate actions. +This marks the transition from isolated automation to a **collaborative, agentic network** powered by shared threads and dynamic planning. -Use general non-bulleted text for the beginning of a solution area for this challenge +--- -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets +## Goal -Break things apart with more than one bullet list +Build a communication layer that enables agents to: -- Like this -- One -- Right -- Here +- Share context through **shared threads** +- Exchange messages dynamically +- Coordinate actions using **shared memory** +- Optionally leverage **Semantic Kernel** or **Autogen v2** for autonomous planning + +--- + +## 🧩 Shared Thread Communication + +Enhance your orchestrator to support **dynamic interaction** between agents. + +Create or update `agent_orchestrator.py`: + +```python +# πŸ”Ή STUDENT MISSING SECTION: Implement dynamic orchestration method +def orchestrate_dynamic(self, user_input): + thread = self.create_thread() + + # Step 1: Trigger Anomaly Detector + self.send_to_agent(thread, "anomaly", user_input) + + # Step 2: Retrieve anomaly message + messages = self.get_thread_messages(thread) + anomaly_msg = next((m.content for m in messages if "Anomaly" in m.content), None) + + # Step 3: Trigger Resource Optimizer if anomaly detected + if anomaly_msg: + self.send_to_agent(thread, "optimizer", anomaly_msg) + + # Step 4: Retrieve optimization message + messages = self.get_thread_messages(thread) + optimization_msg = next((m.content for m in messages if "πŸ› οΈ" in m.content), None) + + # Step 5: Trigger Alert Manager if optimization succeeded + if optimization_msg: + self.send_to_agent(thread, "alert", optimization_msg) + + return self.get_thread_messages(thread) +```` + +### Explanation + +* **Shared thread**: Keeps all agent messages in the same context. +* **Sequential routing**: Each agent reads and reacts to prior messages. +* **Dynamic flow**: The orchestrator adapts based on actual responses. + +--- + +## βš™οΈ Update the App to Use Dynamic Orchestration + +Update `app.py` so user input triggers your new dynamic orchestration: + +```python +# πŸ”Ή STUDENT MISSING SECTION: Integrate orchestrator into app logic +async def handle_user_input(user_input): + messages = orchestrator.orchestrate_dynamic(user_input) + return [msg.content for msg in messages] +``` + +> πŸ’‘ The `async` keyword ensures compatibility with future streaming or concurrent message handling. + +--- + +## Add Agent Role Awareness (Optional) + +To improve clarity in logs and dashboards, tag messages by agent role. + +```python +return [f"{msg.role}: {msg.content}" for msg in messages] +``` + +Example output: + +``` +anomaly-detector: High CPU detected +resource-optimizer: Scaling VM to Standard_DS2_v2 +alert-manager: Notification sent to admin +``` + +--- + +## πŸ€– Optional: Semantic Kernel Integration + +For adaptive task routing, integrate **Microsoft Semantic Kernel**: + +```python +# πŸ”Ή STUDENT MISSING SECTION: Implement dynamic planning via Semantic Kernel +from semantickernel import Kernel + +kernel = Kernel() +plan = kernel.create_plan("Detect and respond to system anomalies") +for step in plan.steps: + orchestrator.send_to_agent(thread, step.plugin_name, step.description) +``` + +This enables **goal-driven orchestration**, allowing agents to decide which should act next based on current system state and context. + +--- + +## Expected Behavior + +When running the system: + +* **Anomaly Detector** identifies anomalies from Azure metrics +* **Resource Optimizer** responds and applies optimizations +* **Alert Manager** notifies users and stakeholders +* All messages and context flow through **shared threads** + +Example output: + +``` +anomaly-detector: Anomaly detected: CPU = 92% +resource-optimizer: Scaling VM to Standard_DS2_v2 +alert-manager: Alert sent: VM scaled successfully +``` + +--- + +## Next Steps + +Proceed to **Challenge 07** to extend your agentic system with: + +* Persistent memory between sessions +* Historical anomaly tracking +* Context-aware planning using Azure AI Foundry or Semantic Kernel + +--- + +All sections marked with `πŸ”Ή STUDENT MISSING SECTION` are **what students were expected to implement themselves** in the student guide. +Coaches can reference these to confirm the correctness of submitted solutions. + +``` + +Would you like me to continue with **Challenge 07 (Anomaly & Resolution Tracker)** in the same GitHub-ready format next? +``` diff --git a/xxx-AgenticAIApps/Coach/Solution-07.md b/xxx-AgenticAIApps/Coach/Solution-07.md index d0dce03848..9e73bb00cc 100644 --- a/xxx-AgenticAIApps/Coach/Solution-07.md +++ b/xxx-AgenticAIApps/Coach/Solution-07.md @@ -1,20 +1,181 @@ -# Challenge 07 - <Title of Challenge> - Coach's Guide +````markdown +# Challenge 07 - Build the Anomaly & Resolution Tracker - Coach's Guide [< Previous Solution](./Solution-06.md) - **[Home](./README.md)** - [Next Solution >](./Solution-08.md) ## Notes & Guidance -This is the only section you need to include. +In this challenge, participants will **track anomalies and resolutions** detected by their Azure Agents and visualize the results in real time. +You’ll implement lightweight logging, optionally add a Streamlit dashboard, and explore Azure-based storage options for enterprise-scale tracking. -Use general non-bulleted text for the beginning of a solution area for this challenge +--- -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets +## Goal + +Build a tracking system that: + +- Logs anomalies detected by the **Anomaly Detector Agent** +- Logs resolutions applied by the **Resource Optimizer Agent** +- Visualizes all events locally or in Azure +- Optionally integrates with **Streamlit**, **Power BI**, or **Azure Workbooks** + +--- + +## Log Anomalies and Resolutions + +Update each agent to log its actions to a local file (or a database, if desired). +Python’s built-in `logging` module is perfect for this. + +### Example β€” *Anomaly Detector Agent* + +```python +import logging + +logging.basicConfig(filename='agent_log.txt', level=logging.INFO, format='[%(asctime)s] %(message)s') + +def log_anomaly(metric, value): + logging.info(f"Anomaly Detected: {metric} = {value}") +```` + +Use `log_anomaly()` inside your anomaly detection logic whenever an issue is detected. + +--- + +### Example β€” *Resource Optimizer Agent* + +```python +def log_resolution(action): + logging.info(f"Resolution Applied: {action}") +``` + +Call `log_resolution()` after each successful optimization or simulated fix. + +--- + +## Structure the Log Format + +Maintain a **consistent format** for readability and parsing: + +``` +[2025-08-21 14:32:10] Anomaly Detected: CPU = 92% +[2025-08-21 14:32:15] Resolution Applied: Scaled VM to Standard_DS2_v2 +``` + +This makes it easy to visualize or analyze later β€” either manually or with tools like **Streamlit** or **Power BI**. + +> **Tip:** Use `logging.basicConfig(..., format='[%(asctime)s] %(message)s')` to automatically include timestamps. + +--- + +## Visualize with Streamlit (Optional) + +πŸ”Ή **This section is not included in the student guide.** +Coaches can use it to demonstrate how to turn logs into a real-time dashboard. + +Create a file named **`dashboard.py`**: + +```python +import streamlit as st + +st.title("πŸ” Anomaly & Resolution Tracker") + +with open("agent_log.txt") as f: + logs = f.readlines() + +for line in logs: + st.text(line.strip()) +``` + +Run the dashboard with: + +```bash +streamlit run dashboard.py +``` + +Then open the local URL Streamlit provides (usually `http://localhost:8501`) to view your live log feed. + +--- + +## (Optional) Store Logs in Azure Table or Cosmos DB + +πŸ”Ή **This section is not in the student guide.** +It provides advanced options for enterprise-level tracking and cloud persistence. + +For a **cloud-based tracking system**, you can log directly into **Azure Table Storage** or **Azure Cosmos DB** for long-term retention and visualization. + +### Option A – Azure Table Storage + +Install the SDK: + +```bash +pip install azure-data-tables +``` + +Then use: + +```python +from azure.data.tables import TableServiceClient +from datetime import datetime +import os + +service = TableServiceClient.from_connection_string(conn_str=os.getenv("AZURE_STORAGE_CONNECTION_STRING")) +table_client = service.get_table_client(table_name="AgentLogs") + +def log_to_table(event_type, detail): + entity = { + "PartitionKey": "AgentLogs", + "RowKey": str(datetime.utcnow().timestamp()), + "EventType": event_type, + "Detail": detail + } + table_client.create_entity(entity) +``` + +### Option B – Azure Cosmos DB + +Use **`azure-cosmos`** for structured, scalable document storage. +Each log can be stored as a JSON document and visualized using **Power BI** or **Azure Workbooks**. + +--- + +## Expected Behavior + +When running your system: + +* **Anomaly Detector** logs events like: + + ``` + [2025-10-11 14:01:10] Anomaly Detected: CPU = 91% + ``` +* **Resource Optimizer** logs resolutions: + + ``` + [2025-10-11 14:01:15] Resolution Applied: Scaled VM to Standard_DS2_v2 + ``` +* Logs can be viewed locally or through your **Streamlit dashboard** (πŸ”Ή *dashboard is a coach-only enhancement*). + +--- + +## Success Criteria + +A student has successfully completed Challenge 07 when they can: + +* Log anomalies detected by the Anomaly Detector Agent to a local file or database. +* Log resolutions applied by the Resource Optimizer Agent consistently. +* View logs in the correct timestamped format. +* Demonstrate that both anomaly detection and resolution events are captured and trackable in real time. + +--- + +πŸ”Ή **Coach Extension:** +Encourage students to explore: + +* Streamlit for local dashboards +* Azure Table or Cosmos DB for persistent logging +* Power BI or Azure Workbooks for advanced visualization + +--- + +All sections marked with `πŸ”Ή STUDENT MISSING SECTION` are **what students were expected to implement themselves** in the student guide. Coaches can reference these for solution verification. -Break things apart with more than one bullet list -- Like this -- One -- Right -- Here diff --git a/xxx-AgenticAIApps/Coach/Solution-08.md b/xxx-AgenticAIApps/Coach/Solution-08.md index dd606228fe..8fc41677ad 100644 --- a/xxx-AgenticAIApps/Coach/Solution-08.md +++ b/xxx-AgenticAIApps/Coach/Solution-08.md @@ -1,20 +1,200 @@ -# Challenge 08 - <Title of Challenge> - Coach's Guide +````markdown +# Challenge 008 – Spike VM Resources & Test Agent Detection – Coach's Guide -[< Previous Solution](./Solution-07.md) - **[Home](./README.md)** - [Next Solution >](./Solution-09.md) +[< Previous Solution](./Solution-005.md) - **[Home](./README.md)** -## Notes & Guidance +## Goal +Temporarily spike CPU and memory on your VM to test agent detection. +Participants will observe the **Anomaly Detector**, **Resource Optimizer**, and **Alert Manager** responding to real-time changes. -This is the only section you need to include. +--- -Use general non-bulleted text for the beginning of a solution area for this challenge +## Important Pre-Step: Establish a Baseline +Before creating the spike: +1. Connect to your Azure environment. +2. Run your agents **without any artificial load**: -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets +```bash +python test_anomaly.py +# or +python run_orchestrator.py +```` -Break things apart with more than one bullet list +* Confirm no anomalies are logged β€” this is your baseline reference. -- Like this -- One -- Right -- Here +--- + +## Choose the Appropriate Stress Script + +### Linux/macOS – Bash or Zsh Users (`spike_vm.sh`) + +```bash +#!/usr/bin/env bash +# CPU + Memory stress test for Linux/macOS + +DURATION=${1:-30} # default duration in seconds +MEMORY_MB=${2:-1024} # default memory allocation + +echo "πŸ” Spiking CPU and memory for $DURATION seconds (Memory: $MEMORY_MB MB)..." + +# CPU spike: spawn a background loop per CPU core +CPU_CORES=$(nproc) +for i in $(seq 1 $CPU_CORES); do + ( while :; do 1..200000 | xargs -n1 echo | md5sum > /dev/null; done ) & +done + +# Memory spike: allocate arrays +MEM_BLOCKS=() +BLOCK_SIZE_MB=64 +BLOCKS_TO_ALLOCATE=$(( (MEMORY_MB + BLOCK_SIZE_MB - 1) / BLOCK_SIZE_MB )) +for i in $(seq 1 $BLOCKS_TO_ALLOCATE); do + MEM_BLOCKS+=( $(python3 -c "a = ['x'*1024*1024 for _ in range($BLOCK_SIZE_MB)]; input()") ) +done + +echo "CPU+Memory stress running. Stop manually by killing background jobs or closing terminal." +``` + +Run: + +```bash +chmod +x spike_vm.sh +./spike_vm.sh 45 1024 +``` + +--- + +### Windows – PowerShell Users (`spike_vm.ps1`) + +```powershell +# Set CPU threads and memory allocation +$cpuThreads = [int](Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors +$memoryMB = 1024 + +Write-Host "`nStarting CPU spike with $cpuThreads threads and allocating $memoryMB MB of RAM..." + +# Start CPU jobs +$jobs = for ($i=1; $i -le $cpuThreads; $i++) { + Start-Job -ScriptBlock { + while ($true) { 1..200000 | ForEach-Object { [math]::Sqrt($_) } > $null } + } +} + +# Allocate memory +try { + $global:memBlocks = @() + $blockSizeMB = 64 + $toAllocate = [int]([math]::Ceiling($memoryMB / $blockSizeMB)) + for ($i=0; $i -lt $toAllocate; $i++) { + $b = New-Object Byte[] ($blockSizeMB * 1MB) + for ($j=0; $j -lt $b.Length; $j += 4096) { $b[$j] = 0x1 } + $global:memBlocks += ,$b + } + Write-Host "Memory allocation succeeded." +} catch { + Write-Warning "Memory allocation failed or reached system limit: $_" +} + +Write-Host "`nCPU+Memory stress running. To stop run the STOP block shown below." +``` + +Run: + +```powershell +Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force +.\spike_vm.ps1 -Duration 45 +``` + +--- + +## Run Agents During Stress + +Immediately after starting the spike: + +```bash +python test_anomaly.py +# or +python run_orchestrator.py +``` + +* **Anomaly Detector Agent** should detect high CPU/memory. +* **Resource Optimizer Agent** may suggest scaling or other resolutions. +* **Alert Manager Agent** may log or simulate alerts. + +--- + +## Verify Logs + +```powershell +# On Windows +Get-Content .\agent_log.txt -Wait + +# On Linux/macOS +tail -f agent_log.txt +``` + +Expected entries: + +``` +[2025-10-11 15:22:00] Anomaly Detected: CPU = 98% +[2025-10-11 15:22:05] Resolution Applied: Suggested VM scale-up +``` + +--- + +## Stop the Stress Script + +**Linux/macOS:** + +```bash +pkill -f 'md5sum' # stops CPU loops +``` + +**Windows PowerShell:** + +```powershell +Get-Job | Where-Object { $_.State -eq 'Running' } | ForEach-Object { Stop-Job -Job $_; Remove-Job -Job $_ } +Remove-Variable memBlocks -ErrorAction SilentlyContinue -Scope Global +[GC]::Collect(); [GC]::WaitForPendingFinalizers() +Write-Host "Stress jobs stopped and memory released." +``` + +--- + +## Success Criteria + +* Appropriate spike script in your repo (`spike_vm.sh` or `spike_vm.ps1`) +* Logs showing baseline and spike detection +* Optional screenshot of agent alerts or Streamlit dashboard + +--- + +πŸ”Ή **Coach-Only Troubleshooting Guide** + +If agents fail to detect or respond to the spike: + +* **Verify Environment Variables:** + Ensure `.env` includes all required Azure credentials (`AZURESUBSCRIPTIONID`, `AZURERESOURCEGROUP`, etc.). +* **Check Agent Registration:** + Run `python -m azure.ai.foundry list-agents` to confirm `anomaly-detector`, `resource-optimizer`, and `alert-manager` are registered. +* **Inspect Thread Flow:** + Add print statements or use logging to verify message propagation between agents in shared threads. +* **Validate Log Permissions:** + Confirm `agent_log.txt` exists and the process has write access. +* **Simulate Manual Alerts:** + Send a test message directly to `alert-manager`: + + ```bash + python -c "from azure.ai.foundry import AgentClient; c=AgentClient(); t=c.create_thread(); c.send_message(t.id, '⚠️ Manual test alert', agent_name='alert-manager')" + ``` +* **Check VM Monitoring Limits:** + If Azure Monitor metrics are delayed, manually confirm with: + + ```bash + az monitor metrics list --resource <resource_id> --metric "Percentage CPU" + ``` +* **Restart Agents:** + Occasionally agents hold stale threads; restarting clears cached state. + +--- + +All sections marked with `πŸ”Ή STUDENT MISSING SECTION` are **what students were expected to implement themselves** in the student guide. Coaches can reference these for solution verification. diff --git a/xxx-AgenticAIApps/Coach/Solution-09.md b/xxx-AgenticAIApps/Coach/Solution-09.md index 432a0bb9ad..e69de29bb2 100644 --- a/xxx-AgenticAIApps/Coach/Solution-09.md +++ b/xxx-AgenticAIApps/Coach/Solution-09.md @@ -1,20 +0,0 @@ -# Challenge 09 - <Title of Challenge> - Coach's Guide - -[< Previous Solution](./Solution-08.md) - **[Home](./README.md)** - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here From 1a5f3400ebcb19dca1c2ef05e38c151bbe83a1d7 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <eruiz005@wilmu.edu> Date: Thu, 16 Oct 2025 06:18:09 -0400 Subject: [PATCH 05/34] Updated README.md file --- xxx-AgenticAIApps/Coach/README.md | 137 ++++++++++++++----------- xxx-AgenticAIApps/Coach/Solution-00.md | 2 +- 2 files changed, 76 insertions(+), 63 deletions(-) diff --git a/xxx-AgenticAIApps/Coach/README.md b/xxx-AgenticAIApps/Coach/README.md index 5c1b64670d..af082db509 100644 --- a/xxx-AgenticAIApps/Coach/README.md +++ b/xxx-AgenticAIApps/Coach/README.md @@ -2,7 +2,8 @@ ## Introduction -Welcome to the coach's guide for the AgenticAIApps What The Hack. Here you will find links to specific guidance for coaches for each of the challenges. +Welcome to the coach's guide for **AgenticAIApps**, a modern **Azure Agentic AI Hack** designed to help participants build, test, and scale intelligent multi-agent systems. +Here you will find links to specific guidance for coaches for each of the challenges. This hack includes an optional [lecture presentation](Lectures.pptx) that features short presentations to introduce key topics associated with each challenge. It is recommended that the host present each short presentation before attendees kick off that challenge. @@ -10,91 +11,103 @@ This hack includes an optional [lecture presentation](Lectures.pptx) that featur ## Learning Objectives -This project is designed to teach participants how to build agentic applications using Azure’s AI ecosystem. It begins with setting up a cloud-native development environment through GitHub Codespaces and Azure AI Foundry, eliminating local setup and streamlining access to cloud resources. Learners will orchestrate intelligent agents using Semantic Kernel, implement secure communication protocols like Agent2Agent (A2A), and deploy multi-agent workflows with live metric integration via Azure Monitor. The experience is grounded in hands-on development with Python, and optionally enhanced with a Flask-based UI for visualizing agent interactions. By the end, participants will be equipped to design, deploy, and manage scalable, secure, and collaborative AI agents in real-world scenarios. +This project is designed to teach participants how to build agentic applications using Azure’s AI ecosystem. +Participants will orchestrate intelligent agents using Semantic Kernel, implement secure communication protocols, and deploy multi-agent workflows with live metric integration via Azure Monitor. By the end, participants will be equipped to design, deploy, and manage scalable, secure, and collaborative AI agents in real-world scenarios. + +Participants will learn to: + +- Provision and configure a Linux VM in Azure with read/write permissions +- Deploy and test **Anomaly Detector**, **Resource Optimizer**, and **Alert Manager** agents +- Orchestrate multi-agent collaboration for real-time decision-making +- Build and visualize logs locally and in Azure (via Streamlit or Power BI) +- Spike VM resources to test agent detection and resilience +- Integrate Azure tools (Monitor, Storage, and AI Foundry) for advanced observability + +--- ## Coach's Guides -- Challenge 00: **[Prerequisites - Ready, Set, GO!](./Solution-00.md)** - - Prepare your workstation to work with Azure. -- Challenge 01: **[Title of Challenge](./Solution-01.md)** - - Description of challenge -- Challenge 02: **[Title of Challenge](./Solution-02.md)** - - Description of challenge -- Challenge 03: **[Title of Challenge](./Solution-03.md)** - - Description of challenge -- Challenge 04: **[Title of Challenge](./Solution-04.md)** - - Description of challenge -- Challenge 05: **[Title of Challenge](./Solution-05.md)** - - Description of challenge -- Challenge 06: **[Title of Challenge](./Solution-06.md)** - - Description of challenge -- Challenge 07: **[Title of Challenge](./Solution-07.md)** - - Description of challenge -- Challenge 08: **[Title of Challenge](./Solution-08.md)** - - Description of challenge -- Challenge 09: **[Title of Challenge](./Solution-09.md)** - - Description of challenge +- **Challenge 00:** [Azure AI Foundry Onboarding & Environment Prep](./Solution-00.md) + *Set up your Azure environment and validate permissions.* -## Coach Prerequisites +- **Challenge 01:** [Semantic Kernel Setup & Configuration](./Solution-01.md) + *Deploy a Linux VM with contributor permissions and enable SSH access.* -This hack has pre-reqs that a coach is responsible for understanding and/or setting up BEFORE hosting an event. Please review the [What The Hack Hosting Guide](https://aka.ms/wthhost) for information on how to host a hack event. +- **Challenge 02:** [Build the Anomaly Detector Agent (Real Azure Metrics)](./Solution-02.md) + *Set up your environment with Python, Bash, and Azure SDKs, and create your first monitoring agent.* -The guide covers the common preparation steps a coach needs to do before any What The Hack event, including how to properly configure Microsoft Teams. +- **Challenge 03:** [Build the Resource Optimizer Agent (Real Azure Integration)](./Solution-03.md) + *Implement automated resource adjustments based on detected anomalies.* -**Required Prerequisites:** -- Python (Version 3.7 or higher, Python 3.13 preferred) -- Pip (package installer for Python) -- Active Azure Subscription -- Azure Developer CLI +- **Challenge 04:** [Build the Alert Manager Agent (Live Azure Integration)](./Solution-04.md) + *Design a communication layer to notify or log alerts from your system.* -### Student Resources +- **Challenge 05:** [Orchestrate Agent-to-Agent Communication](./Solution-05.md) + *Build an orchestrator to coordinate communication between agents.* + +- **Challenge 06:** [Enable Agent-to-Agent Communication (A2A)](./Solution-06.md) + *Enable agents to share context, pass messages, and coordinate actions dynamically.* -Before the hack, it is the Coach's responsibility to download and package up the contents of the `/Student/Resources` folder of this hack into a "Resources.zip" file. The coach should then provide a copy of the Resources.zip file to all students at the start of the hack. +- **Challenge 07:** [Build the Anomaly & Resolution Tracker](./Solution-07.md) + *Log and visualize all anomaly and resolution events in real time.* -Always refer students to the [What The Hack website](https://aka.ms/wth) for the student guide: [https://aka.ms/wth](https://aka.ms/wth) +- **Challenge 08:** [Spike VM Resources & Test Agent Detection](./Solution-08.md) + *Simulate CPU and memory spikes to validate your agentic system.* -**NOTE:** Students should **not** be given a link to the What The Hack repo before or during a hack. The student guide does **NOT** have any links to the Coach's guide or the What The Hack repo on GitHub. +--- -### Additional Coach Prerequisites (Optional) +## Coach Prerequisites -_Please list any additional pre-event setup steps a coach would be required to set up such as, creating or hosting a shared dataset, or deploying a lab environment._ +Before hosting, coaches should ensure they can perform the following: -## Azure Requirements +- **Active Azure Subscription** +- **Python 3.7 or higher** *(Python 3.13 preferred)* +- **Pip** (Python package installer) +- **GitHub account** with access to the AgenticAIApps repository and **Codespaces** +- **VS Code** with Python and Azure extensions +- **Azure CLI** installed and authenticated +- Basic familiarity with **Linux, SSH, and Bash scripting** +- (Optional) Azure Monitor, Streamlit, and Power BI for visualization -This hack requires students to have access to an Azure subscription where they can create and consume Azure resources. These Azure requirements should be shared with a stakeholder in the organization that will be providing the Azure subscription(s) that will be used by the students. +Always review the [What The Hack Hosting Guide](https://aka.ms/wthhost) for event-specific instructions. -_Please list Azure subscription requirements._ +### Student Resources + +Coaches should download and package the `/Student/Resources` folder into a `Resources.zip` file and provide it to students at the start of the hack. + +**NOTE:** Students should **not** have access to the repository before or during the hack. + +--- -_For example:_ +## Azure Requirements + +Students require access to an Azure subscription capable of creating and consuming resources used in the challenges. +This includes: -- Azure resources that will be consumed by a student implementing the hack's challenges -- Azure permissions required by a student to complete the hack's challenges. +- VM creation and scaling +- Storage access (for logs) +- Permissions to deploy agents and monitoring solutions -## Suggested Hack Agenda (Optional) +--- -_This section is optional. You may wish to provide an estimate of how long each challenge should take for an average squad of students to complete and/or a proposal of how many challenges a coach should structure each session for a multi-session hack event. For example:_ +## Learning Resources -- Sample Day 1 - - Challenge 1 (1 hour) - - Challenge 2 (30 mins) - - Challenge 3 (2 hours) -- Sample Day 2 - - Challenge 4 (45 mins) - - Challenge 5 (1 hour) - - Challenge 6 (45 mins) +- [Microsoft Agent Framework – Python User Guide](https://learn.microsoft.com/en-us/agent-framework/user-guide/agents/agent-types/?pivots=programming-language-python) +- [Connect to a VM using SSH (Azure Docs)](https://learn.microsoft.com/en-us/azure/virtual-machines/linux/mac-create-ssh-keys) +- [Introduction to Bash and Linux CLI](https://ubuntu.com/tutorials/command-line-for-beginners) +- [Azure AI Foundry Overview](https://learn.microsoft.com/en-us/azure/ai-foundry/) + +--- ## Repository Contents -_The default files & folders are listed below. You may add to this if you want to specify what is in additional sub-folders you may add._ +- `./Coach` – Coach's guide and related files +- `./Coach/Solutions` – Completed solution files for each challenge +- `./Student` – Student challenge guide +- `./Student/Resources` – Resource files, sample code, and scripts for students -- `./Coach` - - Coach's Guide and related files -- `./Coach/Solutions` - - Solution files with completed example answers to a challenge -- `./Student` - - Student's Challenge Guide -- `./Student/Resources` - - Resource files, sample code, scripts, etc meant to be provided to students. (Must be packaged up by the coach and provided to students at start of event) +--- ## Contributors -- Esvin RUiz + +- **Esvin Ruiz** diff --git a/xxx-AgenticAIApps/Coach/Solution-00.md b/xxx-AgenticAIApps/Coach/Solution-00.md index 156ce11038..5e737ae3f3 100644 --- a/xxx-AgenticAIApps/Coach/Solution-00.md +++ b/xxx-AgenticAIApps/Coach/Solution-00.md @@ -1,4 +1,4 @@ -# Challenge 00 - <Azure AI Foundry Onboarding & Environment Prep> - Coach's Guide +# Challenge 00 - Azure AI Foundry Onboarding & Environment Prep - Coach's Guide **[Home](./README.md)** - [Next Solution >](./Solution-00.md) From 5348a5f3a4730d8d92b32284c5e61203e2916b49 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <eruiz005@wilmu.edu> Date: Thu, 16 Oct 2025 06:33:14 -0400 Subject: [PATCH 06/34] Updated Student Guides --- xxx-AgenticAIApps/Student/Challenge-00.md | 111 +++++-------- xxx-AgenticAIApps/Student/Challenge-01.md | 116 ++++++------- xxx-AgenticAIApps/Student/Challenge-02.md | 193 ++++++++++++++++------ xxx-AgenticAIApps/Student/Challenge-03.md | 177 ++++++++++++++------ xxx-AgenticAIApps/Student/Challenge-04.md | 178 ++++++++++++++------ xxx-AgenticAIApps/Student/Challenge-05.md | 143 +++++++++------- xxx-AgenticAIApps/Student/Challenge-06.md | 126 ++++++++------ xxx-AgenticAIApps/Student/Challenge-07.md | 165 ++++++++++++------ xxx-AgenticAIApps/Student/Challenge-08.md | 153 +++++++++++------ 9 files changed, 853 insertions(+), 509 deletions(-) diff --git a/xxx-AgenticAIApps/Student/Challenge-00.md b/xxx-AgenticAIApps/Student/Challenge-00.md index 843c24047a..39212f9e61 100644 --- a/xxx-AgenticAIApps/Student/Challenge-00.md +++ b/xxx-AgenticAIApps/Student/Challenge-00.md @@ -1,100 +1,77 @@ -# Challenge 00 - Prerequisites - Ready, Set, GO! +# Challenge 00 - Azure AI Foundry Onboarding & Environment Prep **[Home](../README.md)** - [Next Challenge >](./Challenge-01.md) -**_This is a template for "Challenge Zero" which focuses on getting prerequisites set up for the hack. The italicized text provides hints & examples of what should or should NOT go in each section._** +## Pre-requisites -**_We have included links to some common What The Hack pre-reqs in this template. All common prerequisite links go to the WTH-CommonPrerequisites page where there are more details on what each tool's purpose is._** +- Active Azure Subscription +- Python 3.7 or higher (Python 3.13 preferred) +- Pip (Python package installer) +- GitHub account with access to the Agentic AI Apps repository -**_You should remove any common pre-reqs that are not required for your hack. Then add additional pre-reqs that are required for your hack in the Description section below._** +*This challenge assumes you have completed the What The Hack onboarding and have access to GitHub Codespaces.* -**_You should remove all italicized & sample text in this template and replace with your content._** +--- ## Introduction -Thank you for participating in the AgenticAIApps What The Hack. Before you can hack, you will need to set up some prerequisites. +In this challenge, you will set up your development environment for Azure AI Foundry. You will learn how to: -## Common Prerequisites +- Create Azure resources necessary for agent development +- Launch GitHub Codespaces for a cloud-hosted development environment +- Prepare a VM to test agent workloads +- Authenticate your Codespaces session with Azure -We have compiled a list of common tools and software that will come in handy to complete most What The Hack Azure-based hacks! +Completing this challenge ensures you have a fully functional workspace for building and running intelligent agents in subsequent challenges. -You might not need all of them for the hack you are participating in. However, if you work with Azure on a regular basis, these are all things you should consider having in your toolbox. - -<!-- If you are editing this template manually, be aware that these links are only designed to work if this Markdown file is in the /xxx-HackName/Student/ folder of your hack. --> - -- [Azure Subscription](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-subscription) -- [Windows Subsystem for Linux](../../000-HowToHack/WTH-Common-Prerequisites.md#windows-subsystem-for-linux) -- [Managing Cloud Resources](../../000-HowToHack/WTH-Common-Prerequisites.md#managing-cloud-resources) - - [Azure Portal](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-portal) - - [Azure CLI](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cli) - - [Note for Windows Users](../../000-HowToHack/WTH-Common-Prerequisites.md#note-for-windows-users) - - [Azure PowerShell CmdLets](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-powershell-cmdlets) - - [Azure Cloud Shell](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cloud-shell) -- [Visual Studio Code](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code) - - [VS Code plugin for ARM Templates](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code-plugins-for-arm-templates) -- [Azure Storage Explorer](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-storage-explorer) +--- ## Description -_This section should clearly state any additional prerequisite tools that need to be installed or set up in the Azure environment that the student will hack in._ - -_While ordered lists are generally not welcome in What The Hack challenge descriptions, you can use one here in Challenge Zero IF and only IF the steps you are asking the student to perform are not core to the learning objectives of the hack._ - -_For example, if the hack is on IoT Devices and you want the student to deploy an ARM/Bicep template that sets up the environment they will hack in without them needing to understand how ARM/Bicep templates work, you can provide step-by-step instructions on how to deploy the ARM/Bicep template._ +Your goal is to prepare an environment capable of running the Azure AI Foundry agents. This includes: -_Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack. You should leave the sample text below in that refers to the Resources.zip file._ +- Creating an Azure AI Foundry resource in your subscription +- Setting up GitHub Codespaces connected to your Azure account +- Installing required Python SDKs and dependencies +- Provisioning a Linux VM (`agentic-vm-test`) with contributor permissions to allow for read/ write operations +- Verifying your environment can run Python scripts and connect to Azure services -**\*NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resources.zip file provided by the coach.\* +> **Note:** This challenge focuses on environment preparation. You are not yet building agents. -**\*NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.\* +--- -_Sample challenge zero text for the IoT Hack Of The Century:_ - -Now that you have the common pre-requisites installed on your workstation, there are prerequisites specifc to this hack. +## Learning Resources -Your coach will provide you with a Resources.zip file that contains resources you will need to complete the hack. If you plan to work locally, you should unpack it on your workstation. If you plan to use the Azure Cloud Shell, you should upload it to the Cloud Shell and unpack it there. +- [Azure AI Foundry Overview](https://learn.microsoft.com/en-us/azure/ai-foundry/what-is-azure-ai-foundry) +- [GitHub Codespaces Documentation](https://docs.github.com/en/codespaces/about-codespaces/what-are-codespaces) +- [Azure CLI Documentation](https://learn.microsoft.com/en-us/cli/azure/) +- [Python `pip` Documentation](https://pip.pypa.io/en/stable/) -Please install these additional tools: +--- -- [Azure IoT Tools](https://marketplace.visualstudio.com/items?itemName=vsciot-vscode.azure-iot-tools) extension for Visual Studio Code -- .NET SDK 6.0 or later installed on your development machine. This can be downloaded from [here](https://www.microsoft.com/net/download/all) for multiple platforms. +## Tips -In the `/Challenge00/` folder of the Resources.zip file, you will find an ARM template, `setupIoTEnvironment.json` that sets up the initial hack environment in Azure you will work with in subsequent challenges. +- Ensure you keep your `.env` and Foundry configuration secure β€” you will reuse them in all subsequent challenges +- Codespaces automatically installs dependencies; if something fails, check your terminal for installation errors +- Use SSH keys carefully when configuring the VM for secure access -Please deploy the template by running the following Azure CLI commands from the location of the template file: -``` -az group create --name myIoT-rg --location eastus -az group deployment create -g myIoT-rg --name HackEnvironment -f setupIoTEnvironment.json -``` +--- ## Success Criteria -_Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach._ - -_The success criteria should not be a list of instructions._ - -_Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."_ - -_Sample success criteria for the IoT prerequisites challenge:_ - To complete this challenge successfully, you should be able to: -- Verify that you have a bash shell with the Azure CLI available. -- Verify that the ARM template has deployed the following resources in Azure: - - Azure IoT Hub - - Virtual Network - - Jumpbox VM - -## Learning Resources - -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ +- Verify you can authenticate to Azure from GitHub Codespaces using `az login` +- Show that Python and required packages (`azure-ai-projects`, `azure-identity`) are installed +- Demonstrate that the VM is deployed, accessible via SSH, and has contributor permissions +- Confirm that your Codespaces terminal can interact with Azure AI Foundry resources -_Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario._ +--- -**\*Note:** Use descriptive text for each link instead of just URLs.\* +## Advanced Challenges (Optional) -_Sample IoT resource links:_ +If you want to go beyond the baseline setup: -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) +- Experiment with different VM sizes and regions +- Enable additional managed identities and role assignments for advanced testing +- Configure the Codespace to mount external repositories for agent collaboration diff --git a/xxx-AgenticAIApps/Student/Challenge-01.md b/xxx-AgenticAIApps/Student/Challenge-01.md index fcf81ed831..af70d7dd87 100644 --- a/xxx-AgenticAIApps/Student/Challenge-01.md +++ b/xxx-AgenticAIApps/Student/Challenge-01.md @@ -1,99 +1,89 @@ -# Challenge 01 - <Title of Challenge> +````markdown +# Challenge 01 - Semantic Kernel Setup & Configuration [< Previous Challenge](./Challenge-00.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-02.md) -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** +--- -## Pre-requisites (Optional) +## Pre-requisites -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* +- Completion of **Challenge 00 – Azure AI Foundry Onboarding & Environment Prep** +- Active **Azure AI Foundry** resource +- **GitHub Codespaces** environment ready +- `.env` file configured with your **Azure OpenAI** keys -## Introduction +--- -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* +## Introduction -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* +In this challenge, you will set up **Semantic Kernel** inside your GitHub Codespaces environment. +Semantic Kernel provides the **cognitive layer** for your AI agents, enabling them to interpret instructions, generate structured plans, and execute actions. -*For example:* +You’ll configure your environment to connect to Azure OpenAI services and prepare to create your first **agent skills**. +Later, these skills will be extended to work with live Azure telemetry data. -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. +--- ## Description -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* - -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* - -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* - -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* +Your goal is to configure **Semantic Kernel** and establish the foundation for skill development. +This includes: -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* +- Initializing the kernel with **Azure OpenAI** credentials +- Testing a simple **prompt** to confirm connectivity +- Creating a `skills/` folder for skill development +- Preparing a skeleton for a **live Azure Monitor skill** (students implement core functionality) -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* +> **Note:** Some code sections are intentionally left incomplete for you to implement. Follow the hints and references below to complete the skill. -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* +--- -*Sample challenge text for the IoT Hack Of The Century:* +### Skeleton Example (`azure_monitor_skill.py`) -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. - -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. - -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" - -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). - -## Success Criteria +```python +# students implement this -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* +class AzureMonitorSkill: + def __init__(self): + # TODO: Initialize Azure credentials and MetricsQueryClient + pass -*The success criteria should not be a list of instructions.* + def get_vm_cpu(self) -> str: + # TODO: Query Azure Monitor for VM CPU usage and return a string + pass +```` -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* +--- -*Sample success criteria for the IoT sample challenge:* - -To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip ## Learning Resources -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ - -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* - -***Note:** Use descriptive text for each link instead of just URLs.* - -*Sample IoT resource links:* +* [Semantic Kernel Documentation](https://learn.microsoft.com/en-us/semantic-kernel/overview) +* [Azure Monitor Metrics Query SDK](https://learn.microsoft.com/en-us/python/api/overview/azure/monitor-query-readme) +* [Azure Identity Python SDK](https://learn.microsoft.com/en-us/python/api/overview/azure/identity-readme) +* [GitHub Codespaces Basics](https://docs.github.com/en/codespaces/getting-started/quickstart) -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) +--- ## Tips -*This section is optional and may be omitted.* +* Ensure your `.env` file has **no extra spaces or quotes** around values +* Test prompts incrementally to confirm **connectivity** before implementing skills +* Use the learning resources to guide your **Azure Monitor queries** +* Keep your class methods small, modular, and focused for easier debugging -*Add tips and hints here to give students food for thought. Sample IoT tips:* +--- -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. - -## Advanced Challenges (Optional) +## Success Criteria -*If you want, you may provide additional goals to this challenge for folks who are eager.* +To complete this challenge successfully, you should be able to: -*This section is optional and may be omitted.* +1. Validate that **Semantic Kernel** initializes correctly with Azure OpenAI credentials +2. Verify that a **test prompt** returns a meaningful response +3. Demonstrate that the `skills/` folder exists and contains at least one skill skeleton (`AzureMonitorSkill`) +4. Explain how the kernel can be extended to pull **live telemetry** from Azure -*Sample IoT advanced challenges:* -Too comfortable? Eager to do more? Try these additional challenges! +[< Previous Challenge](./Challenge-00.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-02.md) -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. +``` diff --git a/xxx-AgenticAIApps/Student/Challenge-02.md b/xxx-AgenticAIApps/Student/Challenge-02.md index 459fb175d5..fd310f3a52 100644 --- a/xxx-AgenticAIApps/Student/Challenge-02.md +++ b/xxx-AgenticAIApps/Student/Challenge-02.md @@ -1,99 +1,182 @@ -# Challenge 02 - <Title of Challenge> +````markdown +# Challenge 02 - Build the Anomaly Detector Agent (Real Azure Metrics) -[< Previous Challenge](./Challenge-01.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-03.md) +**[Home](../README.md)** - [Next Challenge >](./Challenge-03.md) -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** +--- -## Pre-requisites (Optional) +## Introduction -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* +In this challenge, you’ll build your first **intelligent agent** β€” the **Anomaly Detector Agent**. This agent will use **Semantic Kernel** to analyze **live Azure Monitor metrics** and detect when your virtual machine experiences performance anomalies (for example, high CPU or memory usage). -## Introduction +By the end of this challenge, you’ll have a functional AI-driven process that monitors your Azure resources and flags abnormal behavior β€” forming the foundation for your next, self-healing agent. + +--- -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* +## Description -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* +You will extend your existing environment (from Challenge 01) by creating a new skill and agent capable of: -*For example:* +- Reading **real telemetry data** (CPU, Memory, Disk I/O) from your Azure VM +- Comparing metric values to defined thresholds +- Reporting an **anomaly detected** message when metrics exceed limits -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. +This challenge focuses on **logic building**, **skill registration**, and **data reasoning** using Semantic Kernel. -## Description +--- -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* +### Confirm Your Setup -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* +Before building your agent: -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* +- Ensure your `.env` file includes your Azure credentials. +- Confirm that your **Azure Monitor Skill** from Challenge 01 works and returns live metrics. -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* +You can quickly test it by running: -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* +```bash +python test_kernel.py +```` -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* +βœ… You should see something like: -*Sample challenge text for the IoT Hack Of The Century:* +``` +Current CPU usage: 23.54% +``` -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. +--- -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. +### Create the Anomaly Detector Skill -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" +In the `skills/` folder, create a new file named `anomaly_detector_skill.py`. -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). +Inside this file, you will: -## Success Criteria +* Define a class called `AnomalyDetectorSkill` +* Set threshold values for CPU and Memory +* Add a function called `detect_anomaly()` that checks for high usage and returns a message + +Start with the following structure and fill in the logic where marked: + +```python +from semantic_kernel.skill_definition import sk_function + +class AnomalyDetectorSkill: + def __init__(self, cpu_threshold: float = 80.0, memory_threshold: float = 85.0): + self.cpu_threshold = cpu_threshold + self.memory_threshold = memory_threshold + + @sk_function(name="detect_anomaly", description="Detect if system metrics exceed normal thresholds") + def detect_anomaly(self, cpu_usage: float, memory_usage: float) -> str: + """ + TODO: Compare metric values against thresholds. + If CPU or memory usage exceeds their threshold, + return a message describing the anomaly. + Otherwise, return a message that the system is normal. + """ +``` + +--- + +### Create the Anomaly Detector Agent -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* +Now, in the `agents/` folder, create a file called `anomaly_detector_agent.py`. -*The success criteria should not be a list of instructions.* +This agent will: -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* +* Initialize the Semantic Kernel +* Register both the `AzureMonitorSkill` and your new `AnomalyDetectorSkill` +* Retrieve CPU and memory data +* Pass it into your anomaly detection skill and print the result -*Sample success criteria for the IoT sample challenge:* +Use this as your starter template: -To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip +```python +import asyncio +from semantic_kernel import Kernel +from skills.azure_monitor_skill import AzureMonitorSkill +from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion -## Learning Resources +# TODO: Import your new AnomalyDetectorSkill here -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ +async def main(): + kernel = Kernel() + kernel.add_service( + AzureChatCompletion( + service_id="chatcompletion", + deployment_name="your-deployment", + endpoint="your-endpoint", + api_key="your-api-key" + ) + ) -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + kernel.import_skill(AzureMonitorSkill(), "azure_monitor") -***Note:** Use descriptive text for each link instead of just URLs.* + # TODO: + # 1. Import and register the AnomalyDetectorSkill. + # 2. Retrieve live metrics using the Azure Monitor skill. + # 3. Pass the metrics to your anomaly detection function. + # 4. Print the result. -*Sample IoT resource links:* +if __name__ == "__main__": + asyncio.run(main()) +``` -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) +--- -## Tips +### Test Your Agent -*This section is optional and may be omitted.* +Run your agent script: + +```bash +python agents/anomaly_detector_agent.py +``` + +βœ… Expected Output: + +``` +CPU anomaly detected: 91.3% exceeds 80.0% +``` + +or + +``` +System metrics are within normal range. +``` + +--- + +### Learning Resources + +These resources will help you complete the challenge: + +* [Semantic Kernel Documentation](https://learn.microsoft.com/en-us/semantic-kernel/) +* [Azure Monitor Python SDK](https://learn.microsoft.com/en-us/python/api/overview/azure/monitor-query-readme) +* [Anomaly Detection in Azure](https://learn.microsoft.com/en-us/azure/ai-services/anomaly-detector/overview) +* [AsyncIO in Python](https://docs.python.org/3/library/asyncio.html) + +--- + +## Success Criteria -*Add tips and hints here to give students food for thought. Sample IoT tips:* +To successfully complete Challenge 02, you should be able to: -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. +- Verify that the **Anomaly Detector Agent** initializes without errors. +- Confirm that live metrics from your Azure VM (CPU, Memory, Disk I/O) are retrieved correctly. +- Demonstrate that the agent **detects anomalies** when metrics exceed defined thresholds. +- Show that the agent prints appropriate messages for both normal and anomalous states. +- Ensure that the skill and agent are **registered and callable** via Semantic Kernel. -## Advanced Challenges (Optional) -*If you want, you may provide additional goals to this challenge for folks who are eager.* +--- -*This section is optional and may be omitted.* +## Next Steps -*Sample IoT advanced challenges:* +Proceed to **[Challenge 03 – Build the Resource Optimizer Agent](./Challenge-03.md)** to: -Too comfortable? Eager to do more? Try these additional challenges! +* Respond to detected anomalies with remediation actions +* Enable multi-agent communication (Agent-to-Agent protocol) +* Begin orchestrating self-healing AI systems in Azure -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. +``` \ No newline at end of file diff --git a/xxx-AgenticAIApps/Student/Challenge-03.md b/xxx-AgenticAIApps/Student/Challenge-03.md index 88656873ba..cba2e52d96 100644 --- a/xxx-AgenticAIApps/Student/Challenge-03.md +++ b/xxx-AgenticAIApps/Student/Challenge-03.md @@ -1,99 +1,174 @@ -# Challenge 03 - <Title of Challenge> +````markdown +# Challenge 03 - Build the Resource Optimizer Agent (Real Azure Integration) [< Previous Challenge](./Challenge-02.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-04.md) -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** +--- -## Pre-requisites (Optional) +## Pre-requisites -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* +- Completion of **Challenge 02 – Anomaly Detection Agent** +- Active **Azure subscription** with access to a **Virtual Machine (VM)** +- `.env` file configured with your Azure details +- Working **Semantic Kernel setup** from previous challenges + +--- ## Introduction -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* +In this challenge, you will build a **Resource Optimizer Agent** capable of analyzing telemetry data (like CPU, memory, and disk usage) and performing **real optimization actions** in Azure using the **Azure Management SDK**. -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* +Your agent will listen for anomaly alerts and intelligently recommend or perform optimizations (like scaling VMs or restarting services). -*For example:* +This challenge introduces real-world **Azure SDK integration** β€” connecting the AI layer (Semantic Kernel) with the **Azure Compute Management API**. -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. +--- ## Description -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* +You’ll create and test a **Resource Optimizer Agent** that: +- Receives alerts about CPU, memory, or disk usage +- Determines an appropriate optimization strategy +- Executes the optimization using the **Azure SDK** -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* +> ⚠️ **Note:** Parts of the code are intentionally left incomplete. +> Fill in the missing functions to make your agent operational. -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* +--- -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* +### Environment Setup -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* +Install required SDKs: -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* +```bash +pip install azure-mgmt-compute azure-identity python-dotenv +```` -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* +Update your `.env` file with your Azure resource details: -*Sample challenge text for the IoT Hack Of The Century:* +```env +AZURESUBSCRIPTIONID=your-subscription-id +AZURERESOURCEGROUP=your-resource-group +AZUREVMNAME=your-vm-name +``` -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. +--- -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. +### Create `resource_optimizer.py` -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" +```python +import os +from azure.identity import DefaultAzureCredential +from azure.mgmt.compute import ComputeManagementClient +from azure.ai.foundry import Agent, Message, Thread +from dotenv import load_dotenv -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). +load_dotenv() -## Success Criteria +class ResourceOptimizerAgent(Agent): + def init(self): + super().init(name="resource-optimizer") -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + # TODO: Initialize Azure credentials and compute client + # Hint: Use DefaultAzureCredential() and ComputeManagementClient() + self.subscription_id = os.getenv("AZURESUBSCRIPTIONID") + self.resource_group = os.getenv("AZURERESOURCEGROUP") + self.vm_name = os.getenv("AZUREVMNAME") + pass -*The success criteria should not be a list of instructions.* + def run(self, thread: Thread, message: Message): + print("Optimizer received:", message.content) + response = "" -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + # TODO: Parse the message and decide what optimization to perform + # Example: if "CPU" in message.content β†’ call self.scale_vm("Standard_DS2_v2") -*Sample success criteria for the IoT sample challenge:* + thread.send_message(Message(content=response, role="agent")) -To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip + def scale_vm(self, new_size): + # TODO: Implement VM scaling logic using Azure SDK + # Hint: Retrieve the VM, modify its hardware profile, and use begin_create_or_update() + pass +``` -## Learning Resources +--- + +### Register the Agent + +Create a new file named `register_optimizer.py`: + +```python +from azure.ai.foundry import AgentClient +from resource_optimizer import ResourceOptimizerAgent + +client = AgentClient() +agent = ResourceOptimizerAgent() +client.register_agent(agent) +``` + +Run the registration script: + +```bash +python register_optimizer.py +``` + +--- -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ +### Test the Agent -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* +Create a new test file named `test_optimizer.py`: -***Note:** Use descriptive text for each link instead of just URLs.* +```python +from azure.ai.foundry import AgentClient -*Sample IoT resource links:* +client = AgentClient() +thread = client.create_thread() +client.send_message(thread.id, "⚠️ Anomaly detected: Percentage CPU = 92", agent_name="resource-optimizer") +``` -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) +Then execute: + +```bash +python test_optimizer.py +``` + +--- + +## Learning Resources + +* [Azure SDK for Python Documentation](https://learn.microsoft.com/en-us/python/api/overview/azure/) +* [Azure Compute Management Client](https://learn.microsoft.com/en-us/python/api/overview/azure/compute) +* [Azure Identity SDK](https://learn.microsoft.com/en-us/python/api/overview/azure/identity-readme) +* [Semantic Kernel Overview](https://learn.microsoft.com/en-us/semantic-kernel/overview) +* [Anomaly Detector Overview](https://learn.microsoft.com/en-us/azure/ai-services/anomaly-detector/overview) + +--- ## Tips -*This section is optional and may be omitted.* +* If you encounter authentication issues, ensure **Azure CLI** is logged in (`az login`). +* Start by **printing** messages before implementing full scaling logic. +* Use **try/except** around Azure SDK calls to handle errors gracefully. +* You can safely simulate optimization responses before executing real operations. + +--- -*Add tips and hints here to give students food for thought. Sample IoT tips:* +## Success Criteria -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. +To successfully complete Challenge 03, you should be able to: -## Advanced Challenges (Optional) +- Register and initialize the **Resource Optimizer Agent** without errors. +- Receive and display incoming anomaly messages correctly. +- Demonstrate that the agent can parse telemetry and respond (either by executing or simulating optimization). +- Confirm the agent is connected to **Semantic Kernel** and the **Azure SDK**. -*If you want, you may provide additional goals to this challenge for folks who are eager.* +--- -*This section is optional and may be omitted.* +## Next Steps -*Sample IoT advanced challenges:* +Once your **Resource Optimizer Agent** is working, move to **Challenge 04**, where you’ll build an **Alert Manager Agent** that coordinates notifications and alert responses across your system. + +[< Previous Challenge](./Challenge-02.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-04.md) -Too comfortable? Eager to do more? Try these additional challenges! +``` -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AgenticAIApps/Student/Challenge-04.md b/xxx-AgenticAIApps/Student/Challenge-04.md index a032304040..bf1fded423 100644 --- a/xxx-AgenticAIApps/Student/Challenge-04.md +++ b/xxx-AgenticAIApps/Student/Challenge-04.md @@ -1,99 +1,171 @@ -# Challenge 04 - <Title of Challenge> +````markdown +# Challenge 04 - Build the Alert Manager Agent (Live Azure Integration) [< Previous Challenge](./Challenge-03.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-05.md) -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** +## Pre-requisites -## Pre-requisites (Optional) +- Completion of Challenge 03 – Resource Optimizer Agent +- Active Azure subscription with Monitor and Action Groups access +- `.env` file updated with your Azure subscription, resource group, and action group name +- Installed dependencies: + ```bash + pip install azure-monitor-query azure-identity azure-mgmt-monitor python-dotenv +```` -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* +--- ## Introduction -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* +In this challenge, you’ll create the **Alert Manager Agent**, responsible for notifying stakeholders when anomalies or optimization events occur. +This agent integrates with **Azure Monitor** and **Action Groups**, allowing your system to deliver real-time alerts about critical events. -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* +You’ll implement alerting logic, test it in a safe β€œsimulation” mode, and prepare it to handle live alerts in later challenges. -*For example:* - -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. +--- ## Description -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* +Your goal is to build an agent that listens for incoming messages about anomalies or optimization results, and sends alerts using Azure Monitor or your chosen notification service. -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* +You’ll: -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* +* Create the **Alert Manager Agent** +* Detect when an anomaly or optimization event occurs +* Send (or simulate sending) alerts +* Ensure alerts appear in the terminal or Azure Action Group log -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* +> **Note:** Some code sections are intentionally left incomplete β€” you’ll implement the core alert logic and message handling yourself. -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* +--- -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* +### Create the Agent -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* +Create a new file called `alert_manager.py`: -*Sample challenge text for the IoT Hack Of The Century:* +```python +import os +from azure.identity import DefaultAzureCredential +from azure.mgmt.monitor import MonitorManagementClient +from azure.ai.foundry import Agent, Message, Thread +from dotenv import load_dotenv -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. +load_dotenv() -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. +class AlertManagerAgent(Agent): + def init(self): + super().init(name="alert-manager") + self.subscription_id = os.getenv("AZURESUBSCRIPTIONID") + self.resource_group = os.getenv("AZURERESOURCEGROUP") -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" + # TODO: Initialize the Azure Monitor client here + # Example: + # self.monitor_client = MonitorManagementClient( + # credential=DefaultAzureCredential(), + # subscription_id=self.subscription_id + # ) -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + def run(self, thread: Thread, message: Message): + print("Alert Manager received:", message.content) -## Success Criteria + # TODO: Detect anomaly or optimization message + # if "Anomaly" in message.content or "Optimization" in message.content: + # alert_msg = f"🚨 Alert triggered: {message.content}" + # thread.send_message(Message(content=alert_msg, role="agent")) + # print("Sending alert to Azure Monitor action group…") + # self.send_alert(alert_msg) -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + def send_alert(self, alert_msg): + # TODO: Implement your alert-sending logic (can be simulated for testing) + # print(f"Simulated alert sent: {alert_msg}") + pass +``` -*The success criteria should not be a list of instructions.* +--- -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* +### Register the Agent -*Sample success criteria for the IoT sample challenge:* +Create a file named `register_alert.py`: -To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip +```python +from azure.ai.foundry import AgentClient +from alert_manager import AlertManagerAgent -## Learning Resources +client = AgentClient() +agent = AlertManagerAgent() +client.register_agent(agent) +``` -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ +Run the registration: -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* +```bash +python register_alert.py +``` -***Note:** Use descriptive text for each link instead of just URLs.* +--- -*Sample IoT resource links:* +### Test the Agent -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) +Create a file named `test_alert.py`: -## Tips +```python +from azure.ai.foundry import AgentClient + +client = AgentClient() +thread = client.create_thread() -*This section is optional and may be omitted.* +# Simulate a message from the optimizer or anomaly agent +client.send_message( + thread.id, + "⚠️ Optimization failed due to high CPU usage", + agent_name="alert-manager" +) +``` -*Add tips and hints here to give students food for thought. Sample IoT tips:* +Run the test: -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. +```bash +python test_alert.py +``` -## Advanced Challenges (Optional) + **Expected Output Example:** + +``` +Alert Manager received: ⚠️ Optimization failed due to high CPU usage +🚨 Alert triggered: ⚠️ Optimization failed due to high CPU usage +Simulated alert sent: 🚨 Alert triggered: ⚠️ Optimization failed due to high CPU usage +``` + +--- + +## Learning Resources + +* [Azure Monitor Overview](https://learn.microsoft.com/en-us/azure/azure-monitor/overview) +* [Azure Monitor Action Groups](https://learn.microsoft.com/en-us/azure/azure-monitor/alerts/action-groups) +* [Azure Identity Python SDK](https://learn.microsoft.com/en-us/python/api/overview/azure/identity-readme) +* [Semantic Kernel Python Docs](https://learn.microsoft.com/en-us/semantic-kernel/overview/) + +--- + +## Tips + +* Keep your `.env` file clean (no quotes or extra spaces). +* You can safely test alerts by printing them to the terminal before enabling live alerts. +* Once verified, you can extend `send_alert()` to send real alerts through Azure Monitor’s **Action Groups** or webhooks. + +--- + +## Success Criteria -*If you want, you may provide additional goals to this challenge for folks who are eager.* +To complete this challenge successfully, you should: -*This section is optional and may be omitted.* +* Create and register an `AlertManagerAgent` class +* Implement message detection for anomalies or optimizations +* Simulate or send an alert through `send_alert()` +* Verify -*Sample IoT advanced challenges:* +## Next Steps -Too comfortable? Eager to do more? Try these additional challenges! +Proceed to **Challenge 05** to build the **Agent-to-Agent Communication Layer**, enabling collaboration and orchestration between all agents. -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. +``` diff --git a/xxx-AgenticAIApps/Student/Challenge-05.md b/xxx-AgenticAIApps/Student/Challenge-05.md index bc2fa34b49..f8046e6ec9 100644 --- a/xxx-AgenticAIApps/Student/Challenge-05.md +++ b/xxx-AgenticAIApps/Student/Challenge-05.md @@ -1,99 +1,130 @@ -# Challenge 05 - <Title of Challenge> +````markdown +# Challenge 05 - Orchestrate Agent-to-Agent Communicatio [< Previous Challenge](./Challenge-04.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-06.md) -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** - -## Pre-requisites (Optional) - -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* - ## Introduction -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* +In this challenge, you will connect all of your agentsβ€”**Anomaly Detector**, **Resource Optimizer**, and **Alert Manager**β€”into a unified communication system using an **Agent Orchestrator**. -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* +This orchestrator will serve as the bridge that enables agents to pass messages, share context, and execute tasks in sequence. -*For example:* +You will explore: +- How agents communicate through threads using the Azure AI Foundry SDK +- How to design message routing between independent components +- The foundations of semantic coordination for intelligent multi-agent workflows -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. +By completing this challenge, you’ll be able to design scalable, modular agent architectures where autonomous components work together in real time. -## Description +--- -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* - -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* +## Description -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* +Your task is to **implement the Agent Orchestrator** that manages the communication between your existing agents. -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* +## Learning Resources -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* +You will create two files: +- `agent_orchestrator.py` β€” defines the orchestration logic +- `run_orchestrator.py` β€” runs the orchestrator to test communication between agents -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* +The orchestrator should: +- Create a shared communication thread +- Trigger the **Anomaly Detector Agent** to check system metrics +- Trigger the **Resource Optimizer Agent** to respond to detected issues +- Trigger the **Alert Manager Agent** to notify stakeholders +- Display console messages confirming each step -*Sample challenge text for the IoT Hack Of The Century:* +Below is the incomplete code you will build upon: -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. +```python +from azure.ai.foundry import AgentClient, Thread +from dotenv import load_dotenv +import os -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. +load_dotenv() -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" +class AgentOrchestrator: + def __init__(self): + self.client = AgentClient() + self.agents = { + "anomaly": "anomaly-detector", + "optimizer": "resource-optimizer", + "alert": "alert-manager" + } -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + def create_thread(self): + # TODO: Create and return a new Thread + pass -## Success Criteria + def send_to_agent(self, thread: Thread, agent_key: str, message: str): + # TODO: Send a message to a specific agent using the client + pass -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + def orchestrate(self): + # TODO: Implement the orchestration flow: + # 1. Trigger anomaly detector + # 2. Trigger resource optimizer + # 3. Trigger alert manager + pass +```` -*The success criteria should not be a list of instructions.* +To execute your orchestrator, create a new script called `run_orchestrator.py`: -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* +```python +from agent_orchestrator import AgentOrchestrator -*Sample success criteria for the IoT sample challenge:* +orchestrator = AgentOrchestrator() +orchestrator.orchestrate() +``` -To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip +When you run this file, your output should look similar to: -## Learning Resources +``` + Step 1: Trigger Anomaly Detector + Step 2: Trigger Resource Optimizer + Step 3: Trigger Alert Manager + Orchestration complete. +``` -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ +--- -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* -***Note:** Use descriptive text for each link instead of just URLs.* +## Learning Resources -*Sample IoT resource links:* +* [Azure AI Foundry Overview](https://learn.microsoft.com/en-us/azure/ai-services/) +* [Azure Anomaly Detector Overview](https://learn.microsoft.com/en-us/azure/ai-services/anomaly-detector/overview) +* [Microsoft Semantic Kernel Documentation](https://learn.microsoft.com/en-us/semantic-kernel/) +* [Threading in Python (Real Python)](https://realpython.com/intro-to-python-threading/) +* [Introduction to Multi-Agent Systems (Microsoft Learn)](https://learn.microsoft.com/en-us/azure/ai-services/) -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) +--- ## Tips -*This section is optional and may be omitted.* +* Ensure your previous agents (Anomaly Detector, Resource Optimizer, Alert Manager) are correctly registered +* Test each message exchange individually before running the full orchestration +* Use logging statements to visualize the flow of messages between agents +* If you encounter threading errors, print the thread ID after creation to confirm proper initialization -*Add tips and hints here to give students food for thought. Sample IoT tips:* +--- -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. +## Success Criteria + +To complete this challenge successfully, you should be able to: -## Advanced Challenges (Optional) +* Validate that the orchestrator successfully creates a thread +* Verify that each agent receives and processes its assigned message +* Demonstrate that the console output confirms all three agent triggers +* Optionally, extend the orchestrator with a planning mechanism to dynamically decide which agent to trigger next -*If you want, you may provide additional goals to this challenge for folks who are eager.* +--- -*This section is optional and may be omitted.* +## Next Steps -*Sample IoT advanced challenges:* +After completing the Agent Orchestrator, you are ready to move on to **Challenge 06**, where you will implement **multi-agent planning and dynamic task scheduling** using Semantic Kernel. -Too comfortable? Eager to do more? Try these additional challenges! +This next challenge will build on your orchestrator to enable agents to make intelligent decisions, prioritize tasks, and collaborate autonomously based on real-time data. -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. +``` diff --git a/xxx-AgenticAIApps/Student/Challenge-06.md b/xxx-AgenticAIApps/Student/Challenge-06.md index 59e43d9bae..75a04c4bfe 100644 --- a/xxx-AgenticAIApps/Student/Challenge-06.md +++ b/xxx-AgenticAIApps/Student/Challenge-06.md @@ -1,99 +1,115 @@ -# Challenge 06 - <Title of Challenge> +````markdown +# Challenge 06 - Enable Agent-to-Agent Communication (A2A) [< Previous Challenge](./Challenge-05.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-07.md) -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** - -## Pre-requisites (Optional) - -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* - ## Introduction -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* +In this challenge, you will enhance your multi-agent system by enabling **direct communication between agents**. -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* +Your agentsβ€”**Anomaly Detector**, **Resource Optimizer**, and **Alert Manager**β€”will now share context and coordinate actions dynamically through a **shared thread**. -*For example:* +This step transforms your system from a static orchestration sequence into a **fully agentic network**, allowing agents to collaborate intelligently and make decisions based on previous outputs. -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. +You will also explore optional **Semantic Kernel integration** for dynamic planning and goal-driven agent behavior. + +--- ## Description -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* +Your task is to extend the orchestrator from Challenge 05 to enable **agent-to-agent communication**. -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* +You will: -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* +- Update `agent_orchestrator.py` to implement dynamic routing through shared threads. +- Ensure agents can read messages from the thread, respond appropriately, and pass results to the next agent. +- Optionally integrate Semantic Kernel for intelligent, goal-based agent planning. +- Modify `app.py` (if using a UI) to call the new dynamic orchestrator method. -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* +Below is a partial skeleton for your orchestrator logic. Complete the missing functionality: -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* +```python +def orchestratedynamic(self, user_input): + thread = self.create_thread() -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + # Step 1: Anomaly Detector + self.send_to_agent(thread, "anomaly", user_input) -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + # Step 2: Read anomaly message + messages = self.get_thread_messages(thread) + anomaly_msg = next((m.content for m in messages if "Anomaly" in m.content), None) -*Sample challenge text for the IoT Hack Of The Century:* + # Step 3: Resource Optimizer + if anomaly_msg: + self.send_to_agent(thread, "optimizer", anomaly_msg) -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + # Step 4: Read optimization message + messages = self.get_thread_messages(thread) + optimization_msg = next((m.content for m in messages if "πŸ› οΈ" in m.content), None) -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + # Step 5: Alert Manager + if optimization_msg: + self.send_to_agent(thread, "alert", optimization_msg) -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" + return self.get_thread_messages(thread) +```` -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). +### Optional: Semantic Kernel Planning -## Success Criteria +You may optionally add **goal-driven orchestration**: -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* +```python +from semantickernel import Kernel -*The success criteria should not be a list of instructions.* +kernel = Kernel() +plan = kernel.create_plan("Detect and respond to system anomalies") +for step in plan.steps: + orchestrator.send_to_agent(thread, step.plugin_name, step.description) +``` -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* +This enables your orchestrator to decide dynamically which agent to call next based on the context. -*Sample success criteria for the IoT sample challenge:* +--- -To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip ## Learning Resources -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ +* [Azure AI Foundry Overview](https://learn.microsoft.com/en-us/azure/ai-services/) +* [Python Threading & Concurrency](https://realpython.com/intro-to-python-threading/) +* [Introduction to Multi-Agent Systems](https://learn.microsoft.com/en-us/azure/architecture/guide/ai/design-multi-agent-systems) +* [Empowering Multi-Agent Apps with the Open Agent2Agent (A2A) Protocol](https://www.microsoft.com/en-us/microsoft-cloud/blog/2025/05/07/empowering-multi-agent-apps-with-the-open-agent2agent-a2a-protocol/?utm_source=chatgpt.com) -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* +--- -***Note:** Use descriptive text for each link instead of just URLs.* - -*Sample IoT resource links:* +## Tips -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) +* Test each agent individually before running the full orchestrator. +* Use logging statements to visualize message flow in the shared thread. +* Make sure thread messages are correctly tagged with agent names to aid debugging. +* Start simple: first pass static messages, then add dynamic routing logic. -## Tips -*This section is optional and may be omitted.* +--- -*Add tips and hints here to give students food for thought. Sample IoT tips:* +## Success Criteria -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. +To complete this challenge successfully, you should be able to: -## Advanced Challenges (Optional) +* Verify that all three agents communicate through a shared thread. +* Confirm that messages from one agent are correctly routed to the next. +* Demonstrate console output showing step-by-step interactions: -*If you want, you may provide additional goals to this challenge for folks who are eager.* +``` +anomaly-detector: Anomaly detected: CPU = 92% +resource-optimizer: Scaling VM to Standard_DS2_v2 +alert-manager: Alert sent: VM scaled successfully +``` -*This section is optional and may be omitted.* +* Optionally, show dynamic routing with Semantic Kernel if implemented. +--- -*Sample IoT advanced challenges:* +## Next Steps -Too comfortable? Eager to do more? Try these additional challenges! +Proceed to **Challenge 07** to implement **memory persistence**, long-term knowledge storage, and context-aware planning to make your agents even more autonomous and intelligent. -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. +``` diff --git a/xxx-AgenticAIApps/Student/Challenge-07.md b/xxx-AgenticAIApps/Student/Challenge-07.md index 82cb7e727e..a70447fd2b 100644 --- a/xxx-AgenticAIApps/Student/Challenge-07.md +++ b/xxx-AgenticAIApps/Student/Challenge-07.md @@ -1,99 +1,156 @@ -# Challenge 07 - <Title of Challenge> +````markdown +# Challenge 07 - Build the Anomaly & Resolution Tracker [< Previous Challenge](./Challenge-06.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-08.md) -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** +## Introduction -## Pre-requisites (Optional) +In this challenge, you will build a **tracking system** to log anomalies detected by your **Anomaly Detector Agent** and resolutions applied by your **Resource Optimizer Agent**. -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* +This system will help you visualize events in real time and optionally integrate with dashboards like **Streamlit**, **Power BI**, or **Azure Workbooks**. -## Introduction +You will explore: +- Logging and storing agent actions +- Structuring log data for clarity +- Visualizing agent activity locally or in the cloud +- Optional integration with Azure storage services for persistence -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* +--- -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* +## Description -*For example:* +Your task is to **implement anomaly and resolution tracking** for your agent system. -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. +Key goals: +- Create logging for both anomaly detection and resolution events +- Maintain a **consistent log format** for easy parsing and visualization +- Optionally build a **Streamlit dashboard** to view logs interactively +- Optionally store logs in **Azure Table Storage** or **Cosmos DB** for cloud-based tracking -## Description +Skeleton example for logging: -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* +### Anomaly Detector Agent -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* +```python +import logging -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* +logging.basicConfig(filename='agent_log.txt', level=logging.INFO, format='[%(asctime)s] %(message)s') -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* +def log_anomaly(metric, value): + # TODO: Call this function whenever an anomaly is detected + logging.info(f"Anomaly Detected: {metric} = {value}") +```` -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* +### Resource Optimizer Agent -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* +```python +def log_resolution(action): + # TODO: Call this function after performing a resolution + logging.info(f"Resolution Applied: {action}") +``` -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* +--- -*Sample challenge text for the IoT Hack Of The Century:* +### Log Format Example -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. +``` +[2025-08-21 14:32:10] Anomaly Detected: CPU = 92% +[2025-08-21 14:32:15] Resolution Applied: Scaled VM to Standard_DS2_v2 +``` -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. +> **Tip:** Using timestamps helps track and visualize event sequences effectively. -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" +--- -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). +### Optional β€” Streamlit Dashboard -## Success Criteria +Create **`dashboard.py`**: -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* +```python +import streamlit as st -*The success criteria should not be a list of instructions.* +st.title("πŸ” Anomaly & Resolution Tracker") -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* +with open("agent_log.txt") as f: + logs = f.readlines() -*Sample success criteria for the IoT sample challenge:* +for line in logs: + st.text(line.strip()) +``` -To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip +Run the dashboard: -## Learning Resources +```bash +streamlit run dashboard.py +``` -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ +--- -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* +### Optional β€” Azure Storage Integration -***Note:** Use descriptive text for each link instead of just URLs.* +**Azure Table Storage** -*Sample IoT resource links:* +```bash +pip install azure-data-tables +``` -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) +```python +from azure.data.tables import TableServiceClient +from datetime import datetime +import os -## Tips +service = TableServiceClient.from_connection_string(conn_str=os.getenv("AZURE_STORAGE_CONNECTION_STRING")) +table_client = service.get_table_client(table_name="AgentLogs") + +def log_to_table(event_type, detail): + entity = { + "PartitionKey": "AgentLogs", + "RowKey": str(datetime.utcnow().timestamp()), + "EventType": event_type, + "Detail": detail + } + table_client.create_entity(entity) +``` + +**Azure Cosmos DB** can also be used to store structured JSON logs for advanced analytics. -*This section is optional and may be omitted.* +--- -*Add tips and hints here to give students food for thought. Sample IoT tips:* +## Success Criteria + +To complete this challenge successfully, you should be able to: + +* Validate that the **Anomaly Detector Agent** logs anomalies +* Validate that the **Resource Optimizer Agent** logs resolutions +* Demonstrate that logs are readable and follow a consistent format +* Optionally show the **Streamlit dashboard** displaying live logs +* Optionally store and retrieve logs from **Azure Table Storage** or **Cosmos DB** + +--- -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. +## Learning Resources + +* [Python Logging Module](https://docs.python.org/3/library/logging.html) – Learn how to log messages with timestamps +* [Streamlit Documentation](https://docs.streamlit.io/) – Guide to building interactive dashboards +* [Azure Data Tables](https://learn.microsoft.com/en-us/azure/storage/tables/table-storage-overview) – Overview of Azure Table Storage +* [Azure Cosmos DB Python SDK](https://learn.microsoft.com/en-us/python/api/overview/azure/cosmos-db?view=azure-python) – Learn to store JSON documents in Cosmos DB + +--- + +## Tips -## Advanced Challenges (Optional) +* Start by logging to a local file before moving to cloud storage +* Keep log formats consistent for easier visualization +* Use small sample data to verify the Streamlit dashboard works before scaling -*If you want, you may provide additional goals to this challenge for folks who are eager.* +--- -*This section is optional and may be omitted.* +## Next Steps -*Sample IoT advanced challenges:* +Proceed to **Challenge 08** to extend your tracking system with: -Too comfortable? Eager to do more? Try these additional challenges! +* Persistent memory across agent sessions +* Advanced analytics for anomaly trends +* Automated reporting using Azure AI Foundry -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. +``` diff --git a/xxx-AgenticAIApps/Student/Challenge-08.md b/xxx-AgenticAIApps/Student/Challenge-08.md index 4fffe19429..327910dcd9 100644 --- a/xxx-AgenticAIApps/Student/Challenge-08.md +++ b/xxx-AgenticAIApps/Student/Challenge-08.md @@ -1,99 +1,142 @@ -# Challenge 08 - <Title of Challenge> +````markdown +# Challenge 08 - Spike VM Resources & Test Agent Detection -[< Previous Challenge](./Challenge-07.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-09.md) +[< Previous Challenge](./Challenge-07.md) - **[Home](../README.md)** -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** +## Introduction -## Pre-requisites (Optional) +In this challenge, you will temporarily **spike CPU and memory** on the Azure VM you have been maintaining since the initial challenges. -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* +The goal is to **test your agents** β€” Anomaly Detector, Resource Optimizer, and Alert Manager β€” and observe how they respond in real time. -## Introduction +You will use the **provided test scripts** to generate the resource spike, so you do not need to write any additional agent code for this challenge. -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* +> **Important:** You must be connected to Azure using `az login` before starting this challenge, so your agents can access the VM telemetry and management APIs. -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* +--- -*For example:* +## Description -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. +Students are expected to: -## Description +- Use the provided stress scripts (`spike_vm.sh` for Linux/macOS or `spike_vm.ps1` for Windows) to create a temporary load on the VM. +- Run your agents using the provided orchestrator or test scripts (`test_anomaly.py` or `run_orchestrator.py`). +- Verify that your agents detect the anomalies and log or respond appropriately. +- Meet the success criteria to complete the What The Hack challenge. -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* +> **Important:** The VM used should be the same one you kept active from the initial challenges. This ensures continuity of testing and monitoring. -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* +--- -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* +## Learning Resources -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* +To help you complete this challenge and work with the VM: -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* +* [Connect to an Azure VM using SSH](https://learn.microsoft.com/en-us/azure/virtual-machines/linux/ssh-from-windows) – Step-by-step guide for connecting to Linux VMs from your terminal. +* [Bash Basics for Beginners](https://www.gnu.org/software/bash/manual/bash.html) – Introduction to Bash scripting and commands. +* [Linux Command Line Tutorial](https://ryanstutorials.net/linuxtutorial/) – Learn basic Linux commands and navigation. +* [Azure CLI Documentation](https://learn.microsoft.com/en-us/cli/azure/) – How to interact with Azure resources using `az login` and CLI commands. -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* +--- -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* +### Establish a Baseline -*Sample challenge text for the IoT Hack Of The Century:* +Before spiking resources, confirm your agents report **no anomalies**: -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. +```bash +python test_anomaly.py +# or +python run_orchestrator.py +```` -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. +This establishes the baseline for detecting changes. -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" +--- -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). +### Run the Stress Script -## Success Criteria +**Linux/macOS – `spike_vm.sh`** -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* +```bash +chmod +x spike_vm.sh +./spike_vm.sh 45 1024 +``` -*The success criteria should not be a list of instructions.* +**Windows – `spike_vm.ps1`** -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* +```powershell +Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force +.\spike_vm.ps1 -Duration 45 +``` -*Sample success criteria for the IoT sample challenge:* +These scripts will temporarily increase CPU and memory usage on the VM. -To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip +--- -## Learning Resources +### Run Agents During Spike + +Immediately after starting the spike: -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ +```bash +python test_anomaly.py +# or +python run_orchestrator.py +``` -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* +* **Anomaly Detector Agent** should detect high CPU/memory. +* **Resource Optimizer Agent** may suggest scaling or other resolutions. +* **Alert Manager Agent** may log or simulate alerts. -***Note:** Use descriptive text for each link instead of just URLs.* +--- -*Sample IoT resource links:* +### Verify Logs -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) +```bash +# Linux/macOS +tail -f agent_log.txt -## Tips +# Windows PowerShell +Get-Content .\agent_log.txt -Wait +``` -*This section is optional and may be omitted.* +Expected entries: -*Add tips and hints here to give students food for thought. Sample IoT tips:* +``` +[2025-10-11 15:22:00] Anomaly Detected: CPU = 98% +[2025-10-11 15:22:05] Resolution Applied: Suggested VM scale-up +``` -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. +--- -## Advanced Challenges (Optional) +### Stop the Stress Script + +**Linux/macOS:** + +```bash +pkill -f 'md5sum' +``` + +**Windows PowerShell:** + +```powershell +Get-Job | Where-Object { $_.State -eq 'Running' } | ForEach-Object { Stop-Job -Job $_; Remove-Job -Job $_ } +Remove-Variable memBlocks -ErrorAction SilentlyContinue -Scope Global +[GC]::Collect(); [GC]::WaitForPendingFinalizers() +Write-Host "Stress jobs stopped and memory released." +``` + +--- + +## Success Criteria -*If you want, you may provide additional goals to this challenge for folks who are eager.* +To successfully complete this challenge (and the What The Hack challenge), students must: -*This section is optional and may be omitted.* +* Run the **provided spike script** on the maintained VM. +* Show that all agents detect anomalies during the spike. +* Demonstrate that resolutions or recommendations are logged correctly. +* Optionally, provide screenshots of agent alerts or Streamlit dashboard updates. -*Sample IoT advanced challenges:* +> **Completion of this step successfully indicates that your agents are functioning correctly and the challenge is complete.** -Too comfortable? Eager to do more? Try these additional challenges! +--- -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. From 4a27a214ba746e938f750b66437f4224fd867f53 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <eruiz005@wilmu.edu> Date: Thu, 16 Oct 2025 06:55:10 -0400 Subject: [PATCH 07/34] [New Hack] Agentic AI Apps --- xxx-AgenticAIApps/README.md | 48 ------------------------------------- 1 file changed, 48 deletions(-) delete mode 100644 xxx-AgenticAIApps/README.md diff --git a/xxx-AgenticAIApps/README.md b/xxx-AgenticAIApps/README.md deleted file mode 100644 index b38bb41725..0000000000 --- a/xxx-AgenticAIApps/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# What The Hack - AgenticAIApps - -## Introduction - -The IoT Hack of the Century will take you on a whirlwind tour in the world of IoT and how it is being used in the modern world of mineral extraction in exotic locations like the Arctic and the wilds of South Africa. - -## Learning Objectives - -In this hack you will be solving the common business problem that companies in the mineral extraction industry face and how IoT solutions from Azure are brought to bare - -1. Provision an IoT Hub -2. Set up an IoT Edge device -3. Bring Azure Sphere to your solution for scale and resiliency - -## Challenges - -- Challenge 00: **[Prerequisites - Ready, Set, GO!](Student/Challenge-00.md)** - - Prepare your workstation to work with Azure. -- Challenge 01: **[Title of Challenge](Student/Challenge-01.md)** - - Description of challenge -- Challenge 02: **[Title of Challenge](Student/Challenge-02.md)** - - Description of challenge -- Challenge 03: **[Title of Challenge](Student/Challenge-03.md)** - - Description of challenge -- Challenge 04: **[Title of Challenge](Student/Challenge-04.md)** - - Description of challenge -- Challenge 05: **[Title of Challenge](Student/Challenge-05.md)** - - Description of challenge -- Challenge 06: **[Title of Challenge](Student/Challenge-06.md)** - - Description of challenge -- Challenge 07: **[Title of Challenge](Student/Challenge-07.md)** - - Description of challenge -- Challenge 08: **[Title of Challenge](Student/Challenge-08.md)** - - Description of challenge -- Challenge 09: **[Title of Challenge](Student/Challenge-09.md)** - - Description of challenge - -## Prerequisites - -- Your own Azure subscription with Owner access -- Visual Studio Code -- Azure CLI -- An AVNET X231 device - -## Contributors - -- Jane Q. Public -- Joe T. Muppet From dbf54100b41a567b6b5483bf1ee68e85c2ece308 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 02:44:25 -0500 Subject: [PATCH 08/34] Update Solution-00.md --- xxx-AgenticAIApps/Coach/Solution-00.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-00.md b/xxx-AgenticAIApps/Coach/Solution-00.md index 5e737ae3f3..17c52993ee 100644 --- a/xxx-AgenticAIApps/Coach/Solution-00.md +++ b/xxx-AgenticAIApps/Coach/Solution-00.md @@ -2,7 +2,7 @@ **[Home](./README.md)** - [Next Solution >](./Solution-00.md) -```markdown + # Challenge 00 - Azure AI Foundry Onboarding & Environment Prep - Coach's Guide **[Home](./README.md)** - [Next Solution >](./Solution-00.md) From 1e122ee596d69730372d728e0ab8c6e99f707a81 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 02:45:35 -0500 Subject: [PATCH 09/34] Update Solution-02.md --- xxx-AgenticAIApps/Coach/Solution-02.md | 1 - 1 file changed, 1 deletion(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-02.md b/xxx-AgenticAIApps/Coach/Solution-02.md index 39506e6930..3171c42a40 100644 --- a/xxx-AgenticAIApps/Coach/Solution-02.md +++ b/xxx-AgenticAIApps/Coach/Solution-02.md @@ -1,4 +1,3 @@ -````markdown # Challenge 2 - Build the Anomaly Detector Agent (Real Azure Metrics) - Coach's Guide [< Previous Solution](./Solution-02.0.md) - **[Home](../README.md)** - [Next Solution >](./Solution-04.md) From b412e5bef3acca31911716d9d8ebd939d1b1b46a Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 02:46:32 -0500 Subject: [PATCH 10/34] Update Solution-03.md --- xxx-AgenticAIApps/Coach/Solution-03.md | 1 - 1 file changed, 1 deletion(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-03.md b/xxx-AgenticAIApps/Coach/Solution-03.md index 2e4b8e3340..7d5ebf1390 100644 --- a/xxx-AgenticAIApps/Coach/Solution-03.md +++ b/xxx-AgenticAIApps/Coach/Solution-03.md @@ -1,4 +1,3 @@ -````markdown # Challenge 03 - Build the Resource Optimizer Agent (Real Azure Integration) - Coach's Guide [< Previous Solution](./Solution-02.md) - **[Home](../README.md)** - [Next Solution >](./Solution-04.md) From f34738d30fecd30b196d57d87b851c139158f6c3 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 02:47:53 -0500 Subject: [PATCH 11/34] Update Solution-04.md --- xxx-AgenticAIApps/Coach/Solution-04.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-04.md b/xxx-AgenticAIApps/Coach/Solution-04.md index 1201421127..ac6aa77cb0 100644 --- a/xxx-AgenticAIApps/Coach/Solution-04.md +++ b/xxx-AgenticAIApps/Coach/Solution-04.md @@ -1,4 +1,3 @@ -````markdown # Challenge 04 - Build the Alert Manager Agent (Live Azure Integration) - Coach's Guide [< Previous Solution](./Solution-03.md) - **[Home](../README.md)** - [Next Solution >](./Solution-05.md) @@ -114,7 +113,7 @@ Expected Output: ``` Alert Manager received: ⚠️ Optimization failed due to high CPU usage -🚨 Alert triggered: ⚠️ Optimization failed due to high CPU usage +Alert triggered: ⚠️ Optimization failed due to high CPU usage Simulated alert sent: 🚨 Alert triggered: ⚠️ Optimization failed due to high CPU usage ``` From 43eaa2a30c2f6731c8abda014d90b696ce4c0e31 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 02:49:04 -0500 Subject: [PATCH 12/34] Update Solution-05.md --- xxx-AgenticAIApps/Coach/Solution-05.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-05.md b/xxx-AgenticAIApps/Coach/Solution-05.md index c7d7bcdf3e..4fde41bd74 100644 --- a/xxx-AgenticAIApps/Coach/Solution-05.md +++ b/xxx-AgenticAIApps/Coach/Solution-05.md @@ -1,12 +1,10 @@ -```markdown # Challenge 05 - Orchestrate Agent-to-Agent Communication - Coach's Guide [< Previous Solution](./Solution-04.md) - **[Home](../README.md)** - [Next Solution >](./Solution-06.md) ## Notes & Guidance -This challenge connects all previous agents β€” **Anomaly Detector**, **Resource Optimizer**, and **Alert Manager** β€” into a unified system. -It introduces **message routing**, **shared threads for memory**, and optional **Semantic Kernel planning** for adaptive orchestration. +This challenge connects all previous agents β€” **Anomaly Detector**, **Resource Optimizer**, and **Alert Manager** β€” into a unified system. It introduces **message routing**, **shared threads for memory**, and optional **Semantic Kernel planning** for adaptive orchestration. --- From 2a89820ac883611dbb7144281cc6eef54686f4c6 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 02:49:55 -0500 Subject: [PATCH 13/34] Update Solution-04.md --- xxx-AgenticAIApps/Coach/Solution-04.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-04.md b/xxx-AgenticAIApps/Coach/Solution-04.md index ac6aa77cb0..9f831403ef 100644 --- a/xxx-AgenticAIApps/Coach/Solution-04.md +++ b/xxx-AgenticAIApps/Coach/Solution-04.md @@ -4,8 +4,7 @@ ## Notes & Guidance -In this challenge, participants build an **Alert Manager Agent** that notifies stakeholders when anomalies or optimizations occur. -This involves integrating with **Azure Monitor Action Groups** and simulating real-world alert handling within an agentic workflow. +In this challenge, participants build an **Alert Manager Agent** that notifies stakeholders when anomalies or optimizations occur. This involves integrating with **Azure Monitor Action Groups** and simulating real-world alert handling within an agentic workflow. --- From 4c56695283a6262fb76bb2111050b9b0011109af Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 02:52:16 -0500 Subject: [PATCH 14/34] Update Solution-06.md --- xxx-AgenticAIApps/Coach/Solution-06.md | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-06.md b/xxx-AgenticAIApps/Coach/Solution-06.md index 49580527a8..a58ea1bc68 100644 --- a/xxx-AgenticAIApps/Coach/Solution-06.md +++ b/xxx-AgenticAIApps/Coach/Solution-06.md @@ -1,12 +1,10 @@ -````markdown # Challenge 06 - Enable Agent-to-Agent Communication (A2A) - Coach's Guide [< Previous Solution](./Solution-05.md) - **[Home](./README.md)** - [Next Solution >](./Solution-07.md) ## Notes & Guidance -In this challenge, participants enable **real-time communication between Azure Agents**, allowing them to exchange context and coordinate actions. -This marks the transition from isolated automation to a **collaborative, agentic network** powered by shared threads and dynamic planning. +In this challenge, participants enable **real-time communication between Azure Agents**, allowing them to exchange context and coordinate actions. This marks the transition from isolated automation to a **collaborative, agentic network** powered by shared threads and dynamic planning. --- @@ -62,7 +60,7 @@ def orchestrate_dynamic(self, user_input): --- -## βš™οΈ Update the App to Use Dynamic Orchestration +## Update the App to Use Dynamic Orchestration Update `app.py` so user input triggers your new dynamic orchestration: @@ -95,7 +93,7 @@ alert-manager: Notification sent to admin --- -## πŸ€– Optional: Semantic Kernel Integration +## Optional: Semantic Kernel Integration For adaptive task routing, integrate **Microsoft Semantic Kernel**: @@ -144,8 +142,3 @@ Proceed to **Challenge 07** to extend your agentic system with: All sections marked with `πŸ”Ή STUDENT MISSING SECTION` are **what students were expected to implement themselves** in the student guide. Coaches can reference these to confirm the correctness of submitted solutions. - -``` - -Would you like me to continue with **Challenge 07 (Anomaly & Resolution Tracker)** in the same GitHub-ready format next? -``` From 7664257b738454a6d5eabf9e5ec9f26fa05626d5 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 02:53:23 -0500 Subject: [PATCH 15/34] Update Solution-07.md --- xxx-AgenticAIApps/Coach/Solution-07.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-07.md b/xxx-AgenticAIApps/Coach/Solution-07.md index 9e73bb00cc..19882c3d38 100644 --- a/xxx-AgenticAIApps/Coach/Solution-07.md +++ b/xxx-AgenticAIApps/Coach/Solution-07.md @@ -1,12 +1,10 @@ -````markdown # Challenge 07 - Build the Anomaly & Resolution Tracker - Coach's Guide [< Previous Solution](./Solution-06.md) - **[Home](./README.md)** - [Next Solution >](./Solution-08.md) ## Notes & Guidance -In this challenge, participants will **track anomalies and resolutions** detected by their Azure Agents and visualize the results in real time. -You’ll implement lightweight logging, optionally add a Streamlit dashboard, and explore Azure-based storage options for enterprise-scale tracking. +In this challenge, participants will **track anomalies and resolutions** detected by their Azure Agents and visualize the results in real time. You’ll implement lightweight logging, optionally add a Streamlit dashboard, and explore Azure-based storage options for enterprise-scale tracking. --- From fa7aff7b497b6b674c48a48acce3111f73ec899d Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 02:54:41 -0500 Subject: [PATCH 16/34] Update Solution-08.md --- xxx-AgenticAIApps/Coach/Solution-08.md | 1 - 1 file changed, 1 deletion(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-08.md b/xxx-AgenticAIApps/Coach/Solution-08.md index 8fc41677ad..8e35cf2da7 100644 --- a/xxx-AgenticAIApps/Coach/Solution-08.md +++ b/xxx-AgenticAIApps/Coach/Solution-08.md @@ -1,4 +1,3 @@ -````markdown # Challenge 008 – Spike VM Resources & Test Agent Detection – Coach's Guide [< Previous Solution](./Solution-005.md) - **[Home](./README.md)** From 7f7c8d878e9eb1ec0996bc5a143af53251cb44fe Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 02:57:01 -0500 Subject: [PATCH 17/34] Delete xxx-AgenticAIApps/Coach/Solution-09.md --- xxx-AgenticAIApps/Coach/Solution-09.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 xxx-AgenticAIApps/Coach/Solution-09.md diff --git a/xxx-AgenticAIApps/Coach/Solution-09.md b/xxx-AgenticAIApps/Coach/Solution-09.md deleted file mode 100644 index e69de29bb2..0000000000 From a4e4494b94b56299ddf9f4de1c2d1a2bd857c9c4 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:00:32 -0500 Subject: [PATCH 18/34] Update Solution-00.md --- xxx-AgenticAIApps/Coach/Solution-00.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-00.md b/xxx-AgenticAIApps/Coach/Solution-00.md index 17c52993ee..b4741895b1 100644 --- a/xxx-AgenticAIApps/Coach/Solution-00.md +++ b/xxx-AgenticAIApps/Coach/Solution-00.md @@ -1,8 +1,3 @@ -# Challenge 00 - Azure AI Foundry Onboarding & Environment Prep - Coach's Guide - -**[Home](./README.md)** - [Next Solution >](./Solution-00.md) - - # Challenge 00 - Azure AI Foundry Onboarding & Environment Prep - Coach's Guide **[Home](./README.md)** - [Next Solution >](./Solution-00.md) From 1b870fcb4ea616a39d2c0636703fa4aede728b5a Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:01:21 -0500 Subject: [PATCH 19/34] Update Solution-00.md --- xxx-AgenticAIApps/Coach/Solution-00.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-00.md b/xxx-AgenticAIApps/Coach/Solution-00.md index b4741895b1..f90d9aef60 100644 --- a/xxx-AgenticAIApps/Coach/Solution-00.md +++ b/xxx-AgenticAIApps/Coach/Solution-00.md @@ -1,6 +1,6 @@ # Challenge 00 - Azure AI Foundry Onboarding & Environment Prep - Coach's Guide -**[Home](./README.md)** - [Next Solution >](./Solution-00.md) +**[Home](./README.md)** - [Next Solution >](./Solution-01.md) ## Notes & Guidance From 59f7af00025bc8820d265ae8ec292964f97ec0f3 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:02:09 -0500 Subject: [PATCH 20/34] Update Solution-00.md --- xxx-AgenticAIApps/Coach/Solution-00.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-00.md b/xxx-AgenticAIApps/Coach/Solution-00.md index f90d9aef60..6dfb90a741 100644 --- a/xxx-AgenticAIApps/Coach/Solution-00.md +++ b/xxx-AgenticAIApps/Coach/Solution-00.md @@ -106,7 +106,7 @@ Tip: Keep your `.env` and Foundry configuration handy β€” you’ll reuse them th --- -Proceed to **[Challenge 001 – Semantic Kernel Setup & Configuration](./Solution-001.md)** to: +Proceed to **[Challenge 001 – Semantic Kernel Setup & Configuration](./Solution-01.md)** to: - Integrate **Semantic Kernel** for planning and reasoning. - Explore how prompts, skills, and plugins form the cognitive layer of your agents. - Learn how agents interpret natural language requests and turn them into structured actions. From 8e1a9947564939d2927531bb3aa220648b7eeb94 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:03:29 -0500 Subject: [PATCH 21/34] Update Solution-02.md --- xxx-AgenticAIApps/Coach/Solution-02.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-02.md b/xxx-AgenticAIApps/Coach/Solution-02.md index 3171c42a40..b730dfbdcc 100644 --- a/xxx-AgenticAIApps/Coach/Solution-02.md +++ b/xxx-AgenticAIApps/Coach/Solution-02.md @@ -1,6 +1,6 @@ # Challenge 2 - Build the Anomaly Detector Agent (Real Azure Metrics) - Coach's Guide -[< Previous Solution](./Solution-02.0.md) - **[Home](../README.md)** - [Next Solution >](./Solution-04.md) +[< Previous Solution](./Solution-01.md) - **[Home](../README.md)** - [Next Solution >](./Solution-03.md) ## Notes & Guidance From 50de4d06e13f7dff53de80c1c50a376fce292ef6 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:07:23 -0500 Subject: [PATCH 22/34] Update Solution-02.md --- xxx-AgenticAIApps/Coach/Solution-02.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-02.md b/xxx-AgenticAIApps/Coach/Solution-02.md index b730dfbdcc..7183848ed2 100644 --- a/xxx-AgenticAIApps/Coach/Solution-02.md +++ b/xxx-AgenticAIApps/Coach/Solution-02.md @@ -1,6 +1,7 @@ # Challenge 2 - Build the Anomaly Detector Agent (Real Azure Metrics) - Coach's Guide -[< Previous Solution](./Solution-01.md) - **[Home](../README.md)** - [Next Solution >](./Solution-03.md) +[< Previous Solution](./Solution-01.md) - **[Home](./README.md)** - [Next Solution >](./Solution-03.md) + ## Notes & Guidance From 2562a0ed4e9b60d914b8301d257cef8b2c624269 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:08:03 -0500 Subject: [PATCH 23/34] Update Solution-03.md --- xxx-AgenticAIApps/Coach/Solution-03.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-03.md b/xxx-AgenticAIApps/Coach/Solution-03.md index 7d5ebf1390..c93281c8f0 100644 --- a/xxx-AgenticAIApps/Coach/Solution-03.md +++ b/xxx-AgenticAIApps/Coach/Solution-03.md @@ -1,6 +1,6 @@ # Challenge 03 - Build the Resource Optimizer Agent (Real Azure Integration) - Coach's Guide -[< Previous Solution](./Solution-02.md) - **[Home](../README.md)** - [Next Solution >](./Solution-04.md) +[< Previous Solution](./Solution-02.md) - **[Home](./README.md)** - [Next Solution >](./Solution-04.md) ## Notes & Guidance From a4ad8534c2b33344b87eee78fe47d2749cf95f6a Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:08:46 -0500 Subject: [PATCH 24/34] Update Solution-04.md --- xxx-AgenticAIApps/Coach/Solution-04.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-04.md b/xxx-AgenticAIApps/Coach/Solution-04.md index 9f831403ef..cbff493c6e 100644 --- a/xxx-AgenticAIApps/Coach/Solution-04.md +++ b/xxx-AgenticAIApps/Coach/Solution-04.md @@ -1,6 +1,6 @@ # Challenge 04 - Build the Alert Manager Agent (Live Azure Integration) - Coach's Guide -[< Previous Solution](./Solution-03.md) - **[Home](../README.md)** - [Next Solution >](./Solution-05.md) +[< Previous Solution](./Solution-03.md) - **[Home](./README.md)** - [Next Solution >](./Solution-05.md) ## Notes & Guidance From 7208da552dc3d07c53afe3b6278faf8f77e48685 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:10:45 -0500 Subject: [PATCH 25/34] Update Solution-08.md --- xxx-AgenticAIApps/Coach/Solution-08.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xxx-AgenticAIApps/Coach/Solution-08.md b/xxx-AgenticAIApps/Coach/Solution-08.md index 8e35cf2da7..d7ec9f5aaa 100644 --- a/xxx-AgenticAIApps/Coach/Solution-08.md +++ b/xxx-AgenticAIApps/Coach/Solution-08.md @@ -1,6 +1,6 @@ # Challenge 008 – Spike VM Resources & Test Agent Detection – Coach's Guide -[< Previous Solution](./Solution-005.md) - **[Home](./README.md)** +[< Previous Solution](./Solution-07.md) - **[Home](./README.md)** ## Goal Temporarily spike CPU and memory on your VM to test agent detection. From 4b5782240967500d7a1062e0134627d229d28c11 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:14:43 -0500 Subject: [PATCH 26/34] Update Challenge-01.md --- xxx-AgenticAIApps/Student/Challenge-01.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/xxx-AgenticAIApps/Student/Challenge-01.md b/xxx-AgenticAIApps/Student/Challenge-01.md index af70d7dd87..9f1c10d08b 100644 --- a/xxx-AgenticAIApps/Student/Challenge-01.md +++ b/xxx-AgenticAIApps/Student/Challenge-01.md @@ -1,7 +1,6 @@ -````markdown # Challenge 01 - Semantic Kernel Setup & Configuration -[< Previous Challenge](./Challenge-00.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-02.md) +[< Previous Challenge](./Challenge-00.md) - **[Home](./README.md)** - [Next Challenge >](./Challenge-02.md) --- @@ -41,7 +40,7 @@ This includes: ### Skeleton Example (`azure_monitor_skill.py`) ```python -# students implement this +# students complete building this section class AzureMonitorSkill: def __init__(self): @@ -84,6 +83,6 @@ To complete this challenge successfully, you should be able to: 4. Explain how the kernel can be extended to pull **live telemetry** from Azure -[< Previous Challenge](./Challenge-00.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-02.md) +[< Previous Challenge](./Challenge-00.md) - **[Home](./README.md)** - [Next Challenge >](./Challenge-02.md) ``` From e90ebea96ba10f1e78d00bb55904561d1afba6fd Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:16:12 -0500 Subject: [PATCH 27/34] Update Challenge-02.md --- xxx-AgenticAIApps/Student/Challenge-02.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/xxx-AgenticAIApps/Student/Challenge-02.md b/xxx-AgenticAIApps/Student/Challenge-02.md index fd310f3a52..52cd464ccd 100644 --- a/xxx-AgenticAIApps/Student/Challenge-02.md +++ b/xxx-AgenticAIApps/Student/Challenge-02.md @@ -1,7 +1,6 @@ -````markdown # Challenge 02 - Build the Anomaly Detector Agent (Real Azure Metrics) -**[Home](../README.md)** - [Next Challenge >](./Challenge-03.md) +**[Home](./README.md)** - [Next Challenge >](./Challenge-03.md) --- @@ -179,4 +178,4 @@ Proceed to **[Challenge 03 – Build the Resource Optimizer Agent](./Challenge-0 * Enable multi-agent communication (Agent-to-Agent protocol) * Begin orchestrating self-healing AI systems in Azure -``` \ No newline at end of file +``` From 8ea69de78e3aaa767fb6156d88d442e3bfcaf66a Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:18:20 -0500 Subject: [PATCH 28/34] Update Challenge-03.md --- xxx-AgenticAIApps/Student/Challenge-03.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/xxx-AgenticAIApps/Student/Challenge-03.md b/xxx-AgenticAIApps/Student/Challenge-03.md index cba2e52d96..5e951c241e 100644 --- a/xxx-AgenticAIApps/Student/Challenge-03.md +++ b/xxx-AgenticAIApps/Student/Challenge-03.md @@ -1,7 +1,6 @@ -````markdown # Challenge 03 - Build the Resource Optimizer Agent (Real Azure Integration) -[< Previous Challenge](./Challenge-02.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-04.md) +[< Previous Challenge](./Challenge-02.md) - **[Home](./README.md)** - [Next Challenge >](./Challenge-04.md) --- @@ -168,7 +167,7 @@ To successfully complete Challenge 03, you should be able to: Once your **Resource Optimizer Agent** is working, move to **Challenge 04**, where you’ll build an **Alert Manager Agent** that coordinates notifications and alert responses across your system. -[< Previous Challenge](./Challenge-02.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-04.md) +[< Previous Challenge](./Challenge-02.md) - **[Home](./README.md)** - [Next Challenge >](./Challenge-04.md) ``` From bd860c9b39ee708e17d64fa204e1a77c01d621f0 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:20:50 -0500 Subject: [PATCH 29/34] Update Challenge-04.md --- xxx-AgenticAIApps/Student/Challenge-04.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xxx-AgenticAIApps/Student/Challenge-04.md b/xxx-AgenticAIApps/Student/Challenge-04.md index bf1fded423..dbb8515d0b 100644 --- a/xxx-AgenticAIApps/Student/Challenge-04.md +++ b/xxx-AgenticAIApps/Student/Challenge-04.md @@ -1,17 +1,17 @@ -````markdown # Challenge 04 - Build the Alert Manager Agent (Live Azure Integration) -[< Previous Challenge](./Challenge-03.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-05.md) +[< Previous Challenge](./Challenge-03.md) - **[Home](./README.md)** - [Next Challenge >](./Challenge-05.md) ## Pre-requisites - Completion of Challenge 03 – Resource Optimizer Agent - Active Azure subscription with Monitor and Action Groups access - `.env` file updated with your Azure subscription, resource group, and action group name -- Installed dependencies: +- Installed dependencies: + ```bash pip install azure-monitor-query azure-identity azure-mgmt-monitor python-dotenv -```` + ``` --- From dc79b34d53c56b562282881a0316e6487e0bda03 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:29:45 -0500 Subject: [PATCH 30/34] Update Challenge-05.md --- xxx-AgenticAIApps/Student/Challenge-05.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xxx-AgenticAIApps/Student/Challenge-05.md b/xxx-AgenticAIApps/Student/Challenge-05.md index f8046e6ec9..d0ad83ef2a 100644 --- a/xxx-AgenticAIApps/Student/Challenge-05.md +++ b/xxx-AgenticAIApps/Student/Challenge-05.md @@ -1,7 +1,6 @@ -````markdown # Challenge 05 - Orchestrate Agent-to-Agent Communicatio -[< Previous Challenge](./Challenge-04.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-06.md) +[< Previous Challenge](./Challenge-04.md) - **[Home](./README.md)** - [Next Challenge >](./Challenge-06.md) ## Introduction From 3b44d54ae6e1bb81d3c597631b3327149342bdf6 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:30:50 -0500 Subject: [PATCH 31/34] Update Challenge-06.md --- xxx-AgenticAIApps/Student/Challenge-06.md | 1 - 1 file changed, 1 deletion(-) diff --git a/xxx-AgenticAIApps/Student/Challenge-06.md b/xxx-AgenticAIApps/Student/Challenge-06.md index 75a04c4bfe..0b1b2d1266 100644 --- a/xxx-AgenticAIApps/Student/Challenge-06.md +++ b/xxx-AgenticAIApps/Student/Challenge-06.md @@ -1,4 +1,3 @@ -````markdown # Challenge 06 - Enable Agent-to-Agent Communication (A2A) [< Previous Challenge](./Challenge-05.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-07.md) From 42d09bd824bcc142fcd6d40221147d74289e842b Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:31:43 -0500 Subject: [PATCH 32/34] Update Challenge-07.md --- xxx-AgenticAIApps/Student/Challenge-07.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xxx-AgenticAIApps/Student/Challenge-07.md b/xxx-AgenticAIApps/Student/Challenge-07.md index a70447fd2b..fe9efb0c6f 100644 --- a/xxx-AgenticAIApps/Student/Challenge-07.md +++ b/xxx-AgenticAIApps/Student/Challenge-07.md @@ -1,7 +1,6 @@ -````markdown # Challenge 07 - Build the Anomaly & Resolution Tracker -[< Previous Challenge](./Challenge-06.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-08.md) +[< Previous Challenge](./Challenge-06.md) - **[Home](./README.md)** - [Next Challenge >](./Challenge-08.md) ## Introduction From e4a6c7e5ecc0351eead6de8c24f3d61bdb034cc9 Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:34:50 -0500 Subject: [PATCH 33/34] Update Challenge-08.md --- xxx-AgenticAIApps/Student/Challenge-08.md | 1 - 1 file changed, 1 deletion(-) diff --git a/xxx-AgenticAIApps/Student/Challenge-08.md b/xxx-AgenticAIApps/Student/Challenge-08.md index 327910dcd9..216d5bf97c 100644 --- a/xxx-AgenticAIApps/Student/Challenge-08.md +++ b/xxx-AgenticAIApps/Student/Challenge-08.md @@ -1,4 +1,3 @@ -````markdown # Challenge 08 - Spike VM Resources & Test Agent Detection [< Previous Challenge](./Challenge-07.md) - **[Home](../README.md)** From 9885ccce57fc4168a01b6a732fa8672aee1d2e3e Mon Sep 17 00:00:00 2001 From: Esvin Ruiz <69549001+esvin2661@users.noreply.github.com> Date: Wed, 3 Dec 2025 03:41:53 -0500 Subject: [PATCH 34/34] Update Challenge-08.md --- xxx-AgenticAIApps/Student/Challenge-08.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xxx-AgenticAIApps/Student/Challenge-08.md b/xxx-AgenticAIApps/Student/Challenge-08.md index 216d5bf97c..7604922ad2 100644 --- a/xxx-AgenticAIApps/Student/Challenge-08.md +++ b/xxx-AgenticAIApps/Student/Challenge-08.md @@ -1,6 +1,6 @@ # Challenge 08 - Spike VM Resources & Test Agent Detection -[< Previous Challenge](./Challenge-07.md) - **[Home](../README.md)** +[< Previous Challenge](./Challenge-07.md) - **[Home](./README.md)** ## Introduction