Interprets legal text in regelrecht YAML files and generates machine-readable execution logic with parameters, operations, outputs, and cross-law references. Use when user wants to make a law executable, add machine_readable sections, or interpret legal articles for computational execution.
Installation
Details
Usage
After installing, this skill will be available to your AI coding assistant.
Verify installation:
npx agent-skills-cli listSkill Instructions
name: law-machine-readable-interpreter description: Interprets legal text in regelrecht YAML files and generates machine-readable execution logic with parameters, operations, outputs, and cross-law references. Use when user wants to make a law executable, add machine_readable sections, or interpret legal articles for computational execution. allowed-tools: Read, Edit, Grep, Glob
Law Machine-Readable Interpreter
Analyzes legal text in YAML files and generates complete machine_readable execution logic.
What This Skill Does
- Reads YAML law files from
regulation/nl/ - Analyzes each article's legal text
- Identifies computational elements:
- Input parameters (BSN, dates, amounts)
- Constants and definitions
- Conditions and logic
- Cross-references to other laws/articles
- Output values
- Generates complete
machine_readablesections with:competent_authority- who has binding authorityrequires- dependencies on other laws/regulationsdefinitions- constants and fixed valuesexecutionsection containing:produces- legal character and decision typeparameters- caller-provided inputsinput- data from other sourcesoutput- what this article producesactions- operations and logic
- Converts monetary amounts to eurocent (€ 795,47 → 79547)
- Creates TODO comments for missing external law references
- Uses aggressive AI interpretation (full automation)
Important Principles
- Aggressive interpretation: Generate complete logic even if uncertain
- Eurocent conversion: Convert all monetary amounts (€ X,XX → eurocent)
- Cross-references: Detect references to other laws/articles
- TODOs for missing refs: Add TODO comments when external laws don't exist in repo
- legal_basis: Add traceability to specific law text where applicable
Schema Structure Overview
The schema has NO public or endpoint fields. The machine_readable section structure is:
machine_readable:
competent_authority: # Who has binding authority
name: "Belastingdienst"
type: "INSTANCE" # or "CATEGORY" (default: INSTANCE)
requires: # Dependencies (optional)
- law: "Zorgverzekeringswet"
values: ["is_verzekerd"]
definitions: # Constants (optional)
VERMOGENSGRENS:
value: 15485900
execution:
produces: # Legal character (optional)
legal_character: "BESCHIKKING" # or TOETS, WAARDEBEPALING, BESLUIT_VAN_ALGEMENE_STREKKING
decision_type: "TOEKENNING" # or AFWIJZING, GOEDKEURING, AANSLAG, etc.
parameters: # Caller-provided inputs
- name: "bsn"
type: "string"
required: true
input: # Data from other sources
- name: "toetsingsinkomen"
type: "amount"
source:
regulation: "awir" # Name of the law/regulation
output: "toetsingsinkomen" # Output field to retrieve
parameters:
bsn: "$bsn"
output: # What this produces
- name: "heeft_recht"
type: "boolean"
actions: # Computation logic
- output: "heeft_recht"
operation: "GREATER_THAN_OR_EQUAL"
subject: "$leeftijd"
value: 18
Step-by-Step Instructions
Step 1: Identify Target Law File
When user asks to "interpret" or "make executable" a law:
- Search
regulation/nl/for the law file - If multiple versions exist, ask which date to use
- Read the entire YAML file
Step 2: Analyze Each Article
For each article in the articles array:
-
Read the legal text in the
textfield -
Identify if it's executable:
- Does it define a calculation, condition, or decision?
- Does it provide a concrete output value?
- If YES → Add
machine_readablesection - If NO (just definitions) → Skip or add minimal section
-
Extract key elements:
- Parameters: What inputs are needed? (BSN, dates, amounts, etc.)
- Constants: Fixed values defined in the text
- Conditions: If/when/unless statements
- Calculations: Mathematical operations
- References: Mentions of other articles/laws
- Outputs: What the article calculates/determines
Step 3: Identify Competent Authority
Determine who has binding authority for the decision:
competent_authority:
name: "Belastingdienst/Toeslagen"
type: "INSTANCE" # Specific organization
Or for categories (must be resolved per context):
competent_authority:
name: "gemeente"
type: "CATEGORY" # Abstract category, resolved at runtime
Step 4: Identify and Define Parameters
Look for inputs that must be provided by the caller:
Common parameters:
bsn(string) - Citizen service numberpeildatum(date) - Reference datejaar(number) - Yearbedrag(amount) - Amount
Example from text:
"Een persoon heeft recht op zorgtoeslag indien hij de leeftijd van 18 jaar heeft bereikt"
→ Needs bsn to look up person's age
YAML output:
parameters:
- name: "bsn"
type: "string"
required: true
description: "Burgerservicenummer van de persoon"
Step 5: Extract Constants and Definitions
Look for fixed values mentioned in the text:
Example from text:
"De grens bedraagt € 154.859 voor een alleenstaande"
YAML output:
definitions:
VERMOGENSGRENS_ALLEENSTAANDE:
value: 15485900 # Converted to eurocent!
description: "Vermogensgrens voor alleenstaande personen"
Monetary Conversion Rules:
- € 154.859 → 15485900 (eurocent)
- € 2.112 → 211200 (eurocent)
- € 795,47 → 79547 (eurocent)
- Always use integer eurocent values
Step 6: Identify Cross-Law References (Input Sources)
Look for references to other laws or articles:
Patterns to detect:
- "ingevolge de [Law Name]"
- "bedoeld in artikel X"
- "genoemd in [regulation]"
- Markdown links:
[text](https://wetten.overheid.nl/BWBR...)
Source Structure:
input:
- name: "is_verzekerd"
type: "boolean"
source:
regulation: "zorgverzekeringswet" # Law identifier
output: "is_verzekerd" # Output field name
parameters:
bsn: "$bsn"
description: "Verzekerd ingevolge de Zorgverzekeringswet"
For external data (not from another law):
input:
- name: "geboortedatum"
type: "date"
source:
output: "geboortedatum" # No regulation = external data source
description: "Geboortedatum uit BRP"
If external law not found in repo:
input:
- name: "is_verzekerd"
type: "boolean"
source:
# TODO: Implement zorgverzekeringswet
regulation: "zorgverzekeringswet"
output: "is_verzekerd"
parameters:
bsn: "$bsn"
Step 7: Define Outputs
Identify what the article produces:
Data types available:
string- Text valuesnumber- Numeric valuesboolean- True/falseamount- Monetary values (in eurocent)date- Date valuesobject- Complex structuresarray- Lists
With type specifications:
output:
- name: "zorgtoeslag_bedrag"
type: "amount"
type_spec:
unit: "eurocent"
description: "Het bedrag van de zorgtoeslag"
With temporal metadata:
output:
- name: "toetsingsinkomen"
type: "amount"
temporal:
type: "period"
period_type: "year"
Step 8: Interpret Conditions and Logic (Actions)
Convert legal conditions to operations:
Available Operations:
| Category | Operations |
|---|---|
| Arithmetic | ADD, SUBTRACT, MULTIPLY, DIVIDE, MIN, MAX |
| Comparison | EQUALS, NOT_EQUALS, GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL |
| Logical | AND, OR, NOT |
| Membership | IN, NOT_IN |
| Null check | NOT_NULL |
| Conditional | IF |
| Iteration | FOREACH |
| Date | SUBTRACT_DATE |
| String | CONCAT |
Common Legal Patterns → Operations:
| Legal Text | Operation |
|---|---|
| "heeft bereikt de leeftijd van 18 jaar" | GREATER_THAN_OR_EQUAL, subject: $leeftijd, value: 18 |
| "niet meer bedraagt dan X" | LESS_THAN_OR_EQUAL |
| "ten minste X" | GREATER_THAN_OR_EQUAL |
| "indien ... en ..." | AND with values array |
| "indien ... of ..." | OR with values array |
| "niet ..." | NOT |
| "gelijk aan" | EQUALS |
Simple comparison:
actions:
- output: "is_volwassen"
operation: "GREATER_THAN_OR_EQUAL"
subject: "$leeftijd"
value: 18
Multiple conditions (AND/OR):
actions:
- output: "voldoet_aan_voorwaarden"
operation: "AND"
values:
- operation: "EQUALS"
subject: "$is_verzekerd"
value: true
- operation: "GREATER_THAN_OR_EQUAL"
subject: "$leeftijd"
value: 18
Conditional with if-then-else (using conditions array):
actions:
- output: "toeslag_percentage"
conditions:
- test:
operation: "EQUALS"
subject: "$huishouden_type"
value: "alleenstaand"
then: 100
else: 50
Conditional with IF operation:
actions:
- output: "resultaat"
operation: "IF"
test:
operation: "GREATER_THAN"
subject: "$inkomen"
value: 50000
then: 0
else: "$berekend_bedrag"
Calculation chain:
actions:
- output: "premie_basis"
operation: "MULTIPLY"
values:
- "$standaardpremie"
- "$percentage"
- output: "premie_na_korting"
operation: "SUBTRACT"
values:
- "$premie_basis"
- "$korting"
Date calculation:
actions:
- output: "leeftijd"
operation: "SUBTRACT_DATE"
values:
- "$peildatum"
- "$geboortedatum"
Resolve from ministeriele regeling:
actions:
- output: "standaardpremie"
resolve:
type: "ministeriele_regeling"
output: "standaardpremie"
match:
output: "jaar"
value: "$jaar"
Step 9: Add Legal Basis (Traceability)
For important computations, add legal_basis to trace back to the law:
actions:
- output: "heeft_recht"
operation: "AND"
values:
- "$is_verzekerd"
- "$is_volwassen"
legal_basis:
law: "Wet op de zorgtoeslag"
bwb_id: "BWBR0018451"
article: "2"
paragraph: "1"
url: "https://wetten.overheid.nl/BWBR0018451#Artikel2"
explanation: "Lid 1 bepaalt de voorwaarden voor recht op zorgtoeslag"
Step 10: Set Produces (Legal Character)
If the article produces a formal decision:
execution:
produces:
legal_character: "BESCHIKKING" # Individual decision
decision_type: "TOEKENNING" # Grant/approval
Legal character options:
BESCHIKKING- Individual administrative decisionTOETS- Check/verificationWAARDEBEPALING- Value determinationBESLUIT_VAN_ALGEMENE_STREKKING- General binding decision
Decision type options:
TOEKENNING- GrantAFWIJZING- RejectionGOEDKEURING- ApprovalAANSLAG- Tax assessmentALGEMEEN_VERBINDEND_VOORSCHRIFT- General binding regulationBELEIDSREGEL- Policy ruleVOORBEREIDINGSBESLUIT- Preparatory decisionANDERE_HANDELING- Other action
Step 11: Complete Example
Legal text:
Artikel 2
1. Een persoon heeft recht op zorgtoeslag indien hij:
a. de leeftijd van 18 jaar heeft bereikt;
b. verzekerd is ingevolge de Zorgverzekeringswet.
Complete machine_readable section:
machine_readable:
competent_authority:
name: "Belastingdienst/Toeslagen"
requires:
- law: "Zorgverzekeringswet"
values: ["is_verzekerd"]
execution:
produces:
legal_character: "BESCHIKKING"
decision_type: "TOEKENNING"
parameters:
- name: "bsn"
type: "string"
required: true
description: "Burgerservicenummer"
- name: "peildatum"
type: "date"
required: true
description: "Datum waarop het recht wordt getoetst"
input:
- name: "geboortedatum"
type: "date"
source:
output: "geboortedatum"
description: "Geboortedatum uit BRP"
- name: "is_verzekerd"
type: "boolean"
source:
# TODO: Implement zorgverzekeringswet
regulation: "zorgverzekeringswet"
output: "is_verzekerd"
parameters:
bsn: "$bsn"
output:
- name: "leeftijd"
type: "number"
type_spec:
unit: "years"
- name: "heeft_recht"
type: "boolean"
description: "Geeft aan of de persoon recht heeft op zorgtoeslag"
actions:
- output: "leeftijd"
operation: "SUBTRACT_DATE"
values:
- "$peildatum"
- "$geboortedatum"
legal_basis:
article: "2"
paragraph: "1"
explanation: "Leeftijd bepaald op peildatum"
- output: "heeft_recht"
operation: "AND"
values:
- operation: "GREATER_THAN_OR_EQUAL"
subject: "$leeftijd"
value: 18
- operation: "EQUALS"
subject: "$is_verzekerd"
value: true
legal_basis:
article: "2"
paragraph: "1"
explanation: "Voorwaarden a en b van lid 1"
Step 12: Apply Changes to YAML
For each article that needs a machine_readable section:
- Use the Edit tool to add the section after the
urlfield - Maintain proper YAML indentation (2 spaces per level)
- Add comments for TODOs and clarifications
- Convert all monetary amounts to eurocent
Step 13: Validate Against Schema and Lint
Before reporting, validate the updated YAML:
Step 13a: Run validation (linting + schema)
just validate {LAW_FILE_PATH}
This checks for:
- Line length (max 125 chars - wrap long text!)
- Proper indentation
- Quote usage
- YAML formatting
- JSON schema compliance
Step 13b: Run schema validation only
just validate {LAW_FILE_PATH}
This validates against the JSON schema (serde + JSON Schema Draft-07).
If validation fails:
- Review schema errors carefully
- Common issues with machine_readable sections:
- Missing required
outputfield in source - Wrong operation types (check enum values)
- Missing required fields in parameters/input/output
- Incorrect nesting or indentation
- Missing required
- Fix errors and re-validate
- Continue until both lint and validation pass
Step 14: Reverse Validation (Hallucination Check)
After schema validation passes, verify that every element in the machine_readable section can be traced back to the original legal text.
For each element, check:
-
Definitions/Constants:
- Is this value explicitly mentioned in the article text?
- If NOT → Remove it from the YAML
- If needed for logic but not in text → Add to "Assumptions" in report
-
Input fields:
- Is this data source referenced in the article text?
- Look for phrases like "ingevolge", "bedoeld in", "genoemd in"
- If NOT traceable → Remove or mark as assumption
-
Output fields:
- Does the article actually produce this output?
- Is it stated or clearly implied in the legal text?
- If NOT → Remove it
-
Actions/Operations:
- Does the legal text contain the logic for this operation?
- Can you point to specific sentences that justify this action?
- If NOT → Remove or simplify
-
Conditions:
- Are these conditions explicitly stated in the article?
- Watch for invented edge cases not in the law
- If NOT → Remove
Decision matrix:
| Traceable in text? | Needed for logic? | Action |
|---|---|---|
| YES | YES | Keep |
| YES | NO | Keep (may be informational) |
| NO | YES | Report as assumption |
| NO | NO | Remove |
Example check:
# Article text: "Een persoon heeft recht indien hij 18 jaar is"
# GOOD - traceable:
- output: "heeft_recht" # ✓ "heeft recht" in text
operation: "GREATER_THAN_OR_EQUAL"
subject: "$leeftijd"
value: 18 # ✓ "18 jaar" in text
# BAD - not traceable (hallucinated):
- output: "woont_in_nederland" # ✗ Not mentioned in article
operation: "EQUALS"
subject: "$woonland"
value: "NL"
# → REMOVE THIS
After reverse validation:
- Remove all non-traceable elements that aren't needed
- Add "Assumptions" section to report for elements that are:
- Not explicitly in text
- But required to make the logic complete
- These need user review
Step 15: Report Results
After successful validation:
-
Count processed articles:
- How many articles total?
- How many now have machine_readable sections?
-
List TODOs:
- Which external laws need to be downloaded?
- Any ambiguous interpretations?
-
List Assumptions (from reverse validation):
- Elements not explicitly in text but needed for logic
- These require user verification
-
Report to user:
Interpreted {LAW_NAME}
Articles processed: {TOTAL}
Made executable: {EXECUTABLE_COUNT}
Schema validation: PASSED
Reverse validation: PASSED
Assumptions (need review):
- Article 2: Added "peildatum" parameter (implied but not stated)
- Article 3: Assumed "inkomen" refers to toetsingsinkomen
TODOs remaining:
- Download and interpret: {external_law_1}
- Clarify calculation in article {X}
The law is now executable via the engine!
Common Patterns
Pattern 1: Age Check
input:
- name: "geboortedatum"
type: "date"
source:
output: "geboortedatum"
description: "Geboortedatum uit BRP"
actions:
- output: "leeftijd"
operation: "SUBTRACT_DATE"
values:
- "$peildatum"
- "$geboortedatum"
- output: "is_volwassen"
operation: "GREATER_THAN_OR_EQUAL"
subject: "$leeftijd"
value: 18
Pattern 2: Income Threshold
definitions:
INKOMENSGRENS:
value: 7954700 # € 79.547 in eurocent
input:
- name: "toetsingsinkomen"
type: "amount"
source:
regulation: "awir"
output: "toetsingsinkomen"
parameters:
bsn: "$bsn"
jaar: "$jaar"
actions:
- output: "onder_inkomensgrens"
operation: "LESS_THAN_OR_EQUAL"
subject: "$toetsingsinkomen"
value: "$INKOMENSGRENS"
Pattern 3: Multiple Conditions (AND)
actions:
- output: "voldoet_aan_voorwaarden"
operation: "AND"
values:
- operation: "EQUALS"
subject: "$is_verzekerd"
value: true
- operation: "GREATER_THAN_OR_EQUAL"
subject: "$leeftijd"
value: 18
- operation: "EQUALS"
subject: "$woont_in_nederland"
value: true
Pattern 4: Calculation Chain
actions:
- output: "premie_basis"
operation: "MULTIPLY"
values:
- "$standaardpremie"
- "$percentage"
- output: "premie_na_korting"
operation: "SUBTRACT"
values:
- "$premie_basis"
- "$korting"
- output: "premie_finaal"
operation: "MAX"
values:
- 0
- "$premie_na_korting"
Pattern 5: Conditional Value
actions:
- output: "vermogensgrens"
conditions:
- test:
operation: "EQUALS"
subject: "$heeft_partner"
value: true
then: "$VERMOGENSGRENS_PARTNERS"
else: "$VERMOGENSGRENS_ALLEENSTAANDE"
Pattern 6: Lookup from Ministeriele Regeling
actions:
- output: "standaardpremie"
resolve:
type: "ministeriele_regeling"
output: "standaardpremie"
match:
output: "jaar"
value: "$jaar"
Tips for Success
- Be aggressive: Generate complete logic even if uncertain
- Use descriptive names:
toetsingsinkomennotincome - Always eurocent: Never use decimal euro amounts
- Check for existing laws: Use Glob to search
regulation/nl/ - Break down complex logic: Multiple simple actions > one complex action
- Add descriptions: Help future readers understand the logic
- Mark TODOs clearly: Use
# TODO:comments for missing refs - Validate types: Ensure type consistency (boolean, number, string, date, amount)
- Document assumptions: Add comments when interpretation is unclear
- Add legal_basis: Trace important computations back to the law text
Error Handling
If legal text is ambiguous:
- Make best guess with TODO comment
- Explain uncertainty to user
- Suggest manual review
If external law not found:
- Create TODO placeholder in source
- Add to list of missing dependencies
- Continue with other articles
If operation unclear:
- Use simpler operations
- Break into multiple steps
- Add explanatory comments
More by MinBZK
View allDownloads Dutch official legal publications including national laws (wetten, ministeriele regelingen, koninklijk besluiten), local regulations (lokale verordeningen, gemeentelijk beleid), and implementation policies (uitvoeringsbeleid) from government databases (BWB, CVDR) and converts them to YAML format with textual content only. Use when user wants to download, fetch, or import any Dutch regulation by name or type.
Performs critical code reviews using REVIEW.md guidelines. Evaluates code quality, architecture, testing, and domain-specific concerns (legal faithfulness, cross-law references, engine safety). Use after completing significant code changes or before merging.
name: figma-navigator
Gebruik deze skill wanneer de gebruiker vraagt over Digikoppeling, koppelvlakstandaarden, ebMS2, WUS, WSDL, SOAP, REST-API koppelvlak, grote berichten, OIN, Organisatie Identificatie Nummer, PKIoverheid, beveiligingsstandaarden overheid, routering en adressering, CPA, berichtuitwisseling tussen overheidsorganisaties.
