Lab 0 — Setup, dual API, and the scorecard
Lab 0 establishes the reusable boundary between Foundry-hosted Claude Messages
and GPT Responses models. It also supplies an offline ScriptedModel, a
provider usage ledger, and the deterministic local store simulator used by
Labs 0–8.
Concept
Every later lab measures a harness capability against a fixed, known target — so before any agent behavior can be built, the substrate has to be stable: one Entra-only identity path (no API keys, ever), one interface over two different provider APIs, and one deterministic “world” (the store simulator) to run tasks against and grade honestly. Lab 0 has no agent behavior yet; it is the plumbing everything else stands on.
Key ideas
- Two providers, one seam. Claude’s Messages API and GPT’s Responses API
shape tool calls differently (message-grouped vs.
call_id-addressed).ModelClient’s two adapters normalize both into the sameTurn/ToolCallshape so later labs never special-case the provider. - Entra-only, no secrets.
.envholds only endpoint/deployment/provider; every credential is acquired at runtime viaDefaultAzureCredential. - A ledger, not a guess. Usage/cost is recorded exactly as each provider reports it — this is what later labs’ scorecards and cost comparisons rely on.
- A deterministic world to test against. The local store simulator gives every later lab a stable, offline-checkable environment instead of a live, flaky dependency.
Added in this lab
harness/models/adapters.pydefinesModelClientandTurn, withMessagesAdapter,ResponsesAdapter, and the offlineScriptedModel.harness/config.pyprovidesHarnessConfigandfoundry_token_provider()for non-secret configuration and Entra identity.harness/ledger.pyrecords provider-reported usage withLedger;common/store_sim/app.pysupplies the seeded local store and read endpoints.harness/cli/app.pyintroduceswhoami(),ping(), and simulator commands;lab.jsondeclares snapshot capabilities.
Learner steps
- Create and activate a virtual environment, install the lab, configure a
Foundry deployment in
.env, and sign in with Azure CLI:
python -m venv .venv
. .venv/bin/activate
pip install -e '.[dev]'
cp .env.example .env
az login
pytest checks/
Set only non-secret values in .env. Authentication is acquired at runtime
through DefaultAzureCredential; do not add API keys.
-
Open the interactive prompt, ask multiple questions, and leave the prompt:
harness askEnter a question at
You>; eachAssistant>response and its token counts remain visible above the next prompt. Enter/exitto return to your shell. You can also pass one question directly, such asharness ask "What is 17 multiplied by 23?". Each turn is a fresh model call without tools or conversation history.pytest checks/remains the offline regression check; it does not replace this learner-facing Foundry call. -
Create the practice app, once for the whole course. Later labs use their harness on this app. It is its own git repository and is gitignored by the course repo (see the track guide):
mkdir ../app && cd ../app git init -b main printf '# Pet store practice app\n\nSynthetic data only. Built with my own harness during the labs.\n' > README.md printf '.env\n.env.*\n__pycache__/\n.pytest_cache/\n*.log\n' > .gitignore git add . && git commit -m "chore: start practice app" git tag lab00-doneOn Windows PowerShell:
New-Item -ItemType Directory ..\app | Out-Null; cd ..\app git init -b main "# Pet store practice app`n`nSynthetic data only. Built with my own harness during the labs." | Set-Content README.md ".env`n.env.*`n__pycache__/`n.pytest_cache/`n*.log" | Set-Content .gitignore git add . ; git commit -m "chore: start practice app" git tag lab00-doneWith the Lab 0 virtual environment still active, run
harness ask "Reply with OK if you can read this."fromapp/. Theharnesscommand reads the.envfile from the lab folder, so a reply confirms that Foundry works from the app. Lab 0 has no tools, so it cannot read the app’s files yet. Lab 2A adds that.
Start the simulator in a separate terminal before inspecting or resetting it:
harness sim start
harness sim status
Commands
harness askopens a persistent question prompt;harness ask "<question>"sends one stateless question to the configured Foundry model.harness whoamiverifies that an Entra token can be acquired.harness ping --provider claude|gpt [--probe]validates a configured deployment and writes the capability record when probed.harness sim start,harness sim status, andharness sim resetmanage the local simulator.
Done when: git tag in app/ lists lab00-done and a question was
answered through Foundry. The next snapshot adds the first bare model call.