Not recorded yet. The lesson below is complete and runnable today — the video is added later without touching this page.
recordings/F1.11.mp4The classical model-risk playbook silently breaks once the model can act: conceptual soundness was validated, and then the agent was granted write access nobody validated.
Extend the SR 11-7 lineage — conceptual soundness, ongoing monitoring, independent validation — to non-deterministic, tool-using systems, and name where it still holds.
Take a validated model, add one tool, and show which parts of the validation are now void.
Model risk management has forty years of doctrine on validating models — conceptual soundness, ongoing monitoring, independent validation. Most of it transfers. The part that does not is the part where the model calls tools.
validation_scope() returns a validation that is complete against the classical list and invalid for an acting model. Conceptual soundness, input quality, output accuracy, limitations and monitoring all pass; authority, reversibility, blast radius, adversarial reachability and containment were never asked, because no classical template contains them.How the classical model-risk playbook breaks once the model can act — a validation complete on conceptual soundness, accuracy and monitoring, and silent on authority, reversibility, blast radius, reachability and containment.
The classical model-risk playbook silently breaks once the model can act, because validation was scoped to predictions.
Re-read the three pillars for a model that calls tools.
Ongoing monitoring, which is a key control indicator programme in older vocabulary — the lineage that convinces a risk function this is not new.
Measure this
| what to measure | denominator or target |
|---|---|
| ongoing monitoring coverage | share of the model estate; a key control indicator programme in older vocabulary |
SR 11-7 lineage what an agent adds +----------------------+ +-----------------------+ | conceptual soundness | ok | it calls tools | | ongoing monitoring | ok | it acts on the world | | independent validation| ok | output is not a number| +----------------------+ +-----------------------+ most of forty years of doctrine transfers. the tool call does not.
Model risk management is not new. The SR 11-7 lineage has governed models in regulated institutions for over a decade, and its three pillars are sound:
All three still hold for AI systems. What breaks is not the framework but a silent assumption underneath it: that a model produces an output, and a human decides what to do with it.
Once the model can call a tool, that assumption is void. Validation scoped to the model's predictions says nothing about the model's actions. You can hold a perfectly valid validation report for a system that has since been granted write access to a production database, and nothing in the classical process is required to notice.
So the extension is narrow and specific: the unit of validation becomes the model plus its tool surface plus its autonomy level, and any change to any of the three triggers revalidation — not just a change to the weights.
Anchor → F1.1. Model risk management arrived at the same answer decades earlier: SR 11-7's ongoing monitoring is a KCI programme in older vocabulary. The lineage matters because it is the argument that convinces a risk function this is not new.
A model validated with no tools at L1 is deployed with three tools at L3 — same model, same version, different system. The skill diffs validated against deployed and lists what the monitoring never observes.
cybertravels/governance/seams.py separates a classical validation scope from the five activities that only exist once the model can act — authority, reversibility, blast radius, adversarial reachability, containment. A validation can be complete against the classical list and say nothing about any of them. capability_delta() is the trigger: more capability is a re-tiering event even when the release note calls it an improvement, and this skill measures the delta.
The skill — skills/grc/model-risk-validation-scope/SKILL.md
name: model-risk-validation-scope
description: >-
Check whether a model validated under one autonomy level and tool set is still
covered by that validation as deployed, and find the monitoring that stops at
the model's output. Use when applying model risk management to an agentic
system.
allowed-tools: Read, Grep, GlobModel risk management carries three pillars — validation, monitoring, governance — and each makes an assumption that agentic deployment breaks. Validation assumes the thing validated is the thing deployed; a model validated with no tools at L1 and deployed with three tools at L3 is the same model and a different system, and the validation does not cover it.
Applying an existing model risk framework to agents, and at every autonomy or tool-manifest change afterwards.
1 — Write down what was validated. Model, version, tool set, autonomy level, data scope. Validation scope is usually recorded as the model alone, which is the defect.
2 — Write down what is deployed, in the same fields. Then diff. Any difference in tools or autonomy means the validation does not cover the deployment, and that sentence is the finding.
3 — Check what monitoring observes. Most monitors the model's output distribution. List what it does not observe — rows written to production, actions taken, resources reached — because that is where agentic risk lives.
4 — Name the re-validation triggers. Tool added, autonomy raised, model version changed, data scope widened. Without triggers, re-validation happens on the audit calendar, which is the assumption that failed in the first place.
5 — Report per pillar. Validation coverage, monitoring blind spots, governance triggers. Three findings with three owners rather than one finding about the framework.
Input — the fixture committed at the top of scripts/model_risk_validation_scope.py. Edit it and re-run: the buckets, counts and verdicts below are derived from it, not hard-coded.
Output — the opening lines of a real run:
pillar what it asks what it quietly assumes
conceptual_soundness is the method appropriate for the purpose assumes the purpose is stable and stated
independent_validation did someone other than the builder check assumes the thing checked is the thing deployed
ongoing_monitoring is it still performing as validated assumes performance is what changes
All three survive contact with AI. The assumptions are what break.
validation still covers what is deployed: False
tool surface changed: ['db_update', 'read_ticket', 'write_ticket']
The run continues past this. test_skills.py executes the script on every build, with no model configured — so what CI proves is that it runs and refuses legibly, not that it prints these lines. The output above is a recorded run against a real model, and nothing re-diffs it: a model's answer is not reproducible, and this repository does not claim otherwise anywhere it can be checked.
{
"validated": {"model": "str", "version": "str", "tools": ["str"], "autonomy": "str", "data": ["str"]},
"deployed": {"model": "str", "version": "str", "tools": ["str"], "autonomy": "str", "data": ["str"]},
"covers": false,
"differences": ["str"],
"monitoring": {"observes": ["str"], "does_not_observe": ["str"]},
"revalidation_triggers": ["str"]
}
The skill — skills/research/weight-access-capability-delta/SKILL.md
name: weight-access-capability-delta
description: >-
Enumerate the capabilities local weights grant that a hosted API does not, and
convert a rate limit into an attempt budget to show what removing it does to a
low-probability technique. Use when assessing open-weight release risk or
arguing about hosted safeguards.
allowed-tools: Read, Grep, GlobHosted access and local weights differ in two ways that matter and one that gets all the attention. The capability delta — fine-tuning away refusals, reading activations, sampling without a filter — is real. The larger one is arithmetic: a hosted rate limit caps attempts, and removing it turns a technique with a 0.5% success rate into tens of thousands of successes in a day.
Assessing the risk of an open-weight release, comparing hosted and local deployment, or evaluating a safeguard that exists only in the serving layer.
1 — List the capabilities local access grants. Weight modification, activation access, unfiltered sampling, arbitrary system prompts, no logging. For each, say whether a hosted API offers it.
2 — Turn the rate limit into an attempt budget. Requests per minute × the window. Do the same for local inference from its throughput. Report the ratio; it is usually two or three orders of magnitude and it is the headline.
3 — Apply a per-attempt success rate. A technique that works 0.5% of the time produces a handful of successes hosted and tens of thousands locally. The technique did not change.
4 — Assess readiness for each safeguard. Which safeguards survive weight access at all — the ones in the serving layer do not. Say so plainly rather than listing them as mitigations.
5 — Weight the blast radius by scope. A capability that reaches a team's resources is not the same as one that reaches a run's own. Score tools by scope and mark which are gated.
Input — the fixture committed at the top of scripts/weight_access_capability_delta.py. Edit it and re-run: the buckets, counts and verdicts below are derived from it, not hard-coded.
Output — the opening lines of a real run:
setting attempts in 24h
------------------------------------------------------
hosted API, 20 req/min 28,800
hosted API, 20 req/min, 5 keys 144,000
local open weights, 1 GPU 691,200
local open weights, 8 GPUs 5,529,600
ratio: 192× more attempts, with no abuse signal reaching anyone.
The run continues past this. test_skills.py executes the script on every build, with no model configured — so what CI proves is that it runs and refuses legibly, not that it prints these lines. The output above is a recorded run against a real model, and nothing re-diffs it: a model's answer is not reproducible, and this repository does not claim otherwise anywhere it can be checked.
{
"capabilities": [{"name": "str", "hosted": false, "local": true}],
"attempts": {"hosted_per_day": 0, "local_per_day": 0, "ratio": 0},
"technique": {"per_attempt_rate": 0.0, "hosted_successes": 0, "local_successes": 0},
"safeguards": [{"name": "str", "layer": "serving|weights", "survives_local": false}],
"blast": {"tools": [{"name": "str", "scope": "self|project|team", "gated": false}], "score": 0}
}
Three ways to do this lesson. Pick one. They run the same procedure against the same code — what changes is who drives it, and how much you see.
The agent reads the lesson, explains the idea, fetches the code, runs the check and answers your questions as you go. This is the one to take if you are here to learn.
Install it, once. From the folder you cloned. --all does every agent it finds on your machine:
python3 scripts/install_skills.py --all --lessons F1.11Then restart your agent and open it in that folder. On Windows, if python3 says Python was not found, use python instead.
Then pick f1-11-model-risk-management-for-ai-systems:
| agent | install just for this agent | start it |
|---|---|---|
| Claude Code | python3 scripts/install_skills.py --tool claude --lessons F1.11 | type /f1-11-model-risk-management-for-ai-systems |
| GitHub Copilot (VS Code) | python3 scripts/install_skills.py --tool copilot --lessons F1.11 | type /f1-11-model-risk-management-for-ai-systems in Chat |
| Cursor | python3 scripts/install_skills.py --tool cursor --lessons F1.11 | type / in Agent chat and search for it |
| Codex | python3 scripts/install_skills.py --tool agents --lessons F1.11 | type $f1-11-model-risk-management-for-ai-systems, or run /skills |
No agent, no conversation. The same lesson executes and prints the same readback. Take this one if you have no assistant, if you are reviewing rather than learning, or if you want the result without the teaching around it.
python3 scripts/lesson.py F1.11Neither of the above, and no model needed. The first command writes CyberTravels exactly as it stood at the end of this lesson; the second prints the diff — the lines this lesson added or changed, and nothing from any later one.
python3 scripts/checkpoint.py --at F1.11 --out work/cybertravels
python3 scripts/checkpoint.py --at F1.11 --diffOn Windows, type python wherever these say python3 — and use \ instead of / in the paths. Everything else is identical. A0.0 step 2 explains why.
Ways 1 and 2 need a model; way 3 does not. A signed-in Claude Code CLI needs no API key, and any OpenAI-compatible endpoint works too. With neither, the audit exits 2 and says so rather than inventing an answer. A0.0 sets this up.
Ways 1 and 2 both end with the same readback: What I did, What changed, The number and Read this next. A step that was skipped or refused is reported as exactly that, never as a pass.
If you did the last lesson’s challenge, expect this to stop. Most challenges ask you to edit the code, and ways 1 and 2 will not overwrite your edits: you get stopped, not a failure, with two options — --out for a fresh folder that keeps your work, or --force to discard it and start this lesson clean.
The three SR 11-7 pillars, each with the assumption it quietly makes. A system validated with no tools at L1 is shown deployed with three tools at L3 — same model, same version — and the validation no longer covers it. Monitoring reports 200 clean runs of summarisation accuracy while four action-level metrics have no threshold at all, and four revalidation triggers classical MRM would miss are named.
Take one validated model in your estate and list the tools it holds today. If any of them post-dates the validation report, the report is describing a different system.
Tools used
Skill source: skills/grc/model-risk-validation-scope