You cloned the starter repository during course setup. It is a Python project that uses uv.
Review the project before you change code. Find the files, tests, and incomplete exercises.
Project status
The starter kit contains working support code and incomplete exercise code.
uv run pytesttests the support code. This command must pass before you start.uv run behaveruns the acceptance tests. Some tests fail until you complete the exercises.- Each incomplete store method has a docstring. The docstring defines the required behavior and edge cases.
- The
features/directory contains the acceptance tests in Gherkin format. - Each acceptance test has a stable ID. Include the relevant IDs in each pull request.
Your .env file contains the model endpoint, model names, and OPENAI_KEY. Do not commit this file.
Work by lesson
| Lesson | Work | Test IDs |
|---|---|---|
| Stores | Implement the report and incident store methods. | STORE-R*, STORE-I* |
| Agentic loop | Implement the inner tool loop in agent.py. |
LOOP-* |
| Stage 1: dispatcher | Build the state message and dispatch prompt. Implement the minimum intake gate. Connect structured reports to incidents in the runner. | DISP-*, INT-* |
| Stage 2: intake | Complete the intake gate and the intake prompt. | INT-* |
| Stage 3: reconciliation | Integrate the supplied deterministic matching implementation and inspect its rules. | REC-* |
| Stage 4: replanning | Update the dispatch prompt and state message for new evidence. | Team scenarios |
Files you will use
Most course code is in src/hadr_agent/.
| File | Role |
|---|---|
runner.py |
Owns the MCP session and processes each tick. It calls next_tick() once per tick. Its intake and reconciliation steps are incomplete. |
agent.py |
Contains the task-neutral tool loop. The dispatcher uses this loop. |
intake.py |
Converts one human contact into one valid report. It makes one model call and does not use the tool loop. |
reconcile.py |
Matches reports and truck observations to incidents. This code does not use an LLM. |
dispatch.py |
Configures the tool loop for dispatch. It supplies the state message, typed tools, and incident check. |
stores/reports.py |
Stores extracted evidence. Reports are append-only, with one report for each contact. |
stores/incidents.py |
Stores the agent’s current beliefs about suspected fires. Incidents can change. |
prompts/intake_system.md |
The intake system prompt. |
prompts/dispatch_system.md |
The dispatch system prompt. |
Do not change these support files:
engine_client.pyconnects the agent to the game MCP.util.pyprovides token counting, the API client, prompt loading, and tool schemas.
Parts of the dispatch agent
The dispatch agent runs continuously during an episode. It does not wait for a user prompt.
This course calls this type of agent a claw, after OpenClaw. A claw is a small agent with six parts:
| Part | Purpose | Main file |
|---|---|---|
| Prompt | Gives the dispatch rules to the model. | prompts/dispatch_system.md |
| Loop | Sends context to the model and runs its tool calls. | agent.py |
| Tools | Let the model read data and dispatch trucks. | dispatch.py |
| Memory | Keeps reports and incidents between ticks. | stores/ |
| Heartbeat | Starts the agent for each tick. | runner.py |
| Channel | Exchanges data and commands with the simulator. | engine_client.py |
The starter kit supplies the heartbeat and channel. You build or configure the other parts during the course.
Control flow
For each tick, the system does these steps:
- The runner gets new data through the channel.
- Intake and reconciliation update the memory.
- The loop reads the current state and applies the dispatch prompt.
- The model uses tools to dispatch trucks or get more data.
- The runner calls
next_tick()once.
You will build the agentic loop after the store and evaluation activities. You will then configure it as a dispatcher.