Welcome — start here. Step 0 has no agent code. It introduces the workshop, walks you through creating your own copy of the repository, and gets your local toolchain ready so Step 1 can jump straight into building the first agent.
You will build a travel assistant that grows one capability at a time. Starting from a single hosted Foundry agent, by step 9 it will be a multi-agent travel planner with function tools, MCP integration, retrieval-augmented generation, durable workflows, and persistent memory.
The workshop is built on top of the upstream foundry-samples and is delivered as a GitHub template repository: you don't edit this repo directly — you create your own copy, then advance one step at a time. Each advance rewrites the README.md to show the next step in place.
This is a GitHub template repository. You must create your own copy before doing anything else.
- Click the green "Use this template" button at the top of this page → Create a new repository.
- Pick a name and owner, choose visibility (Public or Private), and click Create repository.
- The included Initialize workshop Action runs automatically on the first push to your new repo. It lays down the step 0 starter files into
travel_assistant/and substitutes your owner/repo into the README's Action URLs. Wait for it to finish in the Actions tab of your new repo (~30 seconds). If you don't see a run, your org may have Actions disabled by default — enable them under Settings → Actions → General → Allow all actions, then click Actions → Initialize workshop → Run workflow to run it manually. See the "▶ Start the workshop returns 404" entry under Troubleshooting below for the full recovery procedure. - Repo settings: Settings → Actions → General → Workflow permissions → Read and write permissions. Most repos inherit this, but org-owned repos may need it set explicitly so the workshop Actions can push.
💡 Already in your own copy? If the green button at the top reads "Open" rather than "Use this template", you're already in a workshop instance. Continue below.
Pick one of the two paths — the rest of the workshop works the same either way.
In your new repo, click Code → Codespaces → Create codespace on main. The first build takes ~2 minutes; after that the included devcontainer has everything pre-installed:
- Python 3.12,
azCLI (with Bicep),azdCLI,uv,git,gh, Node.js, GitHub Copilot CLI (copilot) - VS Code extensions: Python, Pylance, Python Debugger, Foundry Toolkit, Bicep, Azure MCP Server (Azure Skills), YAML, GitHub Pull Requests
- The Azure Skills plugin for the GitHub Copilot CLI is installed (its Azure MCP + Foundry MCP tools require
az loginat use time) - The post-create step has already created
.venv/and installed workshop dependencies fromtravel_assistant/requirements.txt(or.workshop/step_files/00/requirements.txt) plus.workshop/scripts/requirements.txt
⚠️ Wait for "Initialize workshop" to finish first. If you create the Codespace before that Action has applied step 0, the container falls back to.workshop/step_files/00/requirements.txtfor workshop deps. After the Action turns green, rebuild the Codespace (Command Palette → Codespaces: Rebuild Container) so it picks uptravel_assistant/requirements.txt.
If you go this route, skip the "Install the tools you'll need" section below and jump straight to "Set up your local environment (one-time)". 👉 Direct link: Set up your local environment (one-time)
git clone https://github.com/<your-owner>/<your-repo>.git
cd <your-repo>Then continue with "Install the tools you'll need" below to install Python, az, azd, and (optionally) uv on your machine.
💡 In a Codespace? Skip this section — the devcontainer already installed all of these. Jump to "Set up your local environment (one-time)".
Prerequisites at a glance:
- Azure subscription with access to a Foundry project and a deployed model such as
gpt-4o-miniorgpt-4.1-mini. See Create a Foundry project. - A role that lets you use the project —
Foundry User(formerly Azure AI User) on the Foundry project. This is the least-privilege role for using a project — prefer it over broader roles like Owner or Contributor. If you created the project you already have at least this. Some steps assign extra roles as needed (Step 5 adds Azure AI Search roles; Step 6 reusesFoundry Userfor the Skills API and grants it to the deployed agent's identity). - Python 3.10 or newer (the devcontainer ships 3.12).
- Azure CLI (
az) — used byDefaultAzureCredentialfor local auth. - Azure Developer CLI (
azd) with themicrosoft.foundryextension — used to scaffold, provision, run, and deploy hosted agents. - VS Code + Foundry Toolkit (optional, recommended) — UI alternative to
azdfor running, debugging, and deploying hosted agents. - GitHub Copilot CLI (
copilot) (optional, recommended) — AI-powered CLI assistant. Install withnpm install -g @github/copilot(the devcontainer installs it automatically via thecopilot-clifeature). - Bicep (optional, recommended) — infrastructure-as-code language for the
azd-generatedinfra/. Install the CLI withaz bicep installand the Bicep VS Code extension for language support. - Azure Skills (optional, recommended) — Azure skills and MCP server configurations for AI coding assistants. In VS Code install the Azure MCP extension; for the GitHub Copilot CLI run
/plugin marketplace add microsoft/azure-skillsthen/plugin install azure@azure-skills. Requires Node.js 18+ (the MCP servers run vianpx) and an authenticatedaz loginfor the Azure tools. uv(optional) — a faster drop-in forpip/venv. Anywhere this workshop sayspiporpython -m venvyou can useuv piporuv venvinstead.
- Windows:
winget install --id Python.Python.3.12 -e
- macOS: install from python.org or
brew install python@3.12. - Linux (Ubuntu/Debian):
sudo apt update && sudo apt install -y python3 python3-venv python3-pip
Verify:
python --version # or `python3 --version`Full instructions: Install the Azure CLI.
- Windows:
winget install --id Microsoft.AzureCLI -e
- macOS:
brew update && brew install azure-cli - Linux (Ubuntu/Debian):
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
Verify:
az --versionFull instructions: Install the Azure Developer CLI.
- Windows:
winget install --id Microsoft.Azd -e
- macOS:
brew tap azure/azd && brew install azd - Linux:
curl -fsSL https://aka.ms/install-azd.sh | bash
Verify:
azd versionFull instructions: Install uv.
- Windows:
winget install --id=astral-sh.uv -e
- macOS / Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh
💡 In a Codespace? The devcontainer already handled the venv and the
pip install(substeps 3 and 5 below) — but you still need to do substeps 1, 2, 4, and 6 (az login,azd auth login+ ext install, copy.env, run preflight). Authentication and your.envcan't be baked into the container.
-
Sign in to Azure:
az login
If needed, select a subscription:
az account set -s <subscription>
-
Sign in to azd and install the Foundry extension (one-time):
azd auth login azd ext install microsoft.foundry
This adds the
azd ai agent ...subcommands used from Step 1 onward to scaffoldazure.yaml/infra/, provision Foundry resources, run the agent locally, deploy, and invoke.microsoft.foundryis a meta-package that installs all the Foundryazd aiextensions — see Install the Azure Developer CLI Foundry extensions for details. If you'd rather drive everything from VS Code, the Foundry Toolkit extension exposes the same operations as palette commands and a sidebar. If you have a Python virtual environment active (next substep), the Foundry Toolkit picks it up automatically when you press F5 to debug. -
Create and activate a Python virtual environment.
Pick one of the two options below. Option A uses the Python stdlib
venvmodule and matches the rest of the workshop; Option B usesuv, which is significantly faster but requires installinguvfirst (see above). Both options create the environment at.venv/, so the activation commands are the same.Option A —
python -m venv(default)python -m venv .venv
Option B —
uv venvuv venv .venv
Then activate it:
- macOS / Linux:
source .venv/bin/activate - Windows (PowerShell):
.\.venv\Scripts\Activate.ps1
💡
uvusers: activation is optional.uv pip install,uv run, anduvitself auto-discover.venv/in the current directory. If you skip activation, prefix later Python commands withuv run(e.g.uv run python .workshop/scripts/preflight.py) so they use the venv's interpreter. - macOS / Linux:
-
Configure environment: setup and every later step read their configuration from a repo-root
.envfile, so create it before running preflight — copy the template, then fill it in:# bash / zsh cp .env.example .env# PowerShell Copy-Item .env.example .env
Then edit
.env:AZURE_AI_PROJECT_ENDPOINT— from your Foundry project's overview page.AZURE_AI_MODEL_DEPLOYMENT_NAME— your deployment name, for examplegpt-4o-mini.WORKSHOP_RESOURCE_PREFIX— this prefixes every Azure/Foundry resource the workshop creates (and is how.workshop/scripts/cleanup.pyfinds them later). If you're working solo in your own subscription, leave the defaultfoundry-workshop. But if you share the Foundry project or subscription with other people running this workshop, change it to a value unique to you (for examplefoundry-workshop-<your-alias>) so your resource names don't collide with a teammate's — otherwise provisioning can fail on name conflicts, and cleanup could delete each other's resources.- Leave step-specific variables empty for now; the README will tell you when to fill them.
-
Install dependencies (use the option that matches your venv choice above):
Option A —
pippip install -r travel_assistant/requirements.txt pip install -r .workshop/scripts/requirements.txt
Option B —
uv pipuv pip install -r travel_assistant/requirements.txt uv pip install -r .workshop/scripts/requirements.txt
-
Run preflight:
# If you activated .venv python .workshop/scripts/preflight.py # If you're using uv without activation uv run python .workshop/scripts/preflight.py
Fix any ❌.
⚠️ items are usually safe to ignore until later steps.
This workshop has one important contract: README.md is the current step. Each time you advance, the repository rewrites README.md so the next set of instructions appears in place.
- Leaving Setup (this step): click the ▶ Start the workshop button at the bottom. It opens the workshop's GitHub Action — click Run workflow, and it moves you from Setup to Step 1.
- Every step after that: there is no button. When you finish a step, commit the files you created and push them to
main. The push triggers the Advance workshop on push to main Action, which loads the next step. Each landed push advances by exactly one step, so push once — when the step is done. - After the Action finishes, run
git pulllocally. If you are reading in the GitHub UI, refresh the page to see the newREADME.md. - Advancing lays the next step's canonical files on top of your
travel_assistant/directory. Files from earlier steps that the next step doesn't touch are kept as-is — nothing is deleted. Files the next step ships are refreshed to that step's version, and your current edits are first saved to.workshop_instance/workshop_backups/step-<N>/in the same commit so you can recover your own wording.
- Step 1: Chat with a basic hosted
TravelBuddyagent. - Step 2: Add function tools for weather, local time, and currency conversion.
- Step 3: Connect an MCP server for external travel documentation.
- Step 4: Use Foundry tools such as Code Interpreter and web search for itinerary analysis.
- Step 5: Ground recommendations with a destinations knowledge base through RAG.
- Step 6: Package reusable itinerary behavior as a skill.
- Step 7: Coordinate flight, hotel, and activities specialists with native multi-agent patterns.
- Step 8 (🧪 experimental): Re-express the same planning flow as a durable workflow with checkpoints.
- Step 9 (🧪 experimental): Remember user preferences across sessions with Foundry Memory.
Make sure python .workshop/scripts/preflight.py is green (or uv run python .workshop/scripts/preflight.py if you're using uv without activation), then click the button below to open the workflow — and click Run workflow in the dialog that appears:
Click Run workflow to move from Setup to Step 1. Pull after the action completes. From Step 1 onward you advance by committing your work and pushing to main — there is no button. With setup already done, Step 1 jumps straight into authoring agent.yaml, agent.manifest.yaml, and main.py for your first hosted TravelBuddy agent.
You can run the entire workshop loop from your terminal — no browser, no Actions, no git push required. Pick whichever flow you prefer; both keep the repository in the same state.
The button in each step's README is just a thin wrapper around .workshop/scripts/advance_step.py. Running the script locally does exactly the same file rewrites.
Advance one step:
python .workshop/scripts/advance_step.py --expected-current-step <N> --auto-commitWhere <N> is the step number you're currently on (the value the button asks for). You can omit --expected-current-step locally if you trust the state — the script will print the detected step and advance anyway. The --auto-commit flag stages only the workshop-owned paths (README.md, .workshop_instance/.workshop-state.json, travel_assistant/, .workshop_instance/workshop_backups/) and creates a commit with the same message the Action uses, so unrelated local edits or untracked files are never swept in.
Reset the workshop:
python .workshop/scripts/advance_step.py --reset --auto-commitYour previous travel_assistant/ is preserved under .workshop_instance/workshop_backups/reset-<timestamp>/.
Re-run preflight:
# If you activated .venv
python .workshop/scripts/preflight.py
# If you're using uv without activation
uv run python .workshop/scripts/preflight.pyShortcuts (optional): the repo ships a Makefile with three aliases:
make advance # advance to the next step (auto-commits workshop paths)
make reset # reset to step 0 (auto-commits workshop paths)
make preflight # run environment checksWhen make is not available (e.g. on a clean Windows install), just run the equivalent python .workshop/scripts/... commands above.
When the button and the local flow are interchangeable. Both write the same files. You can switch back and forth between clicking the button and running the script across steps without breaking anything — the script's state-sync check will catch any genuine drift before it advances.
A branch protection rule is blocking GITHUB_TOKEN from pushing the README update. Fix the rule in Settings → Branches, or allow the workflow/bot account to bypass the rule for this workshop repository.
This means the Initialize workshop Action hasn't run yet in your repo, so the button's URL still contains URL-encoded handlebars (%7B%7B...%7D%7D) where your repo owner and name should appear. To recover:
- Confirm Actions are enabled: Settings → Actions → General → Allow all actions.
- Confirm workflows can write: Settings → Actions → General → Workflow permissions → Read and write permissions.
- Open the Actions tab, choose Initialize workshop, click Run workflow on the default branch.
- Wait for the run to finish, then
git pulllocally (or refresh the GitHub UI). The button URL will now contain your real owner/repo and work on the first click.
If you advanced past step 0 already and only just hit this, the Start the workshop Action also self-heals — running it from the Actions tab will perform the missed initialization in the same commit.
Enable Actions in Settings → Actions → General → Allow all actions.
This workshop does not use marketplace actions for advancing steps; it uses the repo's workflow plus plain git push. If your organization shows this warning, no third-party action exception is needed for the workshop advance flow.
Auto-advance only runs for pushes to main in your own (non-template) repo, and it skips pushes that only changed workshop bookkeeping such as .workshop_instance/.workshop-state.json. Check the Actions tab for the Advance workshop on push to main run. If it was skipped, make sure you pushed a real change to main and that the previous advance already finished. If several quick pushes collapsed into a single advance, that's expected — each landed push advances one step.
DefaultAzureCredential may pick up the Codespace's GitHub token before your Azure CLI identity. Add AZURE_TENANT_ID to your environment, or run this in the Codespace terminal:
az login --use-device-codeThey were backed up to .workshop_instance/workshop_backups/step-<previous>/ in the same commit that advanced the workshop. Cherry-pick or copy back anything you want to keep.
When you finish, or if you want to abandon the workshop, step 99 runs python .workshop/scripts/cleanup.py --apply to delete all workshop-created Azure resources. The script only touches resources whose names start with WORKSHOP_RESOURCE_PREFIX. If you used azd to provision hosted-agent resources, you can alternatively run azd down to tear down the resources azd created.
This step has no code to write — it's intro and setup of your repo from the template.