Cyber Commons · Course guideThe model proposes, your code decides
Every control in the other five functions attaches to a mechanism. Hand somebody a control before they have built the mechanism and they apply it as a sentence in a document — which is the single most common reason agentic security guidance is read, agreed with, and not implemented. This function removes that excuse by making the reader the builder first.
Build CyberTravels end to end on your own machine: the reasoning loop with an independent verifier, two MCP resource servers behind a process boundary, a workload identity per agent, per-action delegation the resource server actually enforces, memory that records where its contents came from, signed agent-to-agent envelopes, a human gate and a budget. Then the harness around it — spans, an audit trail, an evaluation suite — and the blast radius of what you built.
The system runs, and four numbers say how well: scopes on a delegated token (one), memory entries carrying an origin (all of them), audit rows answering all four investigation questions (usually three, and the fourth is the finding), and the blast radius you carry into Function B. None of those is 'it worked once'.
Taught duration: about four hours (Function A's pace is 16 lessons in 4 hours)
Primary audience: Everyone, first · the system the other five tracks are about
Prerequisites: A computer and a Claude account. Reading Python helps from Module 1 on; writing it is not required.
Reading: 15,751 words of lesson prose, at 180 words a minute.
You leave with: A working lab, and a nine-word guess sheet.
You leave with: Trust map, verifier rejection, token refusal; Untrusted label, forged envelope, budget hit.
Everyone, whatever your job, because this is the system the other five tracks are about. Engineers building an agentic feature, and equally the AppSec engineers, red teamers, SOC analysts and GRC leads who will be handed one. It assumes you can read a Python function. It assumes no security background at all, and no prior agent work.
Use this on your own, or to run Function A for other people. Everything here serves both; the shaded blocks marked For a room are the only parts a solo reader can skip.
Every number on this page is generated from the lesson sources and the application, so an expected output here is what the command actually prints. If a run disagrees with this page, trust the run and correct scripts/exercises/guide_a.py.
| On your own | Work through it in order, one module per sitting if four hours in one go is too much. The module boundaries are the natural stopping points: each one ends with something printed that you can look at. |
|---|---|
| With a room | 1 trainer per ~15 learners, working in pairs — one driver prompts Claude, one checker compares the output against this page. |
| What you build | The CyberTravels agentic platform — 8 of the 9 agent components, 7 tools behind two MCP servers, and the controls between a model's suggestion and a real action |
| The one sentence to hold | The model proposes, your code decides |
| Time | Module | Lessons | You leave with |
|---|---|---|---|
| 0:00–0:15 | Framing | — | The "chatbot says, agent does" distinction |
| 0:15–0:45 | Setup and the nine words | A0.0 · A0.1 | A working lab, and a nine-word guess sheet |
| 0:45–1:50 | Build the agent core | A1.0 · A1.1 · A1.2 · A1.3 · A1.4 | Trust map, verifier rejection, token refusal |
| 1:50–2:00 | Break | — | — |
| 2:00–2:45 | Memory, peers, and stopping the loop | A1.5 · A1.6 · A1.7 | Untrusted label, forged envelope, budget hit |
| 2:45–3:40 | Harness engineering | A2.0 · A2.1 · A2.2 · A2.3 · A2.4 | Audit gaps, eval score with its caveats |
| 3:40–3:50 | Break | — | — |
| 3:50–4:20 | Capstone and handover | A2.5 | Blast radius, marked sheet, three answers |
Half the time? Keep Modules 0, 1 and 4 whole. A1.5–A1.7 can be read rather than run, and A2.0–A2.4 collapse into one pass at the question "what would an investigator ask?". Do not cut the capstone: it is the only part that shows whether anything stuck.
Run A1.5–A1.7 as a single 15-minute demo from your machine, and teach A2.0–A2.4 as one 20-minute discussion rather than five labs.
Every lesson can be done three ways. Way 1 is the default; the other two matter because a machine with no model configured can still do every lesson, and because "what actually changed?" is the question that comes up most.
| Way | What it does | Needs a model? | Use it for |
|---|---|---|---|
| 1 — in your AI agent | The agent reads the lesson, teaches it, runs the check | No — Claude is the agent | The default for every lab |
2 — scripts/lesson.py <id> | Runs the lesson, prints a five-heading readback | Yes, or it exits 2 saying "no model configured" | Worth doing once in A0.0, to meet that message on purpose |
3 — scripts/checkpoint.py --at <id> --diff | Shows the code this lesson added | No | Any "what actually changed?" question |
Whoever you are, this is the part that blocks everything else: a machine that cannot run a lesson is the one failure that stops a reader entirely.
python3 scripts/doctor.py, or python scripts\doctor.py on Windows. If the summary says ready, you are ready — -- lines are optional things that are absent, not faults.python3 -m pip install -r cybertravels/requirements.txt. This brings in PyJWT, which A1.3 and A1.4 need.scripts/exercises/guide_a.py../cybertravels/run.sh serves http://127.0.0.1:8000 on your machine. A1.7's human-gate demo needs it; run it yourself if learner machines struggle.Fifteen minutes before the first lesson. A taught session opens with this; alone, read it and move on.
A chatbot that is wrong says something wrong. An agent that is wrong does something wrong — it cancels a booking or moves money. The verb is the whole difference, and everything in Function A follows from it.
You are going to build the agent first and secure it second, in that order, because every control in the five functions after this one attaches to a mechanism you will have written yourself. There is no adversary in Function A. That is deliberate: you cannot reason about an attack on a system you cannot describe.
Hold one sentence through all sixteen lessons: the model proposes, your code decides. Most of what follows is the second half of that sentence.
Key idea, the prompt to paste, what it prints, and the question to answer before moving on.
You leave this module with Claude running the repo and a written guess for where each of the nine agent parts lives. Keep the sheet — it is marked in Module 4, and the difference between your guess and the answer is the point.
Paste this once at the start, so Claude knows how to behave for the whole course:
You are my tutor for Cyber Commons Function A. The repo is in my connected folder.
For each lesson I name: (1) explain the Risk and Control in plain English in 3 sentences,
(2) run the lesson's "Do this" steps and checkpoint diff for me and show the real output,
(3) ask me one question to check I understood before moving on.
Never invent output. If a command fails, show me the error and what it means.A skill is a written procedure (SKILL.md) the model follows. The document and the instruction are the same bytes, so you can read exactly what runs.
Run scripts/doctor.py and explain each ok / FAIL / -- line to me.
Then run scripts/lesson.py A0.0 and tell me exactly what happened.The doctor ends with a "ready" summary; -- lines are fine. lesson.py either completes and names the model, or stops with "no model configured". Both are correct.
If it stops, that is the lesson, not a failure. The program refused to invent an answer rather than print something plausible, and that is the first security behaviour of the day. Way 3 of every lesson needs no model at all.
Your operating system matters here and almost nowhere else. The page gives Windows and Mac their own lines throughout. On Windows the command is python, not python3 — typing python3 opens the Microsoft Store.
Zero contract violations means the answer had the right shape. Does it mean the answer is right?
Answer. No. Shape is not truth.
Lab. Set your computer up from nothing, run one skill and read back which model answered, then find your role's row and the lesson it starts at.
Each of the nine is a component to a builder and an attack surface to an attacker.
Explain the nine words (harness, memory & state, RAG, MCP, skills, guardrails,
evals, A2A, multi-agent) as if to a beginner, one line each, using a
travel-booking example. Do not tell me which files they live in.Nine one-line explanations and no file names. The lesson's own exercise is six numbered steps on paper, and it tells you to write a question mark where you have no idea.
You are guessing on purpose. Six of the nine files do not exist on your computer yet — runtime.py, memory.py, identity.py, observability.py, mcp/internal_server.py and a2a/protocol.py get created across Modules 1–3, by you. There is nothing to look up, and a wrong guess costs nothing.
How the nine stack up. The harness is the agent. Memory, RAG, MCP and skills feed context in. Guardrails sit on the way out and are the only one that says no. Evals sit beside it. A2A and multi-agent are several harnesses at once.
Every arrow into the harness is a way for text you did not write to reach the model. Which of the nine worries you most, and why?
No single right answer — having one of your own is the point.
Lab. Find all nine in the finished CyberTravels tree (checkpoint A2.5) — a file for each — and count how many you placed.
In 65 minutes you see the four things that sit between a model's suggestion and a real action: a verifier, a process boundary, an identity per actor, and one token per action.
| Who | Role | And so |
|---|---|---|
| Dana | traveller | books and cancels her own trips. Cannot refund anything |
| Alex | agent_ops | runs the platform. Can write bookings, cannot refund |
| Priya | finance | the only one of the three who may approve a refund |
Map the system before arguing about its security. The edges where trust changes are where every control will go.
Run lesson A1.0's checkpoint diff, then draw me a simple diagram of
CyberTravels' components and mark which edges cross a trust boundary.9 components, 8 present. egress is absent, and that absence is a finding rather than a gap.
It is not nine components to nine skills, and the page says so. One skill covers four of them, and egress has none, because you cannot check a component nobody built.
The lesson's component table names, for each component, the file you write, the lesson that builds it and the skill that checks it. It is worth keeping open for the rest of Module 1.
Project the component table and leave it up for the whole module. It is the only place the shape of the build is visible at once.
Why mark a box that doesn't exist?
Answer. So nobody later argues about controls for a component nobody built.
Lab. Map the architecture you are about to build, and mark where trust changes.
A loop with no verifier accepts whatever the model says it did, and a demo that 'works' has never been checked.
Plan, act, verify — with the verifier independent of the thing it checks.
The loop's third stage is the one most systems skip. Plan, act, verify — with the verifier independent of the model.
Open cybertravels/runtime.py, show me _verify_result, and run the two refund
checks from lesson A1.1 (asked 140, got 1400; asked 140, got 140).First check prints asked to refund 140, resource server refunded 1400. Second prints None, which in this function means nothing wrong here.
Predict before you run the "Your turn". Replace _verify_result's body with return None and rerun. The 1400 refund now passes silently. Nothing errors, no span says anything is wrong, and the trace is tidier than before — a reviewer reading it sees a clean run. That is what a missing verifier looks like from the outside.
This is the lab to slow down on. If the room only remembers one thing from four hours, it should be the tidier-trace point.
Why not just ask the model whether its answer was right?
Answer. That is a second opinion, not a verification.
Lab. Build the loop and add the independent verifier that decides what it may accept.
Tools called in-process share the agent's authority by default, and there is no place left to put a check.
A resource server per trust domain, each with its own audience.
A tool called in-process shares the agent's authority, leaving nowhere to put a check. One resource server per trust domain, each with its own audience.
Install cybertravels/requirements.txt, then print config.TOOL_POLICY as in
lesson A1.2 and explain the audience and HIGH RISK columns.7 tools: 5 mcp:internal, 2 mcp:vendor. 2 marked HIGH RISK — cancel_booking and issue_refund.
Starting an MCP server shows a blank cursor and nothing else. A1.2 says so explicitly: "It will look like nothing happened… silence means it is running and waiting." Without that line this is ten minutes of thinking you broke it. Control-C stops it.
Have the two servers already running on your machine. The install step is the most common place a room desynchronises.
A tool's description says read-only. Should you believe it?
Answer. No. Annotations are hints, not guarantees, and B1.9 is the lesson on what that enables.
Lab. Stand up both MCP servers and list their tools from the client.
A shared service-account key makes every action look identical in the log, and no investigation can name who caused one.
A workload identity per agent, and a session token for the human that grants nothing downstream.
Three principals in every action: the human who asked, the workload that acted, and the individual call.
Mint Dana's user token and the workflow agent's token as in lesson A1.3,
decode both, and compare them side by side.Two different kinds of identity. Dana's token carries exactly one scope, agent:invoke — she may ask an agent to act, not act herself.
Meet the cast here. Dana, Alex and Priya appear on this page and in every example to the end of Module 3. The table above is worth a second read before moving on — A1.4 turns on the difference between Dana and Priya.
Three principals: the human, the workload, the call. Which question can't you answer if you only log one?
No single right answer — having one of your own is the point.
Lab. Mint both tokens and read the claims that make them different.
An agent holding a long-lived token with every scope is one prompt away from using all of them.
Per-action exchange, least privilege keyed to the human's role, enforced at the resource server.
A long-lived, all-scope token is one ambiguous sentence from misuse. Exchange a token per action, keyed to the human's role.
Run lesson A1.4's loop that asks for payments:refund as Dana and then as Priya.
Explain why the results differ.dana -> REFUSED: role 'traveller' may not delegate 'payments:refund' and priya -> minted.
Where the refusal happened matters more than that it happened, and the page lists all three: Dana's request stopped before the model was asked anything, before any booking was looked up, and before the payment server was contacted at all. Two independent things must fail for a refund to go through, and the second does not depend on the model.
Is Dana's refusal a broken button?
Answer. No: same code, same request, different person.
Lab. Exchange a token, then watch a traveller's role refuse to delegate a refund scope.
The theme is that untrusted text travels — into memory, between agents, and round a loop that never stops. Each lab shows the label or the limit that contains it.
Text an agent read becomes a fact an agent learned, and one vendor sentence outlives the request that fetched it.
Origin travels with content; recall never crosses an owner boundary; delete and export both exist.
Text an agent read becomes a fact it learned, unless the origin travels with it.
Run lesson A1.5's memory example: save the policy sentence and the
vendor-document sentence for owner 1, then print the prompt block for
owner 1 and owner 2.Owner 1 shows [trusted, origin=policy] and [UNTRUSTED, origin=vendor-document]. Owner 2 prints '' — an empty string.
Two things to look at, in this order. The labels survived the write, so the two sentences do not arrive with equal weight. And owner 2's block is empty: same call, different owner, nothing shared. The page's words — "closed here by storage, not by cleverness."
Predict before you run the "Your turn". If the origin column is dropped, what does the model see? Both sentences now carry equal weight, and nothing errors.
Why is the label the control, rather than an instruction telling the model to ignore untrusted text?
Answer. An instruction is a request; a label is structure.
Lab. Write a vendor sentence into memory and watch it come back labelled untrusted.
A peer's message read as a colleague's instruction turns one injected document into four compromised agents.
Signed envelopes, the human carried through every hop, and a ceiling on hops.
A peer's message read as a colleague's instruction turns one poisoned document into four compromised agents.
Run both experiments in lesson A1.6: tamper with a signed envelope, then
forward a message in a loop. Explain each error.Experiment 1 raises A2AError: signature does not match. Experiment 2 prints hops 1, 2, 3 — each still carrying dana and tr-1 — then stops with hop ceiling reached (4).
Both errors are the result, which the page says up front: "in both cases, the error message is the result you are looking for, not a sign something went wrong."
The "Your turn" is a bug that really shipped. Replace forward(...) with a fresh envelope(...) and the hops print 0 forever — the ceiling never fires. That was the real state of this code for one release: nothing incremented the counter, so MAX_HOPS was unreachable. Only a test that forwards for real would have caught it.
The error message was the result we wanted. Where else in security is a refusal the success case?
No single right answer — having one of your own is the point.
Lab. Forge a peer message and watch verification refuse it.
An unbounded loop against an impossible task spends until somebody notices, and a gate nobody can approve fast enough is a gate that gets removed.
High-risk actions gated on a named human; budgets that bind and are recorded when they bind.
Two ceilings on one loop, failing in opposite directions: a gate nobody can keep up with, and a budget that spends until somebody notices.
Run lesson A1.7's budget snippet and explain what the final word it prints means.8 12, then 12 tool_calls. The run ends saying which limit it hit — an unfinished answer that admits it is unfinished.
The gate, in your browser. Run ./cybertravels/run.sh, sign in as Dana, ask to cancel CT-4417. The lesson's steps are numbered: watch it stop and name the scope it wants, approve once, then ask again and refuse. Both decisions are recorded — a gate that only logs the yeses cannot answer what did it try to do.
Worth sitting with. At 10 approvals a day a person reads each one; at 400 they approve the queue. Coverage stays at 100% while real review falls to zero. That is B3.9, and it is why a human gate is a control with a capacity rather than a control.
Run the browser half from your machine if learner setups are uneven — it is the one lab that needs the web app running.
12 calls is a ceiling on the run. What stops all 12 hitting one traveller's booking?
Answer. Nothing yet. That is the per-target ceiling, and it is built in B3.4.
Lab. Approve one action, refuse another, then exhaust the budget on purpose.
The agent works. This module asks whether anyone else could investigate it, and whether its scores mean anything. Hold one scenario across all five labs: a traveller disputes a cancellation three weeks later, and the only log line says run completed.
A demo promoted to production carries none of the machinery an incident needs, and the first investigation discovers that at the worst moment.
Spans, an audit trail, an evaluation, and a stop — built before they are needed.
Measure the gap before building anything.
Run the audit-answerability-check skill from lesson A2.0 and show me which of
the three questions the sample log cannot answer.answerable_count: 0 — all 3 unanswerable. Every row says agent-svc, and there is no motivating input at all.
Two triples, and they are not the same triple. The three capabilities this chapter builds — a trace, an audit trail, an evaluation — are not the three questions the skill scores. The skill asks: which human, what motivated it, which hop. It is a number out of 3.
Is the agent identity the same as the principal?
Answer. No. It answers what ran, never who wanted it.
Lab. List what your run currently cannot tell an operator.
A trace holding only successful calls hides exactly the events worth alerting on, and a token pasted into a span is a credential in the log pipeline.
One trace id joining the reasoning to the audit row; refusals as first-class spans.
A trace of only successes hides what is worth alerting on, and a token pasted into a span is a leaked credential.
List the 12 span kinds in cybertravels/observability.py and explain why
start and done matter.12 span kinds: thought, plan, approval, token_issued, denied, tool_result, final, budget, escalation, start, error, done. The four at the edges — start, error, final and done — are the ones a hand-rolled tracer leaves out, and they are what make a missing span visible.
Four refusal points, four different incidents, and the page names all four: policy is a control working as designed; human is somebody saying no; verifier means the call was authorised, ran, and came back unacceptable; resource server means a token that should never have existed reached a boundary — that is the one that wakes people up.
Predict before you run the "Your turn". What happens if the whole token is logged instead of its claims? The trace gets more useful, and the credential is now in every log backup.
A trace with no done span: is that a run still going, or a run that died?
Answer. You cannot tell, which is why the pair exists.
Lab. Emit a run's spans and join them to the audit log by trace id.
An append-only log the workload can still edit proves nothing, and one that records only successes cannot show what was attempted.
Append-only storage, the delegation chain on every row, and refusals recorded alongside actions.
Every audit row must answer four questions: which human, which workload, which call, and what motivated it. The fourth is almost always missing.
Run the attribution-ledger-check skill from lesson A2.2 and explain question 4
in its output.4/4 answered, and question 4 reads roughly: the traveller asked about a double charge, but wiki/473 — a retrieved document, origin knowledge — is what triggered the DELETE.
The count changed, and that is the point. A2.0 scored out of 3; this is out of four. The fourth question — which call, with its audience and scope — is the one A2.0's three did not include. It is deliberately the same incident as A2.0, told by a record designed to answer.
Without question 4, how does this incident get closed?
Answer. "The agent misbehaved", which fixes nothing.
Lab. Put the four questions to your own audit rows and record which one fails.
A suite everything passes measures nothing, and a score with no interval is a number that will move next week and nobody will know why.
Cases that fail on the old build and pass on the new one, scored with intervals.
A score needs an interval, cases that fail on the old build, and protection from dilution.
Run the eval-suite-health-check skill from lesson A2.3. Then explain how adding
30 easy cases would change the aggregate score.Per-case rates with 95% intervals, for example INJ-01 0.055 (0.033, 0.077). Then the diluted aggregate, with the build unchanged and the skill saying so — "The build did not change. The number improved by 60%."
Conformance versus accuracy: an empty result matches every schema. Is it correct?
No single right answer — having one of your own is the point.
Lab. Run the suite, then dilute it with easy cases and watch the score rise.
"The agent is 90% accurate" with no denominator, no matcher named and no judge validation. Three different numbers can be quoted from one run, the most flattering is the easiest to compute, and an unvalidated judge is a second unmeasured model grading the first.
Exact-match tool-call accuracy reported with its n and beside the two weaker matchers, output accuracy with unscoreable runs in their own column, and a judge whose agreement with ground truth is published before its verdicts are.
Three matchers give three numbers from the same runs. Quote exact match, with n.
Run skills/research/agent-eval-scoring/scripts/agent_eval_scoring.py and explain
why name-only and order-ignored scores are higher than exact match.Exact 0.500, name-only 0.667, order-ignored 0.667, n=6. Output accuracy 0.400 — 2 correct, 3 incorrect, 1 unscoreable.
What each weaker matcher forgives. Name-only forgives R2, which refunded 1400 where 140 was owed. Order-ignored forgives R4, which booked the new seat before releasing the old one so the traveller held two. Different failures, hidden by each — which is why quoting one of them alone is worse than quoting neither.
If you have an older copy of this guide: output accuracy is 0.400, not 0.600. The scorer previously used substring matching and scored R2's 1400 as correct, because "140" sits inside "1400.00" — the lesson was committing the error it teaches. It compares numbers as numbers now, and R2 fails both surfaces.
Someone says our agent is 90% accurate. What three things do you ask?
Answer. Accurate on which matcher, over how many runs, and who judged it?
Lab. Score six agent runs three ways, then check the judge against the runs whose answer you already know.
You switch from builder to attacker's-eye view, put a number on what your agent could damage, and prove to yourself what you now know. The final tasks are done without Claude, on purpose — and the lesson page says so in those words.
Builders who never see their own system described adversarially ship the same defect in the next one.
The same architecture map, annotated with what an attacker reaches for at each edge.
Blast radius = what one run can reach × how irreversible its actions are × how long until a human can stop it.
Run the blast-radius-review skill from lesson A2.5 and explain which actions are
irreversible and which need human approval.A table of actions with reversibility and routing. 4 are irreversible — delete_row, send_email, issue_refund and rotate_credential — and 2 of those are also external: send_email and issue_refund. Those are the ones routed to human approval.
Nothing in the Function B column is a criticism of what you built. It is what the build looks like to somebody who wants it to fail, which is a different question from whether you built it well.
Say that out loud before showing the handover table. A room that reads it as a list of their mistakes disengages from Function B before it starts.
Which number decides how much autonomy this agent can be given?
Answer. The blast radius, which is why it is the last thing Function A produces and the first thing Function B argues with.
Lab. Compute the blast radius of the agent you just built.
work/finished, open the folder, and tick each correct guess from Module 0. All nine words now have a file, and you wrote every one. The guesses you got wrong are the useful half — write down why you expected it somewhere else.Check your own three answers against this, or mark somebody else's. An answer that misses a name but gets the order right is the better answer.
| The question | What a good answer contains |
|---|---|
| What can it do? | Names the tools, the high-risk ones, and that it acts on behalf of a named human rather than as itself. |
| What stops it? | In order: delegation refused by role → human gate on irreversible actions → resource server verifies the token → verifier checks the result → budget stops the loop. An answer that gets the order right counts even if a name is fuzzy; the order is the understanding. |
| Where would you look at 3am? | The trace, by trace id. Then the audit rows, starting with any denied span — and which of the four places it was denied, because that alone tells you whether it is a control working or a credential that should not exist. |
Eight questions. Cover the answer column, or use any three with a room.
| Question | Answer |
|---|---|
| 1. In "the model proposes, your code ___", what is the missing word? | Decides (or disposes) |
| 2. Why must the verifier not be the model? | A model grading itself is an opinion, not a check |
| 3. Why put tools behind a separate MCP server? | So a check can run outside the agent, and tokens bind to one audience |
| 4. Dana asks for a refund. What stops it, and before what? | The token exchange refuses her role's scope — before the model is asked, before any booking is read, and before the payment server is contacted |
| 5. What makes a vendor sentence in memory safe to read back? | Its origin label travels with it: UNTRUSTED, origin=vendor-document |
| 6. What does a hop ceiling protect against, and what breaks it? | Endless agent-to-agent loops; building a new envelope instead of forwarding resets the count to zero |
| 7. Which of the four audit questions is usually missing? | What motivated the action — the input and its origin |
| 8. "90% accurate": name three things missing from that claim | The matcher, n, and judge validation (or the interval) |
| What you built | Attacked in | By |
|---|---|---|
| Ingress accepting traveller text | B1.2 — Prompt injection | prompt injection |
| The vendor MCP server | B1.3 — Indirect prompt injection | indirect injection, through a document you fetched |
| Tool descriptions you trusted | B1.9 — Injection through content the agent was asked to read | a rug-pull after approval |
| Memory with origin recorded | B1.4 — Memory poisoning | what happens when the origin is dropped |
| Agent-to-agent envelopes | B1.7 — Identity spoofing and impersonation | one injection reaching four agents |
| The per-action token exchange | B2.3 — Delegation that narrows, and survives audit | and systems that log it without enforcing it |
| The human gate | B3.9 — Turning a control off without turning the system into an experiment | at four hundred approvals a day |
| The audit trail | B1.14 — Repudiation and untraceability | and the question it still cannot answer |
Function A is the shared floor. After it, a reader goes wherever their job is:
| Pitfall | What to do | If you are running it for a room |
|---|---|---|
| Accepting Claude's narration as the result | Find the actual printed output and compare it against this page. This is the course's own lesson applied to the course, and it is the single easiest way to come out of four hours having learned nothing. | Make the checker in each pair responsible for exactly this. |
| Reading "no model configured" as failure | It is the program refusing to make something up. Way 3 of every lesson needs no model, so an unconfigured machine is not a blocked reader. | Reframe it out loud every time it appears in the room. |
| Edits from a "Your turn" blocking the next lesson | The run prints stopped, not FAILED, says the edits are safe, and offers two choices. Use --out for a fresh folder; do not --force away work you wanted to keep. | — |
| Rushing past the predictions | The predict-then-run step is where the learning happens — a prediction you got wrong teaches more than output you expected. | Protect the time even where a lab finishes early. |
| Turning it into an attack class | Function A has no adversary by design. An attack question is a Function B question, and arriving there with a system you can describe is the whole point of doing this first. | Keep a visible parking lot and put them in it. |
| An expected output here not matching the run | Trust the run, not this guide, and correct the source. Every number on this page is generated from the tree for exactly this reason, but a prompt's wording can still drift. | — |
| What you see | Why | Fix |
|---|---|---|
python3 opens the Microsoft Store | Windows uses python | python or py -3 |
command not found right after installing | Old terminal session | Close the terminal and open a new one |
| Python 3.9 or older | Too old for the repo | Install 3.10+; on Windows tick Add python.exe to PATH |
import jwt fails | PyJWT missing | pip install PyJWT |
| A lesson prints stopped | You edited code in a "Your turn" | --out a fresh folder to keep the work, or --force to reset |
main.py does not exist at this checkpoint yet | Tree from before A1.1 | Run the checkpoint command the message prints |
The doctor shows -- lines | Something optional is absent | Nothing to fix. If the summary says ready, you are ready |
| When | Prompt |
|---|---|
| Starting a lesson | Summarise lesson <id>'s Risk, Control and Day 0/1/2 in plain English, under 100 words. |
| See what changed | Run scripts/checkpoint.py --at <id> --diff and explain the changed lines like I'm new to Python. |
| Predict before "Your turn" | Before you run it: here is my prediction for the Your turn change: <prediction>. Now run it and tell me if I was right. |
| Stuck on an error | Show me the exact error, what it means, and the smallest fix. Don't change anything else. |
| Check understanding | Quiz me with 3 questions on lesson <id>. Don't give answers until I reply. |
| Connect to the attack side | Which Function B lesson attacks what I built in <id>, and how, in two sentences? |
| When something will not run | Run scripts/doctor.py and tell me only the lines that are not ok, with the fix for my operating system. |
| Term | In one line |
|---|---|
| Agent | Software that plans, calls tools and acts on what it reads |
| Harness | The loop around the model: context in, tool call out, result back |
| Verifier | Code, not a model, that checks a result before it is accepted |
| MCP | Model Context Protocol — a standard way for agents to reach tools |
| Sink | Somewhere data can do damage |
Audience (aud) | The one server a token is valid at |
| Scope | The one permission a token grants |
| Workload identity | A name for a piece of software, e.g. spiffe://…/agent/workflow |
| Token exchange | Swapping a user token plus an agent identity for a short, narrow, per-action token |
| A2A | Agent-to-agent messaging |
| Span / trace id | One recorded step of a run / the id that joins all of them |
| Canary token | A credential that looks real and that nothing legitimate ever uses |
| Blast radius | What one run can reach and damage before a human can stop it |
| Conformance vs. accuracy | Whether the answer has the right shape vs. whether it is right |