The AI System Register in a Real Control Tower Org
How we keep a live AI inventory across 200+ AWS accounts — and the SCPs, Config rules, and EventBridge automations that keep it honest.
Every framework we answer to wants an inventory. ISO/IEC 42001 expects us to know what AI systems we operate; the EU AI Act’s deployer obligations are unworkable without one; our own board asks a simpler question — how many AI systems do we run, and who owns each one? — and expects the answer in under a day. The AI system register is the artifact that answers all of them, and this note is about what it takes to keep one truthful in a real AWS estate.
Our context: a Control Tower landing zone, a little over 200 accounts, organised the standard way — a Security OU holding the log-archive and audit accounts, a Sandbox OU for experiments, and Workloads OUs split into prod and non-prod. Bedrock and SageMaker usage is spread across maybe thirty of those accounts. The register itself is boring on purpose: a table, one row per AI system, fronted by a form. The interesting part is everything around it — because a register nobody enforces is a wish list, and we learned that the expensive way.
Who writes what. The application team drafts the entry — they are the only people who actually know what the system does, which models it calls, and what data flows through it. The governance team validates it: checks the legal classification against the intake questionnaire, confirms the guardrail reference points at a real, current configuration, and rejects entries that say 'various' in the model-dependencies field. The architecture review board gates on it: no AI item gets an ARB approval without a validated register entry, which is the single strongest incentive we have found for teams to fill the form in properly. Ownership of the row never transfers — the app team keeps it, because the app team is who drifts.
Each validated entry gets an identifier — AIR-0142 style — and that identifier becomes a resource tag in AWS. That one decision does most of the enforcement work below: the tag is the join key between the governance database and the actual cloud estate.
| Field | Who fills it | Why an auditor cares |
|---|---|---|
Register ID (AIR-nnnn) | Assigned by governance on validation | It is the join key: this ID appears as a resource tag on every AWS resource the system uses, so the auditor can walk from paper to infrastructure and back. |
Business owner | App team; a named person, never a mailbox | Accountability. When the system misbehaves, frameworks and regulators ask who — and “the platform team” is not an answer. |
Intended purpose | App team, in one paragraph of plain language | Purpose drives legal classification under the EU AI Act, and scope creep against the stated purpose is the most common finding in our internal reviews. |
Legal / risk classification | App team proposes via the intake questionnaire; governance confirms | This is the field a regulator reads first. A wrong classification here invalidates every downstream control decision. |
Model dependencies | App team; exact model IDs and versions, not vendor names | “Various Bedrock models” hides exactly the change — a swapped model — that should trigger re-review. Specific IDs make drift detectable. |
Data classes processed | App team, from the corporate data classification scheme | Personal or special-category data in prompts changes the guardrail requirements and can change the legal classification. |
Guardrail configuration ref | App team; the ARN and version of the Bedrock guardrail (or gateway policy) in force | A control that exists in a document but not in the request path is not a control. The versioned ARN lets an auditor confirm the configuration that actually runs. |
Human oversight arrangement | App team; governance pushes back on vague answers | Oversight promised at approval time is the thing most likely to have quietly stopped happening a year later. |
Next review date | Set by governance; quarterly by default | An entry with no review date is a snapshot, not a register. The date is what makes the inventory a living control. |
The multi-account reality. In a Control Tower org, 'is this AI system registered?' is really 'which accounts may run AI workloads at all, and under what conditions?' We answer at the OU level. Accounts in the Workloads OUs may run Bedrock and SageMaker only if the workloads in them are registered — that is what the enforcement stack below checks. The Sandbox OU is exempt from registration, deliberately: forcing a register entry before an engineer can try a prompt kills exactly the experimentation we want to keep in-house rather than in personal accounts. But exemption from registration is not exemption from fences — sandbox accounts carry their own guardrails (no production data, no VPC peering back to workload networks, budget alarms, and the same region restrictions as everyone else), and anything graduating out of sandbox hits the register before it touches a workload account.
Enforcement is three mechanisms, layered:
- The SCP. A deny statement on every OU except the approved ones blocks the Bedrock inference actions — InvokeModel, InvokeModelWithResponseStream, Converse, ConverseStream — so an unapproved account gets an access-denied error, not a quiet model call. Inside approved accounts, IAM policies go further and pin invocations to the approved guardrail using the guardrail-identifier condition key: the allow requires it, an explicit deny rejects anything else. A developer who forgets the guardrail cannot invoke the model at all.
- The Config rule. An AWS Config custom rule (Lambda-backed, aggregated into the audit account) evaluates SageMaker endpoints and Bedrock resources for the register tag. No AIR-nnnn tag, or a tag pointing at a retired entry, flags the resource NON_COMPLIANT — and the audit-account dashboard shows every non-compliant resource across all 200 accounts in one view.
- The tripwire. Bedrock inference calls land in CloudTrail as management events, and CloudTrail delivers them to EventBridge. A rule matching bedrock.amazonaws.com API calls in accounts with no registered AI workload fires an automation that opens a ticket against the account owner. No human watches a screen for this; the ticket queue is the screen.
The undeclared-endpoint loop
- New AI resource or model call appears
A SageMaker endpoint is created, a Bedrock guardrail is configured, or inference calls start showing up in CloudTrail from an account with no registered AI workload.
- Config rule / EventBridge detects it
The Config custom rule evaluates the resource on configuration change; the EventBridge rule matches Bedrock API calls via CloudTrail. Both feed the audit account.
- Carries a valid register tag?
- Compliant — noted in aggregator
The resource joins the evidence trail: at audit time we can show every AI resource mapped to a validated register entry.
- Automation opens a ticket
Assigned to the account owner from the account metadata, cc governance. The ticket text explains how to register — most undeclared usage is ignorance, not malice.
- 5 business days to register or shut down
The deadline is policy, agreed with engineering leadership in advance — not improvised per incident.
- Registered or removed in time?
- Governance validates the new entry
The workload is now legitimate: tagged, guardrailed, on the quarterly attestation cycle.
- Access revoked pending review
The account moves under the deny SCP until the owner engages. This has happened twice in two years; both times the deadline had simply been ignored.
Quarterly attestation is the drift-correction heartbeat. Every quarter, each business owner gets their entries back with one question per field: is this still true? Re-affirming takes ten minutes if nothing changed. Material changes — new model, new data class, widened purpose — reopen governance validation, and occasionally send the system back through the ARB. Entries unattested after two reminders escalate to the owner’s director, which sounds bureaucratic and is: the escalation is the point, because an inventory the leadership chain never feels is an inventory that decays.
Two things made attestation survivable. First, we pre-fill the technical fields from the estate itself — the Config aggregator already knows the endpoints, tags, and guardrail versions, so owners confirm rather than transcribe. Second, we cut the schema down: our first register had forty-one fields and nobody maintained it. The nine above are the ones that earn their maintenance cost.