> For the complete documentation index, see [llms.txt](https://experience-digital-transform.gitbook.io/experience-digital-transformation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://experience-digital-transform.gitbook.io/experience-digital-transformation/gif/module-4-architecture-and-technical-standards/4.4-generate-the-semantic-map.md).

# 4.4 Generate the semantic map

Generate a semantic map so two agencies mean the same 'learner' before they exchange one — the hardest layer, made tractable.

{% embed url="<https://youtu.be/sTFEXDY45NQ>" %}
The semantic map: making two agencies mean the same thing before they exchange data (\~5 min)
{% endembed %}

**Watch first (\~5 min).** Then come back for the play.

> **Single message.** Generate a semantic map so two agencies mean the same 'learner' before they exchange one — the hardest layer, made tractable.

## The concept

Of the four interoperability layers, the semantic one — meaning — is the hardest, and the one most projects skip, because it is slow, unglamorous and a little political. It is also where exchanges silently fail: a working wire that carries data the receiver misreads is still a failure, and a worse one, because it looks like success. The good news for the architect is that meaning can be made tractable by building a semantic map — and you can generate a first draft of one with Claude.

A semantic map, for a single exchange, sets out five things. The entities involved — a learner, a school. Their fields — name, date of birth, enrolment status. The code lists — the allowed values for, say, enrolment status, because one agency's 'active' may be another's 'enrolled'. The identifier — which key reliably links the same learner across two agencies. And the mapping itself — each agency's own terms reconciled to one shared definition, so that the examination authority's 'learner' and the registry's 'learner' are confirmed to mean the same person, identified the same way.

You do not invent these definitions from scratch. For education, much of the meaning is already published. OneRoster gives you rostering and enrolment data. CEDS gives you a common vocabulary of education data elements. ISO/IEC 11179 gives you the discipline of describing each data element precisely, and W3C Verifiable Credentials covers the credential case. The semantic map's job is to adopt these published vocabularies and map your agencies' actual fields onto them — not to start from a blank page.

This is the layer where business and IT must meet, and the semantic map is their shared language. Deciding that 'enrolment' means the same thing to the examination authority and to the learner registry is not a technical choice — it is a decision the business data owners make. But it has to be written down precisely enough for the systems to use. The semantic map is exactly that shared object: it lets the people who own the data and the architects who move it agree, once, what the data means — and then every exchange that touches a learner reuses that one agreement instead of re-arguing it.

The AI prompt for this video does the drafting. Give Claude the published vocabulary and the two agencies' field lists, and it drafts the mapping — which field maps to which, where the code lists differ and need translating, which identifier to use as the link. That is the fast ninety per cent. The essential ten per cent is yours: every identifier and every code value is a \[confirm] until you check it against the real registries. An invented mapping reads convincingly and is wrong — and in the semantic layer, wrong means a learner's records silently merged with someone else's. Generate fast; confirm against the registries carefully.

## Your turn — Generate a semantic map for an exchange

{% hint style="success" %}
**✍️ Drafting play · produces B23 Semantic map**

**Bring:** two agencies' field lists for a shared entity, and the published vocabulary to align to. From **B5, B22** (see [Your framework workbook](/experience-digital-transformation/gif/your-framework-workbook.md)). **Get:** a semantic map with \[confirm] placeholders for identifiers and code values. As text in the chat, not a file or a chart. **Time:** \~25 min · **Assistant:** any; the plays are tool-neutral. **With the kit:** no skill in this release, so the prompt runs bare in any assistant. **Watch for:** Identifier and code-list errors in a semantic map are the most dangerous defects in the whole framework — a wrong identifier silently merges two citizens' records.
{% endhint %}

✍️ **Drafting play.** You give a few facts; the play produces a first draft of a document you will edit.

**What it does.** An architect needs a semantic map for one exchange — the entities, fields, code lists, identifier and the mapping onto published vocabularies — drafted from the two agencies' field lists. This is the semantic-map play.

{% tabs %}
{% tab title="Prompt" %}
Copy the prompt, replace the bracketed parts with your own context, and run it in the AI assistant of your choice. Never paste personal data or unpublished documents — see [How to use the plays](https://experience-digital-transform.gitbook.io/experience-digital-transformation/government-enterprise-architecture-gea/developing-a-gov-enterprise-architecture-gea/start-here/how-to-use-the-plays).

```
Below are two agencies that need to exchange data on [country X]'s bus, with each one's field list for the shared entity [paste: the entity, e.g. a learner; agency A's fields and code lists; agency B's fields and code lists; and the published vocabulary to align to, e.g. OneRoster / CEDS]. Produce a semantic map for this exchange: (1) the shared entity and its fields, aligned to the published vocabulary; (2) for each field, the mapping from agency A's term and agency B's term to the shared definition; (3) code-list reconciliation — where A's allowed values differ from B's, the translation; (4) the identifier to use to link the same record across both agencies, and the risk if it is not unique. CRITICAL: output every identifier choice and every code-list value as [confirm: check against the live registry], because you do not have the real registries and an invented mapping can merge two people's records. Output: the semantic map plus a list of every [confirm] to resolve.
```

[Open in Claude](https://claude.ai/new?q=Below%20are%20two%20agencies%20that%20need%20to%20exchange%20data%20on%20%5Bcountry%20X%5D%27s%20bus%2C%20with%20each%20one%27s%20field%20list%20for%20the%20shared%20entity%20%5Bpaste%3A%20the%20entity%2C%20e.g.%20a%20learner%3B%20agency%20A%27s%20fields%20and%20code%20lists%3B%20agency%20B%27s%20fields%20and%20code%20lists%3B%20and%20the%20published%20vocabulary%20to%20align%20to%2C%20e.g.%20OneRoster%20%2F%20CEDS%5D.%20Produce%20a%20semantic%20map%20for%20this%20exchange%3A%20%281%29%20the%20shared%20entity%20and%20its%20fields%2C%20aligned%20to%20the%20published%20vocabulary%3B%20%282%29%20for%20each%20field%2C%20the%20mapping%20from%20agency%20A%27s%20term%20and%20agency%20B%27s%20term%20to%20the%20shared%20definition%3B%20%283%29%20code-list%20reconciliation%20%E2%80%94%20where%20A%27s%20allowed%20values%20differ%20from%20B%27s%2C%20the%20translation%3B%20%284%29%20the%20identifier%20to%20use%20to%20link%20the%20same%20record%20across%20both%20agencies%2C%20and%20the%20risk%20if%20it%20is%20not%20unique.%20CRITICAL%3A%20output%20every%20identifier%20choice%20and%20every%20code-list%20value%20as%20%5Bconfirm%3A%20check%20against%20the%20live%20registry%5D%2C%20because%20you%20do%20not%20have%20the%20real%20registries%20and%20an%20invented%20mapping%20can%20merge%20two%20people%27s%20records.%20Output%3A%20the%20semantic%20map%20plus%20a%20list%20of%20every%20%5Bconfirm%5D%20to%20resolve.) *(experimental deep link: pre-fills the prompt in a new claude.ai chat; check the bracketed parts before sending)*

*Input, output and the kit skill are in the box above.*
{% endtab %}

{% tab title="Example input" %}
{% hint style="warning" %}
**Draft worked example, 2026-10-04.** A bare run on Progressa, annotated, but not yet checked against the kit's expected output. Read it with the annotations, not on its own.
{% endhint %}

The bracketed context in the prompt was replaced with the following:

The exchange, from the Use-Case Catalogue (B5), the first two rows (PNIA → PNEA: identity; PLR → PNEA: enrolment): PNEA pre-fills a certificate application from two registries. The shared entity is the **learner**: a person (PNIA) with an enrolment (PLR).

**Agency A, PNIA person register:** NIN (11 digits), FIRST\_NAME, SURNAME, DOB, SEX (F, M), REGION. It also holds mother's name, birth registration number and address.

**Agency B, PLR enrolment register:** nin, school (the school's name), level (e.g. "Senior Secondary"), enrolment\_year, status (active, transferred, completed).

**Vocabularies to align to**, from the standards portfolio (B22): CEDS for the person, OneRoster for the enrolment, ISCED 2011 for levels. GovStack's identity specification uses OpenID Connect claim names.
{% endtab %}

{% tab title="Example output" %}
{% hint style="warning" %}
**Draft: model output, unverified.** Read it with the annotations in the next tab, not on its own.
{% endhint %}

{% hint style="info" %}
**In the build pack.** The Progressa version of this artefact is a real file, not a pasted draft: `configs/semantic/semantic-map.yaml` — see [What the build pack is](/experience-digital-transformation/gif/the-build-pack.md).
{% endhint %}

```yaml
person:                # anchor: CEDS
  key: nin             # [confirm: unique, and held for every certificate applicant]
  fields:
    nin:           PNIA NIN        # CEDS Person Identifier
    given_name:    PNIA FIRST_NAME # CEDS First Name;     OIDC given_name
    family_name:   PNIA SURNAME    # CEDS Last or Surname; OIDC family_name
    date_of_birth: PNIA DOB        # CEDS Birthdate;      OIDC birthdate
    sex:           PNIA SEX        # CEDS Sex;            OIDC gender
    region:        PNIA REGION     # OIDC address.region [confirm: code list]
enrolment:             # anchor: OneRoster
  key: nin
  fields:
    nin:            PLR nin
    school:         PLR school     # OneRoster org [confirm: name or code?]
    level:          PLR level      # ISCED 2011 level [confirm]
    enrolment_year: PLR enrolment_year
    status:         PLR status     # [confirm: see code list]
```

| Code list        | PLR / PNIA value       | Shared value                       |
| ---------------- | ---------------------- | ---------------------------------- |
| Enrolment status | active                 | active \[confirm]                  |
| Enrolment status | transferred, completed | active with an end date \[confirm] |
| Sex              | F, M                   | female, male (OIDC) \[confirm]     |

**To confirm against the live registries**

* That every certificate applicant holds a NIN, and that no NIN is shared.
* The region code list, which PNIA and PLR may spell differently.
* Whether `school` can become a school code instead of a name.
* The status and sex translations above.
  {% endtab %}

{% tab title="Reading the output" %}
This is the teaching part of the play. Work through the output the way a chief architect would — what is earned, what is invented, what is missing.

<details>

<summary>1. The shape matches the build pack</summary>

The two entities, the CEDS and OneRoster anchors, the NIN key and the three OpenID Connect renames are all in the pack's `configs/semantic/semantic-map.yaml`. Mother's name, birth registration number and address are left out of the map, as the pack leaves them out. The draft did the fast part well.

</details>

<details>

<summary>2. "Unique" is not the risk; coverage is</summary>

The run treats the NIN's uniqueness as the open question. The bigger one is in A0 §3: PNIA issues child IDs only at 16. This exchange concerns senior-secondary candidates aged 16 and over, so it works. The same map applied to a primary-school learner has no key at all. Write that limit into the map before the next exchange reuses it.

</details>

<details>

<summary>3. School is a name, not an identifier</summary>

PLR returns the school's name as free text. Two schools with the same name, or one name spelt two ways, will not reconcile. The status translation is also a guess: OneRoster has no "transferred". Both need the data owners, not the architect, to decide.

</details>

{% hint style="danger" %}
**Safeguard for this play.** Identifier and code-list errors in a semantic map are the most dangerous defects in the whole framework — a wrong identifier silently merges two citizens' records. Confirm every \[confirm] against the live registries with the data owners before any exchange uses the map; do not deploy a semantic map on the strength of the AI's mapping alone.
{% endhint %}
{% endtab %}

{% tab title="What next" %}
The map feeds the contract in [4.5](/experience-digital-transformation/gif/module-4-architecture-and-technical-standards/4.5-generate-a-service-contract.md), which takes its field names and types, and the school-data pipeline in [4.6](/experience-digital-transformation/gif/module-4-architecture-and-technical-standards/4.6-put-a-real-data-source-on-the-bus-the-giga-case.md), which can give `school` a real code. It is also the reference for portability in [5.10](/experience-digital-transformation/gif/module-5-implementation-and-onboarding/5.10-carry-the-framework-to-the-next-sector.md). In your framework workbook this is artefact **B23**.

**This artefact feeds:** [4.5 Generate an OpenAPI service contract](/experience-digital-transformation/gif/module-4-architecture-and-technical-standards/4.5-generate-a-service-contract.md), [4.6 Map a real sector data source through bronze/silver/gold onto the bus](/experience-digital-transformation/gif/module-4-architecture-and-technical-standards/4.6-put-a-real-data-source-on-the-bus-the-giga-case.md), [5.10 Map your framework's sector-portable vs sector-specific parts for a new sector](/experience-digital-transformation/gif/module-5-implementation-and-onboarding/5.10-carry-the-framework-to-the-next-sector.md)

See the full chain in [Your framework workbook](/experience-digital-transformation/gif/your-framework-workbook.md).
{% endtab %}
{% endtabs %}

## Sources

* ISO/IEC 11179 — <https://www.iso.org/standard/78914.html>
* JSON-LD — <https://json-ld.org>
* W3C Verifiable Credentials — <https://www.w3.org/TR/vc-data-model/>
* OneRoster (1EdTech) — <https://www.1edtech.org/standards/oneroster>
* CEDS — <https://ceds.ed.gov>
* EU EIF semantic layer — <https://interoperable-europe.ec.europa.eu/collection/nifo-national-interoperability-framework-observatory/european-interoperability-framework-detail>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://experience-digital-transform.gitbook.io/experience-digital-transformation/gif/module-4-architecture-and-technical-standards/4.4-generate-the-semantic-map.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
