All lessons › Function F — AI Governance for Agentic Systems › Building the Governance Framework — Risk and Control
F1.11

Model risk management for AI systems

F1
▶
Lightboard recording

Not recorded yet. The lesson below is complete and runnable today — the video is added later without touching this page.

Video placeholderpublishes automatically from recordings/F1.11.mp4
Risk

The 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.

Control

Extend the SR 11-7 lineage — conceptual soundness, ongoing monitoring, independent validation — to non-deterministic, tool-using systems, and name where it still holds.

The lab

Take a validated model, add one tool, and show which parts of the validation are now void.

◉Use case relevance

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.

At CyberTravels. 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.

◴What this lesson is — Day 0, Day 1, Day 2

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.

Day 0 — why

The classical model-risk playbook silently breaks once the model can act, because validation was scoped to predictions.

Day 1 — how

Re-read the three pillars for a model that calls tools.

Day 2 — measure

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 measuredenominator or target
ongoing monitoring coverageshare of the model estate; a key control indicator programme in older vocabulary

▦The framework, and how it works

   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:

  1. Conceptual soundness — is the method appropriate for the purpose?
  2. Ongoing monitoring — is it still performing as validated?
  3. Independent validation — did someone other than the builder check?

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.

2 · The three pillars, and what each assumes

3 · The unit of validation, before and after tools

4 · Where it breaks — monitoring the wrong thing well

5 · The control — revalidate on the triple, not on the weights

6 · Verify — what a validation record must now carry

7 · The procedure, as a skill

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.

8 · And the change that ships as an improvement

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.

▶Real time execution as skill

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, Glob

The validation was of a system that had no tools

Model 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.

When to use this

Applying an existing model risk framework to agents, and at every autonomy or tool-manifest change afterwards.

Procedure

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.

Example

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.

Output contract

{
  "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"]
}

Failure modes

  • Recording validation scope as the model. It is the system.
  • Monitoring output distribution only. The actions are the risk.
  • Calendar re-validation. The triggers are events, not dates.

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, Glob

The rate limit was the control

Hosted 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.

When to use this

Assessing the risk of an open-weight release, comparing hosted and local deployment, or evaluating a safeguard that exists only in the serving layer.

Procedure

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.

Example

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.

Output contract

{
  "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}
}

Failure modes

  • Listing serving-layer safeguards as mitigations for a weight release.
  • Comparing capability and ignoring throughput. Throughput is the bigger term.
  • Assuming a low success rate is a control. It is, until the attempt budget changes.

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.

1In your AI agent — you are taught

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.11

Then 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:

agentinstall just for this agentstart it
Claude Codepython3 scripts/install_skills.py --tool claude --lessons F1.11type /f1-11-model-risk-management-for-ai-systems
GitHub Copilot (VS Code)python3 scripts/install_skills.py --tool copilot --lessons F1.11type /f1-11-model-risk-management-for-ai-systems in Chat
Cursorpython3 scripts/install_skills.py --tool cursor --lessons F1.11type / in Agent chat and search for it
Codexpython3 scripts/install_skills.py --tool agents --lessons F1.11type $f1-11-model-risk-management-for-ai-systems, or run /skills

2As one Python command — you just run it

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.11

3Read the code, and the difference — nothing runs

Neither 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 --diff

On 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.

✓What you just proved

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.

✎Your turn

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

Inspect

Skill source: skills/grc/model-risk-validation-scope

← PreviousF1.10 · The stakeholder map — who owns what