The Problem
In Lesson 1, you conducted an algorithmic impact assessment and produced an internal score — High, Moderate, Low. That score tells your organization how much internal governance to apply. It does not tell you what the law requires. The EU AI Act has its own classification system, with its own four tiers and its own legally binding obligations attached to each one, and getting the tier wrong is not a paperwork error — it's the difference between "voluntary code of conduct" and "up to €15M or 3% of global revenue in fines."
The challenge engineers run into is that the Act's tiers are not intuitive from a technical description alone. A resume-screening tool sounds like a recommendation engine; legally, it's explicitly listed as high-risk in Annex III because it affects access to employment. A chatbot sounds high-stakes because it talks to customers directly; legally, it's limited-risk, with a single transparency obligation (tell the user they're talking to AI). You cannot guess your way through this — you need a repeatable classification process that maps a system's actual use case to the Act's actual categories.
The 4 risk tiers
| Tier | Examples | Obligations | Penalty for Non-Compliance |
|---|
| Unacceptable (banned) | Social scoring, manipulative AI, real-time biometric ID in public spaces | System is prohibited | Up to €35M or 7% of global revenue |
| High-risk (Annex III) | Employment screening, credit scoring, medical diagnosis, education, law enforcement, critical infrastructure | Risk assessment, data governance, transparency, human oversight, logging, conformity assessment | Up to €15M or 3% of global revenue |
| Limited-risk | Chatbots, emotion recognition, deepfakes, biometric categorization | Transparency obligations (users must know they're interacting with AI) | Up to €7.5M or 1.5% of global revenue |
| Minimal-risk | Spam filters, recommendation engines, inventory optimization | No specific obligations (voluntary codes of conduct) | N/A |
Annex III high-risk categories
The EU AI Act explicitly lists high-risk use cases in Annex III:
- Biometrics — Remote biometric identification, biometric categorization
- Critical infrastructure — Safety components of transport, water, gas, electricity
- Education and vocational training — Admissions, evaluations, student placement
- Employment and worker management — Recruitment, screening, promotion, termination
- Essential services — Creditworthiness, credit scoring, insurance pricing
- Law enforcement — Risk assessment, evidence reliability, offender profiling
- Migration and border control — Visa eligibility, asylum assessment
- Justice and democratic processes — Legal research, case interpretation, election influence
Building the risk classifier
"""
eu_ai_act_classifier.py
Classifies AI systems into EU AI Act risk tiers and identifies obligations.
"""
import json
from datetime import datetime
ANNEX_III_CATEGORIES = {
"biometrics": {
"name": "Biometrics",
"examples": ["Remote biometric identification", "Biometric categorization systems"],
"articles": "Art. 6, Annex III(1)",
},
"critical_infrastructure": {
"name": "Critical Infrastructure",
"examples": ["Safety components for transport", "Water/gas/electricity systems"],
"articles": "Art. 6, Annex III(2)",
},
"education": {
"name": "Education and Vocational Training",
"examples": ["Admissions systems", "Automated grading", "Student placement"],
"articles": "Art. 6, Annex III(3)",
},
"employment": {
"name": "Employment and Worker Management",
"examples": ["Resume screening", "Candidate ranking", "Performance evaluation"],
"articles": "Art. 6, Annex III(4)",
},
"essential_services": {
"name": "Essential Services (Credit and Insurance)",
"examples": ["Credit scoring", "Loan approval", "Insurance pricing"],
"articles": "Art. 6, Annex III(5)",
},
"law_enforcement": {
"name": "Law Enforcement",
"examples": ["Risk assessment tools", "Evidence evaluation", "Offender profiling"],
"articles": "Art. 6, Annex III(6)",
},
"migration": {
"name": "Migration and Border Control",
"examples": ["Visa eligibility assessment", "Asylum application evaluation"],
"articles": "Art. 6, Annex III(7)",
},
"justice": {
"name": "Justice and Democratic Processes",
"examples": ["Legal research tools", "Case law interpretation", "Election influence detection"],
"articles": "Art. 6, Annex III(8)",
},
}
UNACCEPTABLE_PRACTICES = [
"Social scoring by public authorities",
"Real-time remote biometric identification in public spaces (with exceptions)",
"AI that manipulates human behavior to circumvent free will",
"AI that exploits vulnerabilities of specific groups (age, disability, socio-economic status)",
"Untargeted facial image scraping",
"Emotion recognition in workplaces and schools",
"Social scoring by private entities for similar purposes",
]
LIMITED_RISK_USES = [
"Chatbots and conversational AI (users must be informed)",
"Emotion recognition systems (users must be informed)",
"Biometric categorization systems (users must be informed)",
"Deep fakes and AI-generated content (must be labeled as synthetic)",
]
HIGH_RISK_OBLIGATIONS = [
{"article": "Art. 9", "requirement": "Risk management system throughout lifecycle"},
{"article": "Art. 10", "requirement": "Data governance — representative, high-quality training data"},
{"article": "Art. 11", "requirement": "Technical documentation (Annex IV)"},
{"article": "Art. 12", "requirement": "Record-keeping (automatic logs)"},
{"article": "Art. 13", "requirement": "Transparency and explainability for users"},
{"article": "Art. 14", "requirement": "Human oversight"},
{"article": "Art. 15", "requirement": "Accuracy, robustness, and cybersecurity"},
{"article": "Art. 16", "requirement": "Provider obligations (quality management, post-market monitoring)"},
{"article": "Art. 26", "requirement": "Deployer obligations (fundamental rights impact assessment for public bodies)"},
{"article": "Art. 27", "requirement": "FRIA for public sector deployers"},
]
def classify_system(system_name, system_description, use_case_keywords):
"""
Classify an AI system into EU AI Act risk tier.
Args:
system_name: Name of the system
system_description: Description of what the system does
use_case_keywords: List of keywords describing the use case
Returns:
Dict with classification results and obligations
"""
description_lower = system_description.lower()
keywords_lower = [k.lower() for k in use_case_keywords]
# Check for unacceptable practices
matched_unacceptable = []
for practice in UNACCEPTABLE_PRACTICES:
practice_lower = practice.lower()
if any(word in practice_lower for word in keywords_lower) and \
any(word in description_lower for word in practice_lower.split()[:3]):
matched_unacceptable.append(practice)
if matched_unacceptable:
return {
"system_name": system_name,
"risk_tier": "Unacceptable",
"classification": "PROHIBITED",
"matched_practices": matched_unacceptable,
"obligations": ["System must not be deployed in the EU"],
"penalty": "Up to €35M or 7% of global annual revenue",
"classification_date": datetime.now().isoformat(),
}
# Check for high-risk (Annex III)
matched_categories = []
for cat_id, cat_data in ANNEX_III_CATEGORIES.items():
for example in cat_data["examples"]:
example_lower = example.lower()
if any(word in keywords_lower for word in example_lower.split()):
matched_categories.append({
"category": cat_data["name"],
"matched_example": example,
"articles": cat_data["articles"],
})
break
if matched_categories:
return {
"system_name": system_name,
"risk_tier": "High-risk",
"classification": "REQUIRES FULL COMPLIANCE",
"matched_categories": matched_categories,
"obligations": HIGH_RISK_OBLIGATIONS,
"penalty": "Up to €15M or 3% of global annual revenue",
"classification_date": datetime.now().isoformat(),
}
# Check for limited risk
matched_limited = []
for use in LIMITED_RISK_USES:
use_lower = use.lower()
if any(word in keywords_lower for word in use_lower.split()):
matched_limited.append(use)
if matched_limited:
return {
"system_name": system_name,
"risk_tier": "Limited-risk",
"classification": "TRANSPARENCY OBLIGATIONS",
"matched_uses": matched_limited,
"obligations": [
{"article": "Art. 50", "requirement": "Inform users they are interacting with AI"},
{"article": "Art. 50(2)", "requirement": "Label AI-generated content as synthetic"},
],
"penalty": "Up to €7.5M or 1.5% of global annual revenue",
"classification_date": datetime.now().isoformat(),
}
# Default: minimal risk
return {
"system_name": system_name,
"risk_tier": "Minimal-risk",
"classification": "NO SPECIFIC OBLIGATIONS",
"obligations": [],
"recommendation": "Voluntary code of conduct recommended (Art. 95)",
"penalty": "N/A",
"classification_date": datetime.now().isoformat(),
}
def generate_classification_report(result):
"""Generate a Markdown classification report."""
lines = []
lines.append(f"# EU AI Act Risk Classification — {result['system_name']}\n")
lines.append(f"**Risk Tier:** {result['risk_tier']}")
lines.append(f"**Classification:** {result['classification']}")
lines.append(f"**Date:** {result['classification_date']}")
lines.append(f"**Penalty for non-compliance:** {result['penalty']}\n")
if result.get("matched_categories"):
lines.append("## Matched Annex III Categories\n")
for cat in result["matched_categories"]:
lines.append(f"- **{cat['category']}** ({cat['articles']}): {cat['matched_example']}")
lines.append("")
if result.get("matched_practices"):
lines.append("## Matched Unacceptable Practices\n")
for practice in result["matched_practices"]:
lines.append(f"- {practice}")
lines.append("")
if result.get("obligations"):
lines.append("## Compliance Obligations\n")
if isinstance(result["obligations"], list):
for ob in result["obligations"]:
if isinstance(ob, dict):
lines.append(f"- **{ob['article']}**: {ob['requirement']}")
else:
lines.append(f"- {ob}")
lines.append("")
lines.append("## Framework Mapping\n")
lines.append("| Framework | Reference | Status |")
lines.append("|---|---|---|")
lines.append(f"| EU AI Act | Risk classification | {result['risk_tier']} |")
lines.append("| NIST AI RMF | MAP 1.5 — Categorize system | ✅ |")
lines.append("| ISO 42001 | Clause 6.1.2 — Risk identification | ✅ |")
return "\n".join(lines)
if __name__ == "__main__":
# Example: Classify a loan approval system
result = classify_system(
system_name="LoanApproval-GBM-v1",
system_description="Automated loan approval system that evaluates consumer credit applications using financial data",
use_case_keywords=["credit scoring", "loan approval", "creditworthiness"],
)
report = generate_classification_report(result)
with open("eu_ai_act_classification.md", "w") as f:
f.write(report)
with open("eu_ai_act_classification.json", "w") as f:
json.dump(result, f, indent=2)
print(f"Risk tier: {result['risk_tier']}")
print(f"Classification: {result['classification']}")
print(f"Obligations: {len(result.get('obligations', []))}")
print("\nReport saved to eu_ai_act_classification.md")
A hospital wants to deploy an AI tool that recommends which patients get scheduled for follow-up appointments sooner based on symptom severity. It's used internally by scheduling staff, who can override any recommendation. Using the classifier's logic, which risk tier does this fall into, and why?
The key mistake to avoid is assuming "humans can override it" downgrades the risk tier — the classifier's own Annex III matching doesn't relax high-risk categories just because a human is in the loop; human oversight is one of the obligations a high-risk system must satisfy (Art. 14), not a reason to avoid the high-risk label in the first place. A system that influences medical scheduling touches health and safety, which is squarely in the territory Annex III was written to cover, alongside employment, credit, and law enforcement. Getting this wrong in the other direction — assuming "just scheduling" means minimal-risk — is exactly the kind of classification error that creates real legal exposure, because the obligations (risk management, human oversight, logging, conformity assessment) never get built if the system was never flagged as high-risk to begin with.