Professional, lesson 18
Compliance and fairness
A policy that says data stays home
Lumen sells in three regions, and the legal team asks whether personal data leaves the region. Nobody has drawn where a ticket goes, and the agent scores 92% overall, which hides a group at 78%. This lesson turns regulation into a data-flow map and fairness into an eval sliced by group. This is the compliance desk at Lumen Supply, an online electronics shop. You will watch an analyst answer from a map that lists only the shop's own services, then fix the map and the eval.
Where does a ticket go, and who does it fail?
The model is one hop among many. A ticket passes through the form, the gateway, a queue, the agent, a database, and vendors that nobody drew. Each hop has a region and a class of data.
Three things go wrong, in this order. Nobody has drawn the flow, so a hop that leaves the region is invisible. Fairness is claimed from one overall score. And the claim that data stays home lives in a policy line, with no check in the system behind it.
A data-flow map
The analyst asks one question: does personal data leave the home region? It loads the system description, then calls hops. The map lists all eleven hops, each with its kind, region and data class.
Open the hops card. One row is flagged: the model provider, which holds personal data in the US while the home region is the EU. The flag is computed from the data, not typed in by hand.
- ReviewerLegal asks whether any personal data from a customer in the home region leaves that…
- Toolsload_system: {'name': 'Lumen support desk', 'home': 'eu', 'regions': ['apac', 'eu', 'us']}
Show the result
{ "name": "Lumen support desk", "home": "eu", "regions": [ "apac", "eu", "us" ] } - Toolshops: 11 hops listed, 1 flagged: model provider
Show the result
{ "hops": [ { "name": "order form", "kind": "service", "region": "eu", "data": "personal", "flagged": false }, { "name": "api gateway", "kind": "service", "region": "eu", "data": "personal", "flagged": false }, { "name": "ticket queue", "kind": "service", "region": "eu", "data": "personal", "flagged": false }, { "name": "support agent", "kind": "service", "region": "eu", "data": "personal", "flagged": false }, { "name": "order database", "kind": "service", "region": "eu", "data": "personal", "flagged": false }, { "name": "audit log", "kind": "service", "region": "eu", "data": "metadata", "flagged": false }, { "name": "data warehouse", "kind": "service", "region": "apac", "data": "metrics", "flagged": false }, { "name": "email sender", "kind": "vendor", "region": "eu", "data": "personal", "flagged": false }, { "name": "error tracker", "kind": "vendor", "region": "us", "data": "metrics", "flagged": false }, { "name": "translation service", "kind": "vendor", "region": "eu", "data": "personal", "flagged": false }, { "name": "model provider", "kind": "provider", "region": "us", "data": "personal", "flagged": true } ] } - AnalystYes. Personal data from the EU home region leaves it: the model provider in the US receives personal data and is…
A cross-region hop is flagged.
Hops and gaps, written as code
Two functions hold the work. hops walks the system description, and gap_by_group scores the labelled rows by group. The starting hops keeps the services and drops the vendors and the provider.
The fix lists every hop with its region, and flags a hop that carries personal data out of the home region. A gap on a small group is reported with its sample size, never waved off as noise.
Does 92% overall accuracy show the agent is fair to every group?
The review board sees an overall accuracy of 92% on 180 labelled tickets. It asks whether every language group is served equally well.
Predict: Does 92% overall accuracy show the agent is fair to every group?
- ANo, it can hide a group at 78%.
- BYes, 92% is high.
Show the answer
A. Fairness is read from a sliced eval. An overall score averages the gap away, because the large groups outvote the small one.
A map of own services only
This is a real Claude Haiku 5.5 run, recorded once and replayed here. The starting hops lists the seven services that Lumen runs itself. The analyst reads that list and finds no hop outside the EU that holds personal data.
It answers that no personal data leaves the region. The answer is false, and the result card is red. The model provider was never on the map, so nothing could flag it.
- ReviewerLegal asks whether any personal data from a customer in the home region leaves that…
- Toolsload_system: {'name': 'Lumen support desk', 'home': 'eu', 'regions': ['apac', 'eu', 'us']}
Show the result
{ "name": "Lumen support desk", "home": "eu", "regions": [ "apac", "eu", "us" ] } - Toolshops: 7 hops listed, 0 flagged
Show the result
{ "hops": [ { "name": "order form", "kind": "service", "region": "eu", "data": "personal", "flagged": false }, { "name": "api gateway", "kind": "service", "region": "eu", "data": "personal", "flagged": false }, { "name": "ticket queue", "kind": "service", "region": "eu", "data": "personal", "flagged": false }, { "name": "support agent", "kind": "service", "region": "eu", "data": "personal", "flagged": false }, { "name": "order database", "kind": "service", "region": "eu", "data": "personal", "flagged": false }, { "name": "audit log", "kind": "service", "region": "eu", "data": "metadata", "flagged": false }, { "name": "data warehouse", "kind": "service", "region": "apac", "data": "metrics", "flagged": false } ] } - AnalystNo personal data leaves the home region (eu) in the hop list: all five personal-data hops (order form, API gateway…
No cross-region hop was flagged.
Map every hop, slice by group
hops now lists all eleven hops and flags personal data outside the home region. The same question gets a different answer, because the provider is on the map with its region.
A flagged hop is a decision: move it, or accept it. Under GDPR, accepting a US hop needs two things. One is a data processing agreement, the contract that lets a vendor handle personal data for you. The other is a transfer basis, the legal reason the data may leave the region, such as standard contractual clauses.
Health data under HIPAA needs a business associate agreement, and US federal work needs a FedRAMP authorised provider.
The eval gets the same treatment. Tamil is 36 of 180 rows, 20% of the tickets, at 78% accuracy. English is 97%, a gap of 19 points, and 14 points below the overall 92%. A 14 point gap on 20% of tickets is a real cost, and one targeted fix is cheaper than a failure found by a regulator.
The same input now ends well
Use the switch to run the same question with the map of own services, then with the full map. The card marked "This is where the runs split" is the hops card: the second map has one flagged row.
The system, the question and the agent are the same in both runs. Only the artifact changed.
This part is interactive in the lab: run ./workshop watch compliance-ethics.
Try it: artifact and concern
Change one setting at a time. Pick the artifact, then the concern. Every combination is a recorded run, so this works with no internet.
With own services only, both concerns are missed, since the eval returns one number too. With the full map and the slices, both are named. A control in a document is a claim, and a control in the flow is a fact.
This part is interactive in the lab: run ./workshop watch compliance-ethics.
Slice the eval by group
The starting gap_by_group returns one number. The fixed version returns the accuracy and the row count for each group, then the worst group, the best group and the gap. The tool returns Tamil at 78% on 36 rows and English at 97% on 72. The recorded reply names both groups and a gap of 0.194, but not the row counts.
The sample size sits beside every number. With 36 rows, a gap of 19 points is far more than chance, so it is a finding, not noise. If a model judge or grader scores the rows, check it against human labels for each group first, or its own bias shows up as a gap.
- ReviewerThe review board asks whether the agent serves every language group equally. Load the…
- Toolsload_rows: {'rows': 180, 'groups': ['English', 'German', 'Spanish', 'Tamil'], 'first': [{'id'…
Show the result
{ "rows": 180, "groups": [ "English", "German", "Spanish", "Tamil" ], "first": [ { "id": "T-1", "group": "English", "label": "refund", "answer": "replace" }, { "id": "T-2", "group": "English", "label": "replace", "answer": "escalate" }, { "id": "T-3", "group": "English", "label": "escalate", "answer": "escalate" } ] } - Toolsgap_by_group: worst group Tamil, gap 19 points
Show the result
{ "overall": 0.922, "groups": { "English": { "accuracy": 0.972, "n": 72 }, "Spanish": { "accuracy": 0.944, "n": 36 }, "German": { "accuracy": 0.944, "n": 36 }, "Tamil": { "accuracy": 0.778, "n": 36 } }, "worst": "Tamil", "best": "English", "gap": 0.194 } - AnalystNo. The agent is least accurate for Tamil at 77.8% (28 of 36), against 97.2% for English, a gap of 19.4 points. German…
The group gap is named, and the tool gives each sample size.
You do: map every hop and slice by group
Copy the starting code and open work/compliance-ethics/flow.py. hops() leaves out the model provider and the vendors, and gap_by_group() returns only the overall score.
./workshop start compliance-ethics
./workshop check compliance-ethics
./workshop watch compliance-ethics
The checks want all eleven hops with their regions, and personal data outside the home region flagged. Each group reports its accuracy and sample size, and the largest gap is named.
Check your understanding
Answer each question, then read why every option is right or wrong. The wrong options are the mistakes engineers make on the job.
1. The legal team at an online shop asks whether personal data from EU customers leaves the EU. Support tickets pass through a form, a gateway, a queue, an agent, a database and two vendors, and nobody has drawn the path. The team has 3 days to answer. What should it produce first?
- AA list of every hop a ticket takes, with the region and the data class of each.
- BA paragraph that says all data stays in the EU, signed by the head of support.
- CA log alert that fires when a request leaves the EU, after the request has already been sent.
- DA shorter retention period, so less data is held in any region.
Show the answer
Answer: A
- A Correct. The map shows each hop and its region, so a hop that leaves the EU can be seen and flagged.
- B A signed statement is a claim. It does not show where any hop sits, so it cannot be checked.
- C An alert after the request has left is a detective control. The legal question is where data goes, which needs a map.
- D Less retention reduces exposure but does not say whether data leaves the region at all.
2. A policy document at an online shop says personal data stays in the EU. An engineer reads the system and finds the model provider runs in the US, and no one listed it as a hop. Legal wants the policy to be true by Friday, and the audit is next week. What closes the gap?
- AAdd the provider to the map with its region, flag the hop, then move it or accept it.
- BAdd a line to the policy that says the provider is trusted and has signed a contract that covers privacy.
- CMove the policy into the system prompt, so the agent refuses to send data abroad.
- DAsk the provider to send a monthly email that confirms where the data is held for the shop.
Show the answer
Answer: A
- A Correct. A flagged hop makes the gap visible. Accepting it then needs a data processing agreement and a transfer basis, recorded as a decision.
- B A line in a policy changes the document, not the flow. The US hop still holds personal data.
- C The agent does not choose where the provider runs. A prompt line cannot move a hop, and the US hop still holds the data.
- D An email after the fact is detective. The map is where the hop is listed and flagged in the first place.
3. A regulator asks an online shop for evidence that EU personal data does not leave the EU. The team has a 10 page policy and no diagram, and eleven systems touch a ticket. The regulator wants something it can check line by line. What should the team hand over?
- AThe 10 page policy, with the sections about data highlighted and a cover note from the head of legal.
- BA data-flow map with one row per system, giving its region and the class of data it holds.
- CThe model provider's ISO 27001 certificate and its security report.
- DA count of how many tickets were handled in the EU last month.
Show the answer
Answer: B
- A A policy says what should happen. The regulator asks for evidence of what does happen.
- B Correct. One row per system with a region and a data class can be checked line by line, and a gap shows.
- C A certificate says the provider runs a security programme. It does not say which region holds the EU data or list the other hops.
- D A count of tickets says how many were handled, not where each hop ran.
4. An auditor reads the data-flow map of an online shop that has eleven hops in three regions. The map should let her find any hop that moves personal data out of the home region without reading the code. Select two facts the map must list for each hop.
- AThe region where the hop runs, so a hop outside home can be found.
- BThe name of the engineer who wrote the hop.
- CThe class of data the hop holds, such as personal data or metrics.
- DThe number of tickets the hop handled last week.
Show the answer
Answer: A, C
- A Correct. The region says where the data sits, and a region other than home is the thing to find.
- B An author says who to ask, not where data goes.
- C Correct. Metrics may leave a region where personal data may not, so the class decides the flag.
- D Volume is useful for cost, but it does not say whether the hop breaks residency.
5. A support agent at an online shop scores 92% on 180 labelled tickets, and the board wants to say it serves every customer well. The rows cover three languages, the smallest group has 36 rows, and the board meets in a week with no budget for a new labelling round. Which step shows a problem the overall score could hide?
- ARaise the overall target to 95% and run the eval again, so the board sees a higher number.
- BAdd 100 more English rows, so the average is more stable.
- CSlice the eval by group, and report the accuracy and the row count of each.
- DAsk the model whether it treats every language equally.
Show the answer
Answer: C
- A A higher target on the same number still averages the groups together.
- B More rows for the largest group move the average toward it and hide the smallest group further.
- C Correct. The slice shows each group's accuracy beside its row count, so a weak group the 92% averaged away can be seen.
- D The model does not know its own accuracy by group. The eval measures it.
6. A sliced eval of an online shop's agent finds a group with 12 rows at 67% accuracy, against 95% for the largest group. A product manager says 12 rows is too few and the gap is noise, so no action is needed. The report goes to the board on Friday, and labelling more rows takes a week. What is the right response?
- ADrop the group from the report until it has more rows, because a small group is not worth a finding.
- BReport the gap with its sample size of 12, and add rows for that group before concluding.
- CMerge the group into the next largest group, so every slice has at least 30 rows.
- DTreat the gap as proven and retrain the model on that group.
Show the answer
Answer: B
- A Dropping a group hides it, and a group with few rows is the one most likely to be served badly.
- B Correct. The sample size is shown beside the gap, and more rows turn a signal into a finding.
- C Merging hides the small group inside a bigger one, and the gap is averaged away again.
- D 12 rows is a signal, not proof, and a retrain without more data may fix nothing.
7. The vendor of an online shop's support agent says the model is neutral across languages, and the team plans to repeat that to its customers. No eval by group exists, and the 180 labelled rows are on hand. The launch is in 2 weeks. What should the team do before it makes the claim?
- AQuote the vendor's statement and name the vendor as the source.
- BSet a flag in the model settings that turns on equal treatment.
- CAdd a line to the prompt that tells the agent to treat every language alike.
- DBuild a sliced eval on the labelled rows, and publish the accuracy by language.
Show the answer
Answer: D
- A A quoted statement is the vendor's claim. The team's own system still has to be measured.
- B No setting makes a system fair. Fairness is a measured property of the whole system.
- C A prompt line is a request. The eval shows whether the agent follows it for each language.
- D Correct. Neutrality is a claim to test, and the sliced eval on the rows already held tests it.
8. A fairness review at an online shop finds that the agent scores 97% for English and 78% for Tamil. The reviewer must write the finding so the board can act on it and a later reviewer can check it, and the report must fit on one page. Select two things to report with the gap.
- AThe accuracy of each group, so the size of the gap and who it hurts is clear.
- BThe overall score alone, since it summarises everything.
- CThe sample size of each group, so the strength of the evidence is clear.
- DA note that the gap is probably noise, to avoid alarm.
Show the answer
Answer: A, C
- A Correct. The two accuracies show who is served worse and by how much.
- B The overall score is what hid the gap in the first place.
- C Correct. The row count behind each score shows how strong the evidence for the 19 point gap is.
- D Calling it noise without a sample size is a guess, and it is what small-group-is-noise gets wrong.
9. An online shop scores its agent's answers with a model judge, and the fairness report says every language group is within 2 points. Nobody has compared the judge's scores with human labels, and the judge reads English best. The report goes to the board next week. What should the team check first?
- AWhether the judge is a larger model than the agent.
- BWhether the judge prompt is shorter than 200 words and lists the scoring steps in order.
- CWhether the overall score has risen since last month.
- DWhether the judge agrees with human labels.
Show the answer
Answer: D
- A A larger model may still score one language worse. Only labels per group show that.
- B Prompt length does not say whether the judge treats a language differently.
- C A rising overall score can still hide a falling group.
- D Correct. A judge that is stricter or looser in one language skews the gap, so it is checked against labels per group.
10. An automatic grader at an online shop gives Tamil answers 71% and English answers 90% on rows that humans rated about the same. The team wants to use the grader to track fairness each week. It has 40 human-rated rows per language and one week before the first report. What should it do?
- AUse the grader as it is, and note the Tamil gap as a finding about how the agent serves that language.
- BAverage the two languages into one score, so the grader's bias cancels and the board sees one clear number.
- CTest the grader on each group against the human ratings, and fix it before using it to measure the agent.
- DSwitch the grader off and rely on the overall score.
Show the answer
Answer: C
- A The humans rated the answers the same, so the gap is the grader's, not the agent's.
- B Averaging hides the gap, and the grader is still wrong for one language.
- C Correct. The human ratings show the grader is stricter on Tamil, and fixing it first makes the measure fair.
- D The overall score is the number that hid the gap, so it is not a safer fallback.
Play: predict the output
A vendor's row in the system file uses its own label for personal data.
hops(
{
"home": "EU",
"hops": [{"name": "vendor", "data": "PII", "region": "US"}],
}
)
Predict: Is the vendor hop flagged?
- ANo. The check looks for the word personal, so the label PII passes.
- BYes. Personal data leaves the EU for the US.
Show the answer
A. A free-text label lets a hop slip past an exact match. Keep data classes to a fixed list, and refuse a hop whose label is not on it.
References
- Anthropic privacy policy: what the model provider keeps, where and for how long.
- Data residency: where inference runs, as a setting you can choose.
- GDPR Article 44: the rule on transfers of personal data out of the EU.
- AI risk management framework: fairness measured, not assumed.
- Create strong empirical evaluations: slicing a test set so one group is not hidden.
Conclusions
- Draw every hop with its region and data class, including the model provider.
- Flag a hop that carries personal data out of the home region, in code.
- Slice the eval by group, and report the sample size beside each gap.
You can now map a data flow, flag a cross-region hop, and name an accuracy gap between groups.
Data-flow map
Every hop a ticket takes, with its region and the class of data
Data residency
Where personal data is stored and processed
Sliced eval
Accuracy reported per group, not one number for everyone
Sample size
The number of rows behind each group's score