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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Keep the post-create hook LF so bash inside the dev container doesn't choke on
# CRLF when the repo is checked out on Windows.
*.sh text eol=lf
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"postCreateCommand": "pip install --upgrade pip && pip install -r requirements.txt",
"postCreateCommand": "bash .devcontainer/post-create.sh",
"customizations": {
"vscode": {
"extensions": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# =============================================================================
# Dev container post-create hook (runs once after the container is built).
#
# 1. Install the Python dependencies (src/requirements.txt) — ESSENTIAL:
# every challenge needs these.
# 2. Best-effort install of the Microsoft ODBC Driver 18 for SQL Server so the
# OPTIONAL Azure SQL contract-status / renewal tool works out of the box.
# That tool's connection string uses "Driver={ODBC Driver 18 for SQL
# Server}" (see labautomation/infra/resources.bicep), so unixODBC alone is
# not enough. If this step fails (e.g. no network to packages.microsoft.com)
# the tool simply falls back to the bundled JSON corpus, so we NEVER fail
# the whole container build over an optional driver.
# =============================================================================
set -euo pipefail

echo "==> [1/2] Installing Python dependencies (src/requirements.txt)"
pip install --upgrade pip
pip install -r src/requirements.txt

echo "==> [2/2] Installing Microsoft ODBC Driver 18 for SQL Server (optional Azure SQL tool)"
if command -v odbcinst >/dev/null 2>&1 && odbcinst -q -d 2>/dev/null | grep -q "ODBC Driver 18 for SQL Server"; then
echo " Driver already present — skipping."
else
# Debian 12 (bookworm) — matches the python:3.11-bookworm base image.
if (
set -e
curl -sSL -O https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm -f packages-microsoft-prod.deb
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18
); then
echo " ODBC Driver 18 installed."
else
echo " WARN: msodbcsql18 install failed — the Azure SQL tool will use the JSON fallback."
fi
fi

echo "==> post-create complete."

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:

- name: Install dependencies
if: steps.guard.outputs.configured == 'true'
run: pip install -r requirements.txt "azure-ai-evaluation[redteam]"
run: pip install -r src/requirements.txt "azure-ai-evaluation[redteam]"

- name: Azure login (OIDC)
if: steps.guard.outputs.configured == 'true'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Secrets / local config
# The repo-root .env is written by src/scripts/write_env.py and holds live
# secrets (SharePoint app secret, connection strings). Never commit it.
.env
.env.*
!.env.example

# Python
# Python (local runs at the repo root)
__pycache__/
*.py[cod]
.venv/
Expand All @@ -13,17 +15,6 @@ venv/
.ruff_cache/
.python-version

# Node / MCP tooling
node_modules/

# Build / conversion artifacts
*.log
*.pdf
# ...but the Challenge 1 CLM corpus PDFs ARE seed data and must be tracked.
!src/data/**/*.pdf
dist/
build/

# OS
.DS_Store
Thumbs.db
Expand Down

This file was deleted.

21 changes: 0 additions & 21 deletions 03-Azure/01-04-AI/04_Agentic_Contract_Lifecycle_Management/LICENSE

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -300,10 +300,10 @@ challenges are a single story:
## Getting started

1. **Open this repo in Codespaces** (no fork needed — the optional Challenge 6 CI bonus is the only part that needs a fork) — **Code → Codespaces → Create codespace**. The devcontainer installs
Python 3.11, Azure CLI, `azd`, Node, and `requirements.txt` automatically.
Python 3.11, Azure CLI, `azd`, Node, and `src/requirements.txt` automatically.
2. `az login` (and `azd auth login` if you use the `azd up` path)
3. Do **[Challenge 1](challenges/challenge-01.md)** to deploy resources and seed the corpus — provision with
**`azd up`** (Bicep in `labautomation/infra/`), the **`labautomation/deploy`** script, or the one-click
**`azd up`** (run from `src/`; Bicep in `labautomation/infra/`), the **`labautomation/deploy`** script, or the one-click
**Deploy to Azure** button (`infra/azuredeploy.json`). The first two autofill your `.env`.
- **Seeding the corpus — default is Path B** (Challenge 1 · Task 6): **Path B (local-PDF)** needs
no SharePoint and no admin consent, works in every tenant, and builds the `clm-corpus` index —
Expand All @@ -317,12 +317,14 @@ challenges are a single story:

```
.
├── .devcontainer/ # Codespaces definition
├── azure.yaml # azd config (points at labautomation/infra, write-.env hook)
├── .devcontainer/ # Codespaces / Dev Containers definition
├── README.md # this file
├── challenges/ # challenge-01 … challenge-06 (one markdown brief per challenge)
├── walkthrough/ # challenge-0N/solution-0N.md — reference solution per challenge
├── src/ # all source code: agents/, clm_common/, mcp_server/, data/, scripts/ …
├── src/ # all source code + build/config: agents/, clm_common/, mcp_server/, data/, scripts/ …
│ ├── azure.yaml # azd config (points at ../labautomation/infra, write-.env hook) — run `cd src && azd up`
│ ├── Dockerfile # Challenge 4 MCP server image (.dockerignore alongside; build context = src/)
│ ├── requirements.txt # Python dependencies
│ └── data/ # CLM corpus (PDF contracts/templates/clauses/policies) + eval datasets
├── labautomation/ # infra (Bicep) + deploy, seed corpus/SQL, write .env, smoke test
├── images/ # rendered images + per-challenge screenshots + diagrams
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
Welcome to your very first challenge! Here you lay the foundation for the whole microhack: you'll
deploy the Azure resources, wire up your development environment, and seed the contract corpus the
later challenges build on. By the end you'll have the full **Microsoft Foundry** environment
running — with **zero local install** — so the rest of the hack is pure agent-building.
running in a **prebuilt dev container** — so the rest of the hack is pure agent-building.

If something isn't working as expected, please let your coach know.

> **⏱️ Duration:** ~30 min

> **📋 Prerequisites:**
> - An **Azure subscription** your lab was provisioned in *(or, if self-hosting, one with rights to create a Foundry project and deploy GPT models)*.
> - A **GitHub account** (to open the repo in Codespaces).
> - **GitHub Codespaces** access — everything runs in the browser; no local tooling required.
> - A **GitHub account** (to clone the repo).
> - **VS Code** with the **Dev Containers** extension and **Docker Desktop** — the repo's dev container has everything preinstalled *(or **GitHub Codespaces**, if you'd rather run in the browser)*.

> 🧩 **How to use this challenge:** for a MicroHack event your Azure resources are **provisioned for
> you** — you just point your `.env` at them (Task 3) and **confirm you understand what got created**:
Expand All @@ -30,8 +30,8 @@ If something isn't working as expected, please let your coach know.

## 🧭 Context

Everything runs from **GitHub Codespaces** using the devcontainer in this repo (Python 3.11, Azure
CLI, `azd`, Node). For a MicroHack event the resources below are **already provisioned** into **one
Everything runs inside the **dev container** in this repo (Python 3.11, Azure
CLI, `azd`, Node) — open it locally in **VS Code** (Dev Containers) or in **GitHub Codespaces**. For a MicroHack event the resources below are **already provisioned** into **one
resource group** and their endpoints appear on your **lab dashboard**; you copy them into `.env` in
Task 3. *(Self-hosting? One **`azd up`** — Bicep in [`infra/`](../labautomation/infra/) — provisions the
same resource group and autofills `.env`.)*
Expand Down Expand Up @@ -128,36 +128,35 @@ text at crawl time); regenerate the PDFs with `python src/scripts/make_corpus_pd

**Before you begin — tick these off:**

- [ ] You can sign in to [github.com](https://github.com).
- [ ] You can sign in to the [Azure Portal](https://portal.azure.com) with the account your lab was provisioned for (or, if self-hosting, one that can **create resources**).
- [ ] *(Self-hosting only)* Your Azure subscription can deploy **GPT** models (ask your coach if unsure).
- [ ] You have ~30 minutes and a stable connection (provisioning takes 5–10 min on its own).

### Task 1 · Open the Codespace (~7 min)
### Task 1 · Open the project in VS Code (~7 min)

**No fork needed for the main hack (Challenges 1–5)** — the code you run lives in this repo. Open it in **GitHub Codespaces** (a full VS
Code + terminal in your browser, zero local install); because you work off the source repo, `git pull`
**No fork needed for the main hack (Challenges 1–5)** — the code you run lives in this repo. Clone it and open it in **VS
Code** using the **Dev Containers** extension (a prebuilt container with Python, Azure CLI, `azd`, and Node — no manual installs); because you work off the source repo, `git pull`
always gets the latest fixes. *(The **one exception** is the optional **Challenge 6** CI bonus — it runs in **GitHub Actions**, so it needs **your own fork**; you'll create it there, not now.)*

1. On the repo's GitHub page, click **`< > Code` → Codespaces → Create codespace on `main`**.
*(Prefer local? `git clone` the repo and **Reopen in Container** with the VS Code Dev Containers
extension.)*
2. Wait for the container to build — it installs dependencies with `pip install -r requirements.txt`
1. Open the folder in **VS Code** (e.g. `code microhack-aiagents`). When VS
Code prompts **"Reopen in Container"**, click it — or run **Dev Containers: Reopen in Container** from
the Command Palette (**F1**). Requires the **Dev Containers** extension and **Docker Desktop**.
2. Wait for the container to build — it installs dependencies with `pip install -r src/requirements.txt`
automatically. When the terminal stops scrolling and shows a prompt, it's ready.

<img src="../images/challenge-01/steps/02-create-codespace.png" alt="GitHub · Code → Codespaces → Create codespace on main" width="80%">

✅ **You'll know it worked when:** a browser VS Code editor opens with a **Terminal** panel showing a
ready prompt (e.g. `@your-username ➜ /workspaces/microhack-aiagents (main) $`).
✅ **You'll know it worked when:** a **VS Code** window opens (locally or in the browser) with a **Terminal** panel showing a
ready prompt.

> [!NOTE]
> If Codespaces isn't enabled in your org, see [enabling Codespaces](https://docs.github.com/en/codespaces/managing-codespaces-for-your-organization/enabling-or-disabling-github-codespaces-for-your-organization) or use a [free personal account](https://github.com/signup) (120 core-hours/month free). While it builds, skim the [scenario & architecture](../README.md#the-scenario--contoso-global) so the pieces you deploy here make sense.
> **Prefer the browser? Use GitHub Codespaces instead.** On the repo's GitHub page, click **`< > Code` → Codespaces → Create codespace on `main`** — the same dev container builds in the cloud, so you need no local Docker.
>
> While it builds, skim the [scenario & architecture](../README.md#the-scenario--contoso-global) so the pieces you deploy here make sense.

---

### Task 2 · Log in to Azure (~3 min)

Now connect the terminal to your Azure account. In the Codespace **Terminal**, type this and press Enter:
Now connect the terminal to your Azure account. In the **VS Code Terminal**, type this and press Enter:

```bash
az login --use-device-code
Expand Down Expand Up @@ -198,13 +197,13 @@ For a **MicroHack event your Azure resources are already provisioned** — a res
Foundry project, the three-model GPT fleet, and Azure AI Search. You don't deploy anything; you just
point your `.env` at them using the values on your **lab dashboard**.

**Step 3a — create your `.env`** from the template (Codespace terminal, at the repo root):
**Step 3a — create your `.env`** from the template (VS Code terminal, at the repo root):

```bash
cp src/.env.example .env
```

**Step 3b — copy your dashboard values into `.env`.** Open `.env` in the Codespace editor and fill in
**Step 3b — copy your dashboard values into `.env`.** Open `.env` in the VS Code editor and fill in
the values shown on your lab dashboard:

| Lab dashboard credential | `.env` variable | Example value |
Expand Down Expand Up @@ -245,6 +244,7 @@ everything. First pick a region that offers **all three** models — this repo's
> old template is what triggers `DeploymentModelNotSupported` / `ServiceModelDeprecating`.

```bash
cd src # azure.yaml (the azd project) lives here
azd auth login # separate from az login above
azd up # answer: environment name (e.g. clm-microhack), your subscription, region = Sweden Central
```
Expand All @@ -257,7 +257,7 @@ It provisions for **5–10 minutes**, assigns the RBAC roles the later challenge
grounding with `azd env set DEPLOY_BING true` before `azd up`.

> **Prefer not to use `azd`?** `LOCATION=swedencentral ./labautomation/deploy.sh` (add `--with-sql` /
> `--with-bing`; on Windows outside Codespaces use `./labautomation/deploy.ps1`) provisions the same
> `--with-bing`; on native **Windows** use `./labautomation/deploy.ps1`) provisions the same
> resources and writes `.env` too. If it fails with `DeploymentModelNotSupported`, a model/version
> isn't offered in your region — see [🛠️ Troubleshooting](#️-troubleshooting).

Expand Down Expand Up @@ -286,7 +286,7 @@ your **`clm-project`** → **Models + endpoints**. Confirm the deployments show
>
> <img src="../images/challenge-01/steps/08-foundry-deployments-dark.png" alt="Screenshot slot: model deployments" width="80%">

**4c — Your `.env` file.** In the Codespace file explorer, open **`.env`** at the repo root. Confirm the
**4c — Your `.env` file.** In the VS Code file explorer, open **`.env`** at the repo root. Confirm the
values are filled in (every entry has a value **except** the `SHAREPOINT_*` corpus and the Challenge 5
`MICROSOFT_APP_*` / `TEAMS_*` variables, which you fill later).

Expand Down Expand Up @@ -604,7 +604,7 @@ Smoke test: ✅ PASS
| `Project can only be created under AIServices Kind account with allowProjectManagement set to true` | Fixed in the template (`account.properties.allowProjectManagement: true`). If you hit it, your checkout is behind — run `git pull` and redeploy. |
| SharePoint: *"Tenant does not have a SPO license"*, or you can't grant the app's Graph **admin consent** (only Global Reader / **"Grant admin consent" greyed out**) | Only happens if you're **not** an admin of the tenant — in your own sandbox tenant the Path A script self-grants consent. If you hit it, it's **not** a failure: use the **local-PDF fallback (Path B)** — leave the `SHAREPOINT_*` values blank in `.env` and run `python src/scripts/seed_corpus.py`. It extracts `src/data/**/*.pdf` and populates `clm-corpus` directly (needs the Search Index Data Contributor role, granted during provisioning) — the **same index** the SharePoint path builds, so Challenges 2–6 are unaffected. See [Task 5, Path B](#task-5--seed-the-corpus). |
| `account project create` unavailable | The CLI project command is preview. Create the project in the **Foundry portal**, then set `AZURE_AI_PROJECT_ENDPOINT` in `.env` manually (Overview → Endpoint). |
| `az login` in Codespaces | Use `az login --use-device-code`. |
| `az login` in a dev container / Codespaces | Use `az login --use-device-code`. |
| Search / quota errors | Ensure the subscription has quota for Basic Search + the model SKUs; request quota if needed. |
| `PermissionDenied` after deploy | RBAC can take 5–10 min to propagate. Wait, run `az login --use-device-code` again, and retry. |

Expand Down
Loading
Loading