[0] From PIM to AIM — Agentic Information Flows Across the Asset Lifecycle

Author: Dragos Milotin · Date: 2026-02-23 · Length: 26 min read

A computational practitioner's guide to ISO 19650, AP242 STEP, REST/MCP, Python, and digital twin automation — treating information requirements as code and handover as an API contract.

# Executive Summary This article reframes the handover of built assets from a file-transfer problem to a data pipeline problem, arguing that modern asset lifecycle management requires treating information requirements as executable code rather than documentation. The author advocates replacing monolithic BIM file formats with composable, API-driven exchange layers—AP242 STEP for precise geometry, JSON over REST for operational attributes, and agent orchestration via the Model Context Protocol—each validated by typed schemas (Pydantic) and governed by ISO 19650 and ISO 9001 standards. The payoff is a living, queryable Asset Information Model that enables autonomous maintenance decisions triggered by sensor thresholds, eliminating manual coordination and creating an auditable, machine-readable handover trail from project delivery through operational life.


Read as:
Two images anchor this article. The first is a photograph of a bus stop — a real, physical asset sitting on a real street — overlaid with the ghost geometry of its Project Information Model: a ground floor plan, a west elevation, a 3D isometric wireframe, each tagged with an ISO 19650 reference. The second is that same bus stop rendered as an exploded isometric diagram, every component labelled with a material specification and a classification code, sitting above an ISO 19650 data schema cylinder that represents not a metaphor but a literal, queryable database. ![AIM — Asset Information Model: the same bus stop as discrete labelled components above an ISO 19650 data schema](entry_0_image_2.png) The journey from the first image to the second is the journey from PIM to AIM — from a project-phase accumulation of geometry and documentation to an operational-phase, component-level, queryable asset record. Most of the industry treats this journey as a file migration problem: export from a BIM authoring tool, bundle into a handover package, drop it on an FM team's shared drive, hope someone opens it. This article argues that the journey is, and always has been, a data pipeline problem. The built environment's information challenge is not a geometry challenge. Geometry is solved. Every major authoring platform can produce precise 3D models. The challenge is that geometry without structured, validated, API-accessible attribute data is an inert shape — beautiful, expensive, and operationally useless the day the scaffolding comes down. A deliberate exclusion: IFC does not appear in this workflow. IFC (ISO 16739) is the industry's default interoperability format, and it has done valuable work in enabling model-based exchange across heterogeneous authoring platforms. But IFC is a file-based exchange format. It assumes a world of periodic exports, round-trip translations, and human-mediated file handling. That assumption is the wrong abstraction for agentic, event-driven workflows where information moves through webhooks, REST calls, and autonomous agent orchestration. The primitives here are JSON over REST for attribute data and AP242 STEP (ISO 10303) for geometry — each doing one thing cleanly, composable into a pipeline that no monolithic file format can match. The thesis is direct: treat information requirements as code, treat handover as an API contract, treat the asset as a living queryable record.
## Introduction: From Static Models to Living Asset Records Two images tell the story of how assets move from design into operation. The first shows a bus stop—a physical structure on a real street—overlaid with its Project Information Model: a floor plan, an elevation view, and a 3D wireframe, each tagged with ISO 19650 references. The second image shows that same bus stop broken down into labeled components—roof panel, support columns, foundation, digital display, lighting—sitting above a data schema that represents not a diagram but an actual, searchable database. This journey from design model to operational asset record is what we call the PIM-to-AIM transition. In construction and facilities management, most teams treat this as a file handover problem: export the design model, package it into a folder, pass it to the operations team, and hope someone uses it. This article argues something different: it's a data pipeline problem. The real challenge in managing built assets isn't geometry—that's solved. Every modern design tool creates accurate 3D models. The challenge is that geometry without structured, validated data about materials, maintenance needs, warranties, and performance thresholds is just an expensive picture. It can't tell a maintenance system when a lamp needs replacing or alert a manager when a structural sensor reading goes out of safe limits. This article focuses on a clean separation of concerns: use AP242 STEP (an ISO standard for precise 3D geometry and product structure) to define *what the asset is and what it looks like*. Use JSON over REST (standard web data formats) to define *how to operate and maintain it*. Use agents (automated reasoning systems) to orchestrate the handover and monitor the asset throughout its life. Together, these form a pipeline that no single file format can match. The core thesis is simple: treat information requirements as executable code, treat handover as an API contract, and treat the asset as a living, queryable database.
## Executive Brief: From Project Data to Operational Asset Intelligence **The Core Challenge**: Your built environment assets contain critical operational information trapped in inaccessible formats. A $50M facility modeled with precision during design becomes an operational liability on day one because geometry without structured, machine-readable attribute data—maintenance schedules, material specs, vendor information, warranty terms—cannot power automated facility management, predictive maintenance, or capital planning. **The Business Impact**: Treating asset handover as a data pipeline problem—not a file migration problem—unlocks three strategic capabilities: (1) **Automated compliance**: Asset records validated against information requirements at project completion, eliminating post-handover data debt; (2) **Sensor-driven maintenance**: Threshold-based alerts trigger work orders without human intervention, reducing emergency calls and extending asset life; (3) **Capital planning accuracy**: Queryable component-level records enable predictive lifecycle costing and portfolio risk assessment. **Why This Matters Now**: Industry-standard formats exist today (ISO 19650 for information governance, AP242 STEP for geometry, REST APIs for attributes, Pydantic for validation). The gap is not technical—it is architectural. Organizations still treat handover as a meeting, not a contract. The asset that leaves the construction site as a static model should arrive in operations as a live, queryable database.

[1] PIM — The Project Information Model as a Data Contract

ISO 19650 Parts 1 and 2 define the Project Information Model as the accumulated body of information generated during the design and construction phases of an asset's lifecycle. The PIM comprises three layers: graphical information (the geometry itself — plans, sections, 3D models), non-graphical information (attributes, classifications, specifications attached to model elements), and documentation (reports, schedules, certificates that accompany but are not embedded in the model). The PIM is not a single file. It is the total structured information state of the project at any given point. The first image makes this concrete. Look at the three views overlaid on the photograph: the ground floor plan (a 2D orthographic cut through the bus stop at floor level), the west elevation (a 2D orthographic projection of the western face), and the 3D isometric model (a parallel-projection rendering of the full geometry). These are not three independent drawings. They are three views of the same underlying model state — three queries against a single geometric dataset. The plan is a horizontal section query. The elevation is a directional projection query. The isometric is an unclipped 3D render query. The model is the source; the views are derived artefacts. This distinction matters because it reframes the PIM not as a collection of drawings but as a versioned information contract. At each Information Delivery Milestone under ISO 19650-2, the PIM must satisfy a defined Level of Information Need (LOIN) — a specification stating what data must be present, at what granularity, for each element category. A column at RIBA Stage 3 might require a material classification code, a structural grade, and a cross-section dimension. At Stage 5, it might additionally require a supplier reference, an as-built survey tolerance, and a commissioning certificate link. The LOIN is the contract; the PIM is the deliverable tested against it. Non-graphical data — the attributes that make geometry operationally meaningful — lives naturally in JSON. Element classification codes following Uniclass 2015, material specifications referencing BS EN standards, cost codes mapped to NRM structures, construction sequencing attributes — all of these are key-value pairs, nested objects, or typed arrays. They belong in structured data formats queryable over REST from a Common Data Environment, not locked inside proprietary binary files accessible only through desktop authoring software. The validator below formalises this idea. It defines a LOIN specification as a Pydantic model — a typed, validated Python schema — and checks a JSON payload fetched from a CDE against that specification. The output is a structured gap report: which elements are complete, which are missing required attributes, and what the overall completeness percentage is per element category. ```python # pim_loin_validator.py — LOIN specification validator # Pydantic model representing a Level of Information Need specification; # validates a JSON payload (fetched via REST from a CDE) against required # attribute presence and type — outputs a structured gap report as JSON from pydantic import BaseModel from typing import Optional class LOINAttribute(BaseModel): name: str required: bool = True type_hint: str = "str" class LOINSpec(BaseModel): element_category: str riba_stage: str attributes: list[LOINAttribute] threshold: float = 0.9 # 90% completeness required class GapItem(BaseModel): element_id: str category: str present: list[str] missing: list[str] completeness: float class GapReport(BaseModel): milestone: str total_elements: int items: list[GapItem] overall_completeness: float ``` The bar chart visualises the result: attribute completeness percentage per element category — columns, roof panels, foundations — plotted against the LOIN threshold. Any bar falling short of the threshold line represents an information delivery failure, a gap that must be closed before the milestone gate opens.
## The Project Information Model (PIM): Structured Data During Design and Construction ISO 19650 Parts 1 and 2 define the Project Information Model as everything the design and construction teams create about an asset—from initial sketches through final handover. The PIM has three layers: graphical data (the 3D models, plans, sections), non-graphical data (attributes like material grades, classifications, specifications attached to model elements), and documentation (reports, certificates, compliance records). Think of it this way: the design model isn't three separate drawings—a floor plan, an elevation, and a 3D view. They're three different queries against the same underlying data. The floor plan is a horizontal slice. The elevation is a directional projection. The 3D view is an unclipped rendering. One model, three views. This matters because it means the PIM isn't a collection of files; it's a versioned information contract. At each project milestone (design stage, construction start, handover), the PIM must meet a Level of Information Need (LOIN)—a formal specification stating what data must exist, at what level of detail, for each component. A concrete foundation column at design stage might need a material grade and dimensions. At handover, it additionally needs the actual as-built survey results, supplier certification, and links to inspection records. The LOIN is the acceptance checklist; the PIM is what gets measured against it. Non-graphical data—the attributes that make geometry useful for operations—naturally fits into JSON, a standard data format. Element classification codes (Uniclass system), material specifications (British Standards), cost codes, construction sequencing—all are key-value pairs that belong in queryable databases accessible via web APIs, not locked in proprietary software files. The validator below formalizes this. It defines a LOIN requirement as a typed schema and checks a JSON payload (fetched from a cloud project platform) against that specification. The output is a gap report: which components are complete, which are missing required data, and what the overall completeness percentage is. ```python # pim_loin_validator.py — LOIN specification validator # Pydantic model representing a Level of Information Need specification; # validates a JSON payload (fetched via REST from a CDE) against required # attribute presence and type — outputs a structured gap report as JSON from pydantic import BaseModel from typing import Optional class LOINAttribute(BaseModel): name: str required: bool = True type_hint: str = "str" class LOINSpec(BaseModel): element_category: str riba_stage: str attributes: list[LOINAttribute] threshold: float = 0.9 # 90% completeness required class GapItem(BaseModel): element_id: str category: str present: list[str] missing: list[str] completeness: float class GapReport(BaseModel): milestone: str total_elements: int items: list[GapItem] overall_completeness: float ``` A bar chart visualizes the result: for each component type (columns, roof panels, foundations), showing what percentage of required data is actually present. Any bar below the threshold line represents missing information that must be added before the project moves forward.
## Project Information Model: Data Structure as a Delivery Contract **What You're Getting**: The PIM is not a drawing package—it is a versioned, structured dataset comprising geometry (3D models, sections, elevations), non-graphical attributes (material specs, classification codes, cost references), and supporting documentation. These are views of a single underlying data model, not independent deliverables. **The Governance Framework**: ISO 19650 defines **Levels of Information Need (LOIN)** per project stage—a specification stating exactly what data must be present and at what detail for each asset component. A structural column at design stage requires a material code and cross-section; at completion, it requires as-built survey tolerance, commissioning sign-off, and supplier reference. The LOIN is your acceptance criterion; the gap report is your proof of compliance. **Why This Drives ROI**: Non-graphical data—Uniclass classifications, BS EN material references, NRM cost codes, maintenance intervals—belongs in structured JSON queried via REST, not locked in proprietary binary files. When attributes live in a Common Data Environment with automated validation, information quality is measurable, auditable, and repeatable per ISO 9001. Manual coordination meetings disappear; timestamped validation reports replace them. A hospital with 50,000 components cannot achieve compliance through desktop reviews—it requires automated schema enforcement. **The Quality Gate**: Completeness metrics per component category (columns, panels, foundations) plotted against LOIN thresholds make information delivery failures immediately visible. Any bar falling below the threshold represents a gate-blocking gap, identified and resolved before project handover.

[2] AP242 STEP — Geometry Without Bloat

ISO 10303, informally known as STEP (Standard for the Exchange of Product model data), is the international standard for product data representation and exchange. Application Protocol 242 — Managed Model-Based 3D Engineering — is the profile designed for precise, complete, geometry-rich exchange. AP242 has been proven at scale in automotive and aerospace, industries where geometric fidelity is non-negotiable and where "close enough" tolerance is a liability. It is now entering the infrastructure and built environment domain, and the reasons are worth understanding. AP242 carries exact boundary representation (B-rep) geometry: NURBS surfaces, precise analytic solids, trimmed surfaces, and closed shells. It does not approximate curved surfaces with tessellated meshes unless explicitly requested. It encodes dimensional and geometric tolerances (GD&T) as first-class data, not as annotation overlays. It represents assembly structure — the parent-child relationships between products and their constituent parts — in a single, self-contained `.stp` file. No proprietary geometry kernel is required to read it. Any STEP-compliant parser can traverse the entity graph and extract both shape and structure. The power of AP242 lies in the schema underneath it. The EXPRESS data modelling language (ISO 10303-11) defines the entity types, attribute constraints, inheritance hierarchies, and relationship semantics that make a STEP file self-describing. An entity like `PRODUCT` carries a name, a description, and links to `PRODUCT_DEFINITION` entities that bind it to a lifecycle stage. `NEXT_ASSEMBLY_USAGE_OCCURRENCE` entities encode the parent-child assembly tree. `PROPERTY_DEFINITION` and `PROPERTY_DEFINITION_REPRESENTATION` entities attach material properties, surface finishes, and physical characteristics to specific products or product definitions. The schema is the documentation; the data file is a populated instance of that schema. Map this to the second image. The bus stop assembly is a `PRODUCT`. Its sub-assemblies — the roof panel (glass), the support columns (recycled plastic), the foundation poles (concrete), the digital display (LCD), the LED luminaire — are each a `PRODUCT` linked to the parent via `NEXT_ASSEMBLY_USAGE_OCCURRENCE`. Material and finish data (glass specification, recycled plastic grade, concrete mix class) attach as `PROPERTY_DEFINITION` entities referencing the relevant `PRODUCT_DEFINITION`. The entire structure — what is the bus stop, what is it made of, how do the parts relate — is encoded in the STEP entity graph, not in a sidecar spreadsheet or a manually maintained BOM. The exchange pattern that emerges is clean: AP242 handles geometry and product structure — the shape and composition of the asset. JSON over REST handles operational and facilities management attributes — maintenance intervals, sensor bindings, warranty dates, cost codes. These are two distinct data planes with a shared key: the component identifier. AP242 tells you what the thing is and what it looks like. JSON tells you how to manage it. Mixing these concerns into a single monolithic file format is the source of most interoperability pain in the industry. Separating them is the solution. The parser below extracts the product assembly tree and property definitions from an AP242 `.stp` file, outputting a flat JSON structure keyed by component name. This is the geometry side of the AIM record — the structural skeleton onto which operational attributes will be grafted. ```python # step_parser.py — AP242 product tree extractor # Uses text parsing to extract PRODUCT tree and PROPERTY_DEFINITION # records from an AP242 .stp file, outputting a flat JSON structure # keyed by component name — the geometry side of the AIM record import re from dataclasses import dataclass, field @dataclass class StepProduct: instance_id: int name: str children: list[str] = field(default_factory=list) properties: dict[str, str] = field(default_factory=dict) PRODUCT_RE = re.compile( r"#(\d+)\s*=\s*PRODUCT\s*\(\s*'([^']+)'", re.IGNORECASE ) NAUO_RE = re.compile( r"NEXT_ASSEMBLY_USAGE_OCCURRENCE\s*\([^)]*\)", re.IGNORECASE ) def extract_products(step_text: str) -> dict[str, StepProduct]: products = {} for m in PRODUCT_RE.finditer(step_text): pid, name = int(m.group(1)), m.group(2) products[name] = StepProduct(instance_id=pid, name=name) return products ``` The treemap visualises the assembly hierarchy: the bus stop as the root, sub-assemblies as branches, individual parts as leaves, each sized by vertex and face count. This is a map of geometric complexity distribution — immediately revealing which components carry the heaviest modelling investment and which are lightweight placeholders.
## AP242 STEP: Precise Geometry Exchange Without Proprietary Dependencies ISO 10303, informally called STEP (Standard for the Exchange of Product model data), is the international standard for representing and sharing product data with exact precision. Application Protocol 242 (AP242)—Managed Model-Based 3D Engineering—is specifically designed for precision geometry. It's been proven in automotive and aerospace, industries where "close enough" is unacceptable. It's now entering construction and infrastructure, and it matters because it solves a real problem. AP242 carries exact boundary representation geometry: NURBS surfaces, precise solids, trimmed surfaces, and closed shells. It doesn't approximate curved surfaces with tessellated meshes. It encodes dimensional and geometric tolerances (the precision requirements engineers care about) as first-class data, not as annotations overlaid on a drawing. It represents how components relate—the parent-child relationships, assembly structure—in a single self-contained file. No proprietary software is needed to read it; any STEP-compliant parser can extract both shape and structure. The power comes from the schema underneath. EXPRESS (the data modeling language in ISO 10303) defines the entity types, constraints, hierarchies, and relationships that make a STEP file self-documenting. A `PRODUCT` entity has a name and description and links to product definitions that bind it to lifecycle stages. `NEXT_ASSEMBLY_USAGE_OCCURRENCE` entities encode the parent-child assembly tree. `PROPERTY_DEFINITION` entities attach material properties, surface finishes, and physical characteristics to specific products. The schema is the documentation; the data file is a populated instance. Applied to the bus stop: the bus stop assembly is a `PRODUCT`. Its sub-assemblies—the glass roof panel, plastic support columns, concrete foundation poles, LCD display, LED lights—are each a `PRODUCT` linked to the parent. Material and finish data (glass specification, recycled plastic grade, concrete mix class) attach as properties linked to product definitions. The entire structure—what the bus stop is, what it's made of, how parts relate—is encoded in the STEP entity graph, not in a separate spreadsheet or manually maintained bill of materials. This is the key pattern: AP242 handles geometry and product structure (shape and composition). JSON handles operational attributes (maintenance intervals, sensor locations, warranty dates). These are two data layers sharing one key: the component identifier. AP242 tells you *what the thing is*. JSON tells you *how to manage it*. Mixing these into one file format is the source of most data exchange pain in construction. Separating them is the solution. The parser below extracts the product assembly and properties from an AP242 file, outputting a flat JSON structure keyed by component name. This is the geometry skeleton onto which operational data will be attached. ```python # step_parser.py — AP242 product tree extractor # Uses text parsing to extract PRODUCT tree and PROPERTY_DEFINITION # records from an AP242 .stp file, outputting a flat JSON structure # keyed by component name — the geometry side of the AIM record import re from dataclasses import dataclass, field @dataclass class StepProduct: instance_id: int name: str children: list[str] = field(default_factory=list) properties: dict[str, str] = field(default_factory=dict) PRODUCT_RE = re.compile( r"#(\d+)\s*=\s*PRODUCT\s*\(\s*'([^']+)'", re.IGNORECASE ) NAUO_RE = re.compile( r"NEXT_ASSEMBLY_USAGE_OCCURRENCE\s*\([^)]*\)", re.IGNORECASE ) def extract_products(step_text: str) -> dict[str, StepProduct]: products = {} for m in PRODUCT_RE.finditer(step_text): pid, name = int(m.group(1)), m.group(2) products[name] = StepProduct(instance_id=pid, name=name) return products ``` A treemap visualizes the assembly hierarchy: bus stop as root, sub-assemblies as branches, individual parts as leaves, sized by geometric complexity. This reveals which components demanded the most modeling effort and which are simplified placeholders.
## Geometry as a Data Plane: Why AP242 STEP Replaces Proprietary Exports **The Core Advantage**: AP242 (ISO 10303) is the proven standard for precise, complete geometry exchange in industries where tolerance is non-negotiable—aerospace, automotive, now infrastructure. It encodes exact boundary-representation geometry (NURBS surfaces, analytic solids, tolerances) in a self-describing schema that requires no proprietary software to parse. Every component's assembly relationship, material properties, and dimensional specification lives in a single queryable data structure. **Operational Reality**: A bus stop assembly becomes a machine-readable product tree: parent asset (bus stop) → sub-assemblies (roof panel, support column, digital display, LED luminaire, foundation pole) → material and finish specifications. This structure—what the asset is, what it comprises, how parts relate—is encoded in the STEP entity graph, not in a spreadsheet or email chain. **Why Separation of Concerns Matters**: AP242 handles geometry and structure (shape, composition); JSON REST handles operational attributes (maintenance intervals, warranty dates, vendor references, sensor bindings). These are two distinct data planes sharing a component identifier as the key. Mixing them in a monolithic file format is the source of interoperability pain. Separating them is the solution. Geometry updates only on physical modification; attributes update continuously during operation. **The Payoff**: The assembly hierarchy—visualized as a treemap sized by geometric complexity—reveals instantly which components carry engineering investment and which are lightweight placeholders. This drives both cost control during design and maintenance prioritization during operations.

[3] AIM — The Asset Information Model as a Queryable Record

ISO 19650-3 shifts the frame from project delivery to asset operation. The Asset Information Model is defined as the persistent body of information required to support the management, maintenance, and operation of an asset throughout its operational life. The critical word is persistent. The PIM is a transient accumulation — it grows during the project and is handed over at completion. The AIM is the enduring record. It does not sit in a project folder that gets archived when the contractor demobilises. It is the live, queryable data layer that the asset owner, the facilities manager, and increasingly the autonomous maintenance agent interact with for the remaining decades of the asset's service life. The second image makes the AIM tangible. Each labelled component — Roof Panel Glass, Support Column Recycled Plastic, Digital Display LCD, LED Luminaire, Foundation Pole Concrete — is not an annotation on a drawing. It is a discrete, addressable asset record. The label is a human-readable rendering of a structured data object: a JSON document with typed fields for classification code, material specification, maintenance interval, warranty expiry, supplier reference, and sensor binding endpoint. The ISO 19650 data schema cylinder at the bottom of the image is not a conceptual metaphor. It represents a literal schema commitment — a database with a defined structure that every component record must conform to before it is accepted into the AIM. Facilities management data requirements per component are specific and non-negotiable. The Roof Panel Glass needs a maintenance interval (cleaning cycle in days), a material spec (toughened laminated glass to BS EN 12150), a warranty expiry date, a supplier reference for replacement procurement, and optionally a sensor binding point for a structural deflection monitor. The LED Luminaire needs a maintenance interval (lamp replacement cycle), a lux output specification, a warranty period, a supplier reference, and a sensor endpoint for real-time lux telemetry. The Foundation Pole Concrete needs a maintenance interval (inspection cycle), a concrete mix class (C40/50 to BS EN 206), a design life, and a corrosion monitoring endpoint. Each component is a typed record; the AIM is the collection of those records under a unified schema. Pydantic makes this schema executable. A Pydantic model is not a documentation exercise — it is a runtime validation contract. Define an `AssetComponent` model with fields typed as `str`, `int`, `date`, `Optional[HttpUrl]`, and every record ingested into the AIM is validated at write time. Malformed data — a missing classification code, a maintenance interval encoded as a string instead of an integer, a warranty date in the wrong format — is rejected before it enters the database. The schema is the quality gate, and it runs automatically on every write. ```python # aim_model.py — Pydantic AIM schema # AssetRecord and AssetComponent models with ISO 19650-aligned fields # Includes from_step_json() classmethod for ingesting step_parser output from datetime import date from typing import Optional from pydantic import BaseModel, HttpUrl class AssetComponent(BaseModel): component_id: str classification_code: str # Uniclass 2015 material_spec: str # BS EN reference maintenance_interval_days: int warranty_expiry: date supplier_reference: Optional[str] = None sensor_endpoint: Optional[HttpUrl] = None class AssetRecord(BaseModel): asset_identifier: str asset_name: str components: list[AssetComponent] schema_version: str = "1.0" @classmethod def from_step_json(cls, step_data: dict, fm_data: dict) -> "AssetRecord": components = [] for name, props in step_data.items(): fm = fm_data.get(name, {}) components.append(AssetComponent( component_id=name, classification_code=fm.get("classification", ""), material_spec=fm.get("material", ""), maintenance_interval_days=fm.get("interval", 365), warranty_expiry=fm.get("warranty", date.today()), )) return cls( asset_identifier=step_data.get("_id", "unknown"), asset_name=step_data.get("_name", "Unnamed"), components=components, ) ``` The Gantt-style chart projects the maintenance schedule across all AIM components over a five-year horizon. Each bar represents a component's recurring maintenance cycle, derived directly from the `maintenance_interval_days` field in the AIM record. This is not a manually created FM schedule — it is a computed artefact, regenerated on demand from the data.
## The Asset Information Model (AIM): The Operational Record That Lasts Decades ISO 19650-3 shifts focus from project delivery to asset operation. The Asset Information Model is the persistent body of data required to manage, maintain, and operate an asset throughout its service life—potentially 30, 50, or more years. The key word is persistent. The PIM grows during the project and is handed over at completion; it's temporary. The AIM is the enduring record that the asset owner, facilities manager, and automated maintenance systems interact with for the entire operational life. The labeled bus stop diagram makes the AIM tangible. Each labeled component—Roof Panel Glass, Support Column Recycled Plastic, Digital Display LCD, LED Luminaire, Foundation Pole Concrete—isn't an annotation on a drawing. It's a discrete, addressable asset record. The label is a human-readable rendering of a structured JSON object with typed fields for classification code, material specification, maintenance interval, warranty expiry, supplier reference, and sensor binding endpoint. The ISO 19650 schema cylinder at the bottom isn't a metaphor; it represents an actual database schema that every component record must conform to. Facilities management data per component is specific and non-negotiable. Roof Panel Glass needs: a cleaning maintenance interval (how often, in days), a material specification (toughened laminated glass to BS EN 12150), warranty expiry date, supplier contact for replacement, and optionally a sensor endpoint for a structural monitoring device. LED Luminaire needs: lamp replacement interval, lux output specification, warranty period, supplier reference, and a sensor endpoint for real-time brightness telemetry. Foundation Pole Concrete needs: inspection interval, concrete mix class (C40/50 to BS EN 206), design life, and a sensor endpoint for corrosion monitoring. Each component is a typed record; the AIM is the collection under a unified schema. Pydantic (a Python data validation tool) makes this schema executable. It's not documentation—it's a runtime validation contract. Define an `AssetComponent` model with typed fields (`str`, `int`, `date`, `URL`), and every record written to the AIM is validated automatically. Malformed data—a missing classification code, a maintenance interval as text instead of a number, a warranty date in the wrong format—is rejected before it enters the database. The schema is the quality gate, running automatically on every write. ```python # aim_model.py — Pydantic AIM schema # AssetRecord and AssetComponent models with ISO 19650-aligned fields # Includes from_step_json() classmethod for ingesting step_parser output from datetime import date from typing import Optional from pydantic import BaseModel, HttpUrl class AssetComponent(BaseModel): component_id: str classification_code: str # Uniclass 2015 material_spec: str # BS EN reference maintenance_interval_days: int warranty_expiry: date supplier_reference: Optional[str] = None sensor_endpoint: Optional[HttpUrl] = None class AssetRecord(BaseModel): asset_identifier: str asset_name: str components: list[AssetComponent] schema_version: str = "1.0" @classmethod def from_step_json(cls, step_data: dict, fm_data: dict) -> "AssetRecord": components = [] for name, props in step_data.items(): fm = fm_data.get(name, {}) components.append(AssetComponent( component_id=name, classification_code=fm.get("classification", ""), material_spec=fm.get("material", ""), maintenance_interval_days=fm.get("interval", 365), warranty_expiry=fm.get("warranty", date.today()), )) return cls( asset_identifier=step_data.get("_id", "unknown"), asset_name=step_data.get("_name", "Unnamed"), components=components, ) ``` A Gantt-style chart projects the maintenance schedule across all components over five years. Each bar represents a component's recurring maintenance cycle, derived directly from the `maintenance_interval_days` field. This isn't a manually created schedule; it's computed automatically from the data every time.
## Asset Information Model: The Living Operational Record **The Shift in Perspective**: ISO 19650-3 moves from project delivery (PIM) to asset operation (AIM). The PIM is transient—it grows during construction and is handed over at completion. The AIM is persistent—it is the live, queryable data layer that asset owners, facilities managers, and autonomous agents interact with for the remaining decades of the asset's operational life. **Operational Structure**: Each component is a discrete, typed JSON record: Roof Panel Glass (toughened laminated glass per BS EN 12150, cleaning cycle 90 days, warranty expires 2034-Q3, sensor-bound for structural deflection); LED Luminaire (lux output 250 cd/m², lamp replacement cycle 180 days, real-time telemetry endpoint); Foundation Pole Concrete (C40/50 concrete per BS EN 206, inspection cycle 365 days, corrosion monitoring sensor). The AIM is the collection of these records under a unified schema enforced by Pydantic at write time. **The Quality Mechanism**: Schema enforcement at runtime means malformed data—missing classification codes, maintenance intervals as strings instead of integers, warranty dates in wrong format—is rejected before it enters the database. The schema becomes the quality gate. Every write is validated; every record entering the AIM is certified conformant. **Strategic Impact**: A computed maintenance schedule regenerated on demand from `maintenance_interval_days` fields replaces manual FM spreadsheets. Predictive capital planning—warranty expiry alerts, maintenance clustering, lifecycle cost projection—flows from validated component-level data. Sensor binding endpoints enable threshold-based work order generation, turning reactive maintenance into data-driven operations.

[4] The Handover Gap — Information Debt at Milestone Boundary

The gap between PIM and AIM is where most built environment projects accumulate their deepest information debt. The geometry arrives — richly modelled, visually impressive, rendered in fly-through videos for client presentations. But the non-graphical data that makes that geometry operationally useful arrives late, arrives incomplete, or does not arrive at all. A column exists as a 3D solid with a material appearance shader, but its classification code field is empty. A roof panel has a material specification in a PDF datasheet on someone's laptop, but the structured attribute in the model element is null. A foundation pole has a supplier reference in an email chain, but no one has entered it into the CDE as a queryable attribute. This is not a people problem, though it manifests through people. It is a systems problem: the information requirements were specified in a document (the Exchange Information Requirements, EIR, or the Asset Information Requirements, AIR), but they were not encoded as machine-readable validation rules. The check was manual — a BIM coordinator opening the model, clicking through elements, scanning property sets. Manual checks are sampling-based, subjective, inconsistent, and they do not scale. A bus stop has five major components. A hospital has fifty thousand. Manual validation at that scale is not a quality process; it is a lottery. Quantifying the gap requires three metrics. First, LOIN completeness score per component: what percentage of the required attributes for a given element category are present and correctly typed. Second, mandatory versus optional attribute fill rate: a component might be 70% complete overall but missing 100% of its mandatory fields — a distinction that matters for milestone acceptance. Third, classification coverage: what percentage of model elements have a valid Uniclass 2015 (or equivalent) classification code, the key that links geometry to asset management taxonomies. These metrics are data quality metrics, and they are auditable under ISO 9001. Section 8.1 of ISO 9001 requires that organisations plan and control the processes needed to meet requirements, including the criteria for acceptance. The LOIN specification is the acceptance criterion. The gap report is the measurement. The audit trail — timestamped, per-component, per-attribute — is the objective evidence. Information quality management is not a BIM-specific discipline; it is a quality management discipline, and it has a standard. ```python # handover_gap.py — PIM vs AIM completeness comparator # Compares a PIM JSON payload (REST fetch) against AIM schema requirements; # produces a gap report JSON with per-component scores and a summary # completeness percentage — idempotent, re-runnable at any CDE milestone def compute_gap(pim_payload: dict, aim_schema: dict) -> dict: items = [] for element in pim_payload.get("elements", []): required = aim_schema.get(element["category"], []) present = [a for a in required if a in element] missing = [a for a in required if a not in element] score = len(present) / len(required) if required else 1.0 items.append({ "element_id": element["id"], "category": element["category"], "present": present, "missing": missing, "completeness": round(score, 3), }) overall = ( sum(i["completeness"] for i in items) / len(items) if items else 0.0 ) return { "total_elements": len(items), "items": items, "overall_completeness": round(overall, 3), } ``` The heatmap makes the gap visible. Components form the rows; required attributes form the columns. Green cells indicate presence; red cells indicate absence. The overall completeness score sits in the chart title. This is the view a project information manager needs at every milestone gate: not a narrative report, not a meeting, but a data-driven, automatically generated diagnostic.
## The Handover Gap: Where Information Debt Accumulates The space between PIM and AIM is where most construction projects run up the deepest information debt. The geometry arrives—detailed, visually impressive, rendered in beautiful presentation videos. But the non-graphical data that makes that geometry operationally useful arrives late, incomplete, or not at all. A concrete column exists as a precise 3D solid with realistic appearance but its classification code is blank. A roof panel has a material datasheet PDF sitting on someone's laptop, but the structured attribute in the model is null. A foundation pole has a supplier name in an email thread, but no one has entered it into the project platform as a queryable field. This isn't a people problem, though it feels like one. It's a systems problem. The information requirements were written in a document (the Exchange Information Requirements or Asset Information Requirements), but they were never encoded as machine-readable validation rules. The check was manual—a BIM coordinator opening the software, clicking through elements, scanning property fields. Manual checks are subjective, inconsistent, and they don't scale. A bus stop has five major components; a hospital has fifty thousand. Manual validation at that scale isn't quality control; it's a lottery. Quantifying the gap requires three metrics. First, LOIN completeness score per component: what percentage of required attributes are present and correctly formatted. Second, mandatory versus optional field fill rate: a component might be 70% complete overall but missing 100% of mandatory fields—a critical distinction for project approval. Third, classification coverage: what percentage of model elements have a valid classification code (the key linking to asset management systems). These are data quality metrics, auditable under ISO 9001. Section 8.1 requires organizations to define acceptance criteria for their processes. The LOIN specification is that criterion. The gap report is the measurement. The timestamped, per-component, per-attribute audit trail is the objective evidence. Information quality isn't a BIM discipline; it's a quality management discipline with an established standard. ```python # handover_gap.py — PIM vs AIM completeness comparator # Compares a PIM JSON payload (REST fetch) against AIM schema requirements; # produces a gap report JSON with per-component scores and a summary # completeness percentage — idempotent, re-runnable at any CDE milestone def compute_gap(pim_payload: dict, aim_schema: dict) -> dict: items = [] for element in pim_payload.get("elements", []): required = aim_schema.get(element["category"], []) present = [a for a in required if a in element] missing = [a for a in required if a not in element] score = len(present) / len(required) if required else 1.0 items.append({ "element_id": element["id"], "category": element["category"], "present": present, "missing": missing, "completeness": round(score, 3), }) overall = ( sum(i["completeness"] for i in items) / len(items) if items else 0.0 ) return { "total_elements": len(items), "items": items, "overall_completeness": round(overall, 3), } ``` A heatmap visualization makes the gap visible at a glance. Components form rows; required attributes form columns. Green indicates data is present; red indicates it's missing. The overall completeness percentage appears in the title. This is what a project information manager needs at each milestone: not a narrative report or a meeting, but a data-driven, automatically generated diagnostic showing exactly what's complete and what's missing.
## Closing the Handover Gap: Quantifying Information Delivery Compliance **The Problem**: Geometry arrives richly modeled; non-graphical data arrives late, incomplete, or not at all. A column exists as a 3D solid but its classification code field is null. A roof panel has a vendor datasheet in someone's email but no structured attribute in the CDE. This is not a people problem—it is a systems problem: information requirements were documented but not encoded as machine-readable validation rules, so checks remained manual, sampling-based, and inconsistent. **Three Metrics That Matter**: - **LOIN Completeness**: What percentage of required attributes per component category are present and correctly typed? - **Mandatory vs. Optional Fill Rate**: A component 70% complete overall might be missing 100% of mandatory fields—a gate-blocking distinction. - **Classification Coverage**: What percentage of model elements have valid Uniclass 2015 codes linking geometry to FM taxonomies? **The Audit Trail**: These metrics are ISO 9001 §8.1 objective evidence. A timestamped, per-component, per-attribute gap report generated automatically at each milestone becomes your documented proof of conformity. Information quality management is not a BIM discipline—it is a quality management discipline with a standard backing it. **The Visual Signal**: A heatmap showing components (rows) vs. required attributes (columns) with green for present and red for absent makes information gaps immediately visible to project and asset leadership. Overall completeness score in the chart title answers the go/no-go question at every milestone gate.

[5] REST + MCP — The Agentic Exchange Layer

Every read and write in this workflow is an HTTP call. The CDE is the source of truth — a cloud-hosted platform exposing RESTful endpoints for document retrieval, metadata query, status transition, and webhook registration. When a design team moves a work package from WIP to Shared status in the CDE, that transition is not a folder move; it is a state change event published via webhook to any registered subscriber. The agent is one such subscriber. The agent does not call CDE APIs directly in the way a script might. This is where the Model Context Protocol (MCP) enters the architecture. MCP is an open protocol that defines how a reasoning agent — an LLM-driven orchestrator — discovers, invokes, and composes tools. The agent does not contain business logic. It contains reasoning about which tools to call, in what order, with what inputs, based on the event it received and the goal it is pursuing. The tools themselves — `validate_loin`, `parse_step`, `write_aim_record` — are functions exposed as MCP tool definitions, each with a typed schema for its inputs and outputs. The workflow is event-driven and linear. A CDE webhook fires when a work package transitions from WIP to Shared, signalling that new information is available for validation. The agent receives the webhook payload, which contains the work package identifier and the CDE endpoint for the associated data. The agent calls the `validate_loin` tool, passing the CDE endpoint; the tool fetches the PIM JSON payload via REST and runs the LOIN validation, returning a gap report. If AP242 geometry is included in the package, the agent calls the `parse_step` tool, which reads the `.stp` file and extracts the product tree as JSON. The agent then calls the `write_aim_record` tool, which merges the validated PIM attributes with the parsed STEP structure and writes the composite record to the AIM database. Finally, the agent posts the gap report back to the CDE via REST, attaching it to the work package as a validation artefact. Why this architecture is lean: there is no middleware layer. There is no ETL batch job running overnight. There is no BIM authoring software in the loop — no desktop application that must be open, licensed, and manually operated. The entire exchange happens on the data plane: JSON payloads over HTTP, parsed STEP files yielding structured JSON, Pydantic models validating every record, and an agent orchestrating the sequence without human intervention. The agent is the middleware, and it reasons about its task rather than executing a hardcoded script. ```python # aim_mcp_server.py — Minimal MCP server exposing three tools # validate_loin(payload), parse_step(file_path), write_aim_record(record) # Wired to the functions from prior scripts; runnable with uv run from mcp.server import Server from mcp.types import Tool app = Server("aim-tools") @app.tool() async def validate_loin(payload: dict) -> dict: """Validate PIM payload against LOIN specification.""" # Delegates to pim_loin_validator.validate() ... @app.tool() async def parse_step(file_path: str) -> dict: """Extract AP242 product tree from .stp file.""" # Delegates to step_parser.extract_products() ... @app.tool() async def write_aim_record(record: dict) -> dict: """Merge validated PIM + STEP data and write AIM record.""" # Delegates to aim_model.AssetRecord.from_step_json() ... ``` ```python # aim_agent.py — Async agent loop (~60 lines) # Listens for a CDE webhook event (simulated), orchestrates the MCP # tool sequence, and logs the AIM write confirmation import asyncio async def handle_webhook(event: dict) -> dict: """Process a CDE state-change webhook.""" wp_id = event["work_package_id"] cde_url = event["cde_endpoint"] # 1. Validate PIM against LOIN gap_report = await validate_loin({"url": cde_url}) # 2. Parse AP242 geometry if present step_data = {} if event.get("has_geometry"): step_data = await parse_step(event["stp_path"]) # 3. Write composite AIM record result = await write_aim_record({ "work_package": wp_id, "pim_data": gap_report, "step_data": step_data, }) return {"status": "ok", "aim_id": result["id"]} ``` The sequence traces the full flow: CDE emits a webhook; the agent receives it; the agent calls `validate_loin`, `parse_step`, and `write_aim_record` in sequence; the AIM database is updated; the gap report is posted back to the CDE. Every arrow is an HTTP call or an MCP tool invocation — no file transfers, no manual steps.
## REST APIs and Agent Orchestration: Automating the Validation Pipeline Every read and write in this workflow is an HTTP call. The project management platform (the Common Data Environment) is the source of truth—a cloud system exposing web API endpoints for document retrieval, metadata queries, status changes, and event notifications. When a design team marks a work package as "Shared" in the platform, that's not a folder move; it's a state change event broadcast to any registered subscriber. An automated agent can be one such subscriber. The agent doesn't call APIs directly like a script might. This is where the Model Context Protocol (MCP) enters the architecture. MCP is an open standard that defines how an AI-driven reasoning agent discovers, invokes, and combines tools. The agent doesn't contain business logic; it reasons about which tools to call, in what sequence, with what inputs, based on the event it received and its goal. The tools themselves—`validate_loin`, `parse_step`, `write_aim_record`—are functions exposed as MCP tools, each with a typed schema for inputs and outputs. The workflow is event-driven and linear. A platform webhook fires when a work package transitions from WIP (Work In Progress) to Shared, signaling new information is available. The agent receives the webhook payload with the work package ID and the platform endpoint for that data. The agent calls `validate_loin`, passing the endpoint; the tool fetches the PIM JSON payload via REST and runs validation, returning a gap report. If the package includes AP242 geometry, the agent calls `parse_step`, which reads the STEP file and extracts the product tree as JSON. The agent then calls `write_aim_record`, which merges validated PIM attributes with the parsed geometry and writes to the AIM database. Finally, the agent posts the gap report back to the platform via REST, attaching it to the work package as a validation record. Why this architecture is efficient: there's no middleware layer. No overnight batch ETL job. No design software running in the background—no desktop application that must be licensed, open, and manually operated. The entire exchange happens on the data plane: JSON payloads over HTTP, STEP files yielding structured JSON, Pydantic models validating every record, and an agent orchestrating the sequence without human intervention. The agent is the middleware, reasoning about its task rather than following a hardcoded script. ```python # aim_mcp_server.py — Minimal MCP server exposing three tools # validate_loin(payload), parse_step(file_path), write_aim_record(record) # Wired to the functions from prior scripts; runnable with uv run from mcp.server import Server from mcp.types import Tool app = Server("aim-tools") @app.tool() async def validate_loin(payload: dict) -> dict: """Validate PIM payload against LOIN specification.""" # Delegates to pim_loin_validator.validate() ... @app.tool() async def parse_step(file_path: str) -> dict: """Extract AP242 product tree from .stp file.""" # Delegates to step_parser.extract_products() ... @app.tool() async def write_aim_record(record: dict) -> dict: """Merge validated PIM + STEP data and write AIM record.""" # Delegates to aim_model.AssetRecord.from_step_json() ... ``` ```python # aim_agent.py — Async agent loop (~60 lines) # Listens for a CDE webhook event (simulated), orchestrates the MCP # tool sequence, and logs the AIM write confirmation import asyncio async def handle_webhook(event: dict) -> dict: """Process a CDE state-change webhook.""" wp_id = event["work_package_id"] cde_url = event["cde_endpoint"] # 1. Validate PIM against LOIN gap_report = await validate_loin({"url": cde_url}) # 2. Parse AP242 geometry if present step_data = {} if event.get("has_geometry"): step_data = await parse_step(event["stp_path"]) # 3. Write composite AIM record result = await write_aim_record({ "work_package": wp_id, "pim_data": gap_report, "step_data": step_data, }) return {"status": "ok", "aim_id": result["id"]} ``` The sequence diagram shows the full flow: Platform emits a webhook; agent receives it; agent calls `validate_loin`, `parse_step`, and `write_aim_record` in sequence; AIM database updates; gap report posts back to platform. Every arrow is an HTTP call or an MCP tool invocation—no file transfers, no manual steps.
## Event-Driven Information Flow: REST APIs and Agent Orchestration **The Architecture**: Every read and write is an HTTP call. The Common Data Environment is the source of truth—a cloud platform exposing REST endpoints for metadata query, status transition, and webhook subscription. When a design team moves a work package from WIP to Shared in the CDE, that state change event fires a webhook to any registered subscriber. **Agent as Middleware**: The agent does not contain business logic; it contains reasoning about which tools to call, in what order, based on the event it received. The tools—`validate_loin`, `parse_step`, `write_aim_record`—are MCP (Model Context Protocol) functions, each with typed input/output schemas. MCP decouples the reasoning layer (agent) from the execution layer (tools), enabling composable, auditable information flows. **The Flow**: CDE webhook → agent receives work package notification → agent calls `validate_loin` (fetches PIM JSON via REST, runs validation, returns gap report) → agent calls `parse_step` (extracts AP242 product tree) → agent calls `write_aim_record` (merges validated PIM + STEP data, writes composite record to AIM database) → agent posts gap report back to CDE. Zero middleware. Zero batch jobs. Zero desktop software licensing. The entire exchange happens on the data plane: JSON over HTTP, validated at every write, orchestrated by an agent reasoning about its task. **Why This Matters**: There is no "BIM in the loop." No one manually exports, validates, or transfers files. The pipeline is event-driven, asynchronous, and auditable. A three-step agent orchestration replaces the day-long BIM coordination meeting.

[6] Quality Gate — ISO 9001 Meets ISO 19650 Information Delivery Milestones

An Information Delivery Milestone under ISO 19650-2 is a formal checkpoint: a point in the project timeline where information must be delivered, reviewed, and accepted before the next phase of work proceeds. In practice, most organisations implement this as a meeting — a BIM coordination session where someone presents a slide deck summarising model status and the team agrees, often under schedule pressure, that the deliverable is "good enough." The gap between that informal consensus and a rigorous, evidence-based quality gate is where information debt accumulates. ISO 9001 provides the framework to close that gap. Section 7.1.6 requires organisational knowledge — the information necessary for the operation of processes and conformity of products. Section 8.1 requires planned criteria for acceptance. Section 8.6 requires release of products only after planned arrangements have been satisfactorily completed. Read these clauses through the lens of information delivery, and the LOIN specification is the planned criteria, the agent's validation run is the satisfactory completion check, and the timestamped gap report is the objective evidence of conformity. The Pydantic validators in the LOIN specification and AIM schema are the enforcement mechanism. They are not advisory — they do not produce warnings for human review. They raise `ValidationError` exceptions that halt the pipeline. A record missing a mandatory classification code does not enter the AIM with a flag; it is rejected. A maintenance interval encoded as a string instead of an integer does not pass with a type coercion; it fails validation. The schema is the QMS procedure, executed automatically, identically, every time. Every agent run writes a timestamped audit entry: the tool called, the input received, the validation result, the output produced, and the wall-clock time of execution. This is ISO 9001 §8.1 objective evidence, generated without human effort. The audit log is append-only — no record is modified or deleted after creation. Over the life of a project, this log constitutes a complete, machine-readable history of every information quality check performed at every milestone boundary. ```python # audit_log.py — ISO 9001 audit trail decorator # Wraps any agent tool call, writes a timestamped JSON audit entry # to an append-only log file — one function, composable on all tools import json import functools from datetime import datetime, timezone from pathlib import Path AUDIT_LOG = Path("var/logs/audit.jsonl") def audited(func): @functools.wraps(func) async def wrapper(*args, **kwargs): t0 = datetime.now(timezone.utc) try: result = await func(*args, **kwargs) status = "success" except Exception as e: result = {"error": str(e)} status = "failure" raise finally: entry = { "timestamp": t0.isoformat(), "tool": func.__name__, "status": status, "elapsed_ms": ( datetime.now(timezone.utc) - t0 ).total_seconds() * 1000, } AUDIT_LOG.parent.mkdir(parents=True, exist_ok=True) with AUDIT_LOG.open("a") as f: f.write(json.dumps(entry) + "\n") return result return wrapper ``` The line chart tracks LOIN completeness score over successive CDE milestone events across the project timeline — from early design stages through construction and into handover. The upward trajectory is the information maturity curve: the progressive enrichment of the PIM from skeletal geometry to a fully attributed, AIM-ready dataset. Plateaus indicate stalled data entry. Dips indicate regressions — elements losing attributes due to model overwrites or re-exports. Both are signals the agent captures and reports automatically.
## Quality Gates and Audit Trails: Formalized Information Acceptance An Information Delivery Milestone under ISO 19650-2 is a formal checkpoint in the project where information must be delivered, reviewed, and accepted before work proceeds to the next phase. In practice, most organizations implement this as a meeting—a BIM coordination session where someone presents slides about model status and the team agrees, often under schedule pressure, that it's "good enough." The gap between informal consensus and rigorous, evidence-based acceptance is where information debt grows. ISO 9001 provides the framework to close that gap. Section 7.1.6 requires organizational knowledge—the information necessary to operate processes and ensure product conformity. Section 8.1 requires defined acceptance criteria. Section 8.6 requires that products only be released after planned arrangements are satisfactorily completed. Apply these clauses to information delivery: the LOIN specification is the acceptance criterion, the agent's validation run is the satisfactory completion check, and the timestamped gap report is the objective evidence of conformity. The Pydantic validators in the LOIN and AIM schemas are the enforcement mechanism. They don't warn for human review; they raise exceptions that halt the pipeline. A record missing a mandatory classification code doesn't enter the AIM with a flag; it's rejected. A maintenance interval encoded as text instead of a number doesn't pass with automatic conversion; it fails. The schema is the quality procedure, executed identically every time, automatically. Every agent run writes a timestamped audit entry: the tool called, input received, validation result, output produced, and wall-clock execution time. This is ISO 9001 objective evidence, generated without manual effort. The audit log is append-only—no record is modified or deleted after creation. Over a project's life, this log creates a complete, machine-readable history of every information quality check at every milestone. ```python # audit_log.py — ISO 9001 audit trail decorator # Wraps any agent tool call, writes a timestamped JSON audit entry # to an append-only log file — one function, composable on all tools import json import functools from datetime import datetime, timezone from pathlib import Path AUDIT_LOG = Path("var/logs/audit.jsonl") def audited(func): @functools.wraps(func) async def wrapper(*args, **kwargs): t0 = datetime.now(timezone.utc) try: result = await func(*args, **kwargs) status = "success" except Exception as e: result = {"error": str(e)} status = "failure" raise finally: entry = { "timestamp": t0.isoformat(), "tool": func.__name__, "status": status, "elapsed_ms": ( datetime.now(timezone.utc) - t0 ).total_seconds() * 1000, } AUDIT_LOG.parent.mkdir(parents=True, exist_ok=True) with AUDIT_LOG.open("a") as f: f.write(json.dumps(entry) + "\n") return result return wrapper ``` A line chart tracks LOIN completeness across successive platform milestone events over the project timeline—from early design through construction to handover. The upward trend is the information maturity curve: progressive enrichment from skeletal geometry to a fully attributed, operational dataset. Plateaus signal stalled data entry. Dips signal regressions—elements losing attributes due to model overwrites. Both are patterns the agent detects and reports automatically.
## ISO 19650 Meets ISO 9001: Automated Information Quality Governance **The Framework**: An Information Delivery Milestone is a formal checkpoint where information must be delivered, reviewed, and accepted before the next phase proceeds. Formally, this is a meeting with informal consensus. Rigorously, it is a validation run with a timestamped, machine-signed audit trail. ISO 9001 §7.1.6 requires organizational knowledge necessary for process operation. §8.1 requires planned acceptance criteria. §8.6 requires release only after planned arrangements are satisfied. Map these to the AIM: the LOIN specification is the planned criterion; the agent validation run is the satisfactory completion check; the gap report is the objective evidence. **Enforcement Without Human Discretion**: Pydantic validators in the schema are not advisory—they are runtime enforcement. A record missing a mandatory classification code does not enter the AIM with a flag; it fails validation and is rejected. A maintenance interval encoded as a string does not coerce silently; it raises a `ValidationError`. The schema is the procedure, executed identically every time. **Audit Trail as Governance**: Every agent run writes a timestamped entry: tool called, input, validation result, output, elapsed time. No record is modified or deleted after creation. Over a project lifetime, this log is a complete machine-readable history of every information quality check at every milestone. This is ISO 9001 objective evidence, generated without human effort. **The Information Maturity Curve**: A line chart tracking LOIN completeness over successive milestones from early design through handover shows progressive enrichment of the PIM. Plateaus signal stalled data entry. Dips signal regressions. Both are automatically detected and reported, triggering corrective action before project completion.

[7] The Asset as a Living Record — Operational Loop

Handover is not the end of the data story. It is the beginning of a different one. Once the bus stop is operational, the AIM is no longer a static record compiled during construction. It becomes a living document — updated not by design teams and contractors but by sensors, maintenance events, and autonomous monitoring agents. Each AIM component has an optional `sensor_endpoint` field: a URL pointing to a telemetry source. The LED Luminaire's endpoint returns real-time lux readings. The Digital Display's endpoint returns uptime and error state. The Roof Panel's endpoint, if instrumented, returns structural deflection measurements from strain gauges. These sensor streams are the behaviour layer of the digital twin — the third data plane alongside AP242 geometry (shape) and AIM JSON (state). The geometry plane is static and authoritative. The AP242 representation of the bus stop does not change unless the asset is physically modified — a panel replaced, a column extended, a new component added. When a physical change occurs, a new AP242 file is generated from the as-built survey, versioned, and linked to the AIM record. Between physical modifications, the geometry is immutable. The attribute plane updates continuously. Maintenance events — a lamp replacement, a glass cleaning, a display firmware update — are written to the AIM as timestamped entries via REST PATCH calls. Warranty status is recalculated automatically as expiry dates approach. Classification codes are updated if taxonomy revisions occur. These are operational writes, small and frequent, validated by the same Pydantic schema that governed the initial handover. The sensor plane streams continuously. Telemetry data arrives at intervals defined per component — every 60 seconds for a lux sensor, every 300 seconds for a structural monitor, every 3600 seconds for a temperature logger. This data does not live in the AIM directly; it lives in a time-series store. But the AIM holds the threshold values — the acceptable lux range, the maximum deflection, the operating temperature band — and the agent monitors the stream against those thresholds. The agentic maintenance trigger is the operational payoff of the entire pipeline. The sensor monitor agent polls the telemetry endpoint, compares the reading against the AIM threshold field, and when a breach is detected — lux output dropping below the minimum, deflection exceeding the safe limit — it raises a work order via a CMMS API call. No human reviewed the sensor data. No human decided to schedule maintenance. The agent made the decision based on a typed threshold value in a validated AIM record, and it created an auditable action. The loop is closed: PIM defined the asset, AIM structured the operational record, the sensor stream provided the signal, and the agent acted on it. ```python # sensor_monitor.py — Operational sensor agent # Async polling loop that fetches simulated sensor JSON, compares # against AIM threshold fields, and triggers create_work_order() # on breach — the operational agent in its simplest form import asyncio import httpx async def monitor_component( component_id: str, sensor_url: str, threshold_min: float, threshold_max: float, poll_interval: int = 60, ): async with httpx.AsyncClient() as client: while True: resp = await client.get(sensor_url) reading = resp.json()["value"] if reading < threshold_min or reading > threshold_max: await create_work_order( component_id=component_id, reading=reading, threshold=(threshold_min, threshold_max), reason="threshold_breach", ) await asyncio.sleep(poll_interval) ``` The time-series chart plots the LED luminaire's lux reading over 30 days, with the AIM threshold line overlaid. The moment the reading crosses below the threshold is the moment the agent fires a work order. The chart is the visual proof of an automated decision — a decision that in a traditional FM operation would have required a scheduled inspection, a technician's visit, a subjective judgement, and a manually raised ticket.
## After Handover: The Living Asset and Continuous Monitoring Handover isn't the end of the data story; it's the beginning of a different one. Once the bus stop is operational, the AIM transitions from a static construction record to a living document—updated not by designers and contractors but by sensors, maintenance events, and autonomous monitoring systems. Each AIM component has an optional `sensor_endpoint` field: a URL pointing to a real-time data source. The LED Luminaire's endpoint returns live brightness readings. The Digital Display's endpoint returns uptime and error status. The Roof Panel's endpoint, if instrumented with strain gauges, returns structural deflection. These sensor streams are the behaviour layer of the digital twin—the third data plane alongside AP242 geometry (shape) and AIM JSON (state). The geometry layer is static and authoritative. The AP242 STEP representation doesn't change unless the asset is physically modified—a panel replaced, a column extended, a new component installed. When physical changes occur, a new STEP file is generated from an as-built survey, versioned, and linked to the AIM. Between modifications, geometry is immutable. The attribute layer updates continuously. Maintenance events—lamp replacement, glass cleaning, firmware updates—are recorded in the AIM as timestamped entries via web API PATCH calls. Warranty status recalculates automatically as expiry dates approach. Classification codes update if taxonomy revisions occur. These are operational writes, small and frequent, validated by the same Pydantic schema that governed handover. The sensor layer streams continuously. Telemetry arrives at intervals per component—every 60 seconds for brightness, every 300 seconds for structural deflection, every 3600 seconds for temperature. This raw data doesn't live in the AIM directly; it lives in a time-series database. But the AIM holds the safe operating thresholds—acceptable brightness range, maximum deflection, operating temperature band—and an agent monitors the stream against those thresholds. The agentic maintenance trigger is the operational payoff. The sensor monitor agent polls the telemetry endpoint, compares the reading against the AIM threshold, and when a breach is detected—brightness below minimum, deflection exceeding safe limit—it creates a work order via a CMMS (Computerized Maintenance Management System) API. No human reviewed the sensor data. No human decided to schedule maintenance. The agent made the decision based on a typed threshold in a validated AIM record and created an auditable action. The loop closes: PIM defined the asset, AIM structured the operational record, sensors provided the signal, and the agent acted. ```python # sensor_monitor.py — Operational sensor agent # Async polling loop that fetches simulated sensor JSON, compares # against AIM threshold fields, and triggers create_work_order() # on breach — the operational agent in its simplest form import asyncio import httpx async def monitor_component( component_id: str, sensor_url: str, threshold_min: float, threshold_max: float, poll_interval: int = 60, ): async with httpx.AsyncClient() as client: while True: resp = await client.get(sensor_url) reading = resp.json()["value"] if reading < threshold_min or reading > threshold_max: await create_work_order( component_id=component_id, reading=reading, threshold=(threshold_min, threshold_max), reason="threshold_breach", ) await asyncio.sleep(poll_interval) ``` A time-series chart plots the LED luminaire's brightness reading over 30 days with the AIM threshold line overlaid. The moment the reading crosses below threshold is when the agent fires a work order. The chart is visual proof of an automated decision—a decision that in traditional facilities management would have required a scheduled inspection, a technician's visit, subjective judgment, and manual ticket creation.
## Beyond Handover: The Living Asset Loop **Handover as a Beginning**: Once operational, the AIM is not static—it becomes a living document updated by sensors, maintenance events, and autonomous agents, not by design teams. **Three Data Planes in Continuous Operation**: - **Geometry Plane** (Static, Authoritative): AP242 STEP representation immutable unless asset is physically modified. New as-built survey → new STEP file → linked to AIM record with version control. - **Attribute Plane** (Continuous Updates): Maintenance events, warranty recalculations, classification updates, threshold changes. Small frequent writes validated by the same Pydantic schema that governed handover. - **Sensor Plane** (Continuous Streaming): LED luminaire lux, digital display uptime, structural deflection, temperature. Data lives in time-series store; AIM holds threshold values. Agent monitors streams against thresholds. **The Agentic Trigger**: Sensor monitor agent polls telemetry endpoint, compares reading against AIM threshold field. When threshold is breached—lux below minimum, deflection exceeds limit—agent creates work order via CMMS API. No human reviewed the data. No human scheduled maintenance. The agent decided based on a typed threshold value in a validated AIM record and created an auditable action. The loop closes: PIM defined the asset, AIM structured the operational record, sensor stream provided the signal, agent acted on it. **The Operational Payoff**: Threshold-based work orders replace scheduled inspections, technician visits, and manual tickets. Emergency maintenance becomes predictive maintenance. Asset downtime drops; lifecycle costs are optimized. The digital twin—precise composition of shape, state, and behavior—drives continuous operational improvement, not once-a-quarter reporting meetings.

[8] Closing — Information Requirements Are Code

The PIM-to-AIM journey, reframed through this article, is not a BIM workflow. It is a typed, validated, version-controlled data pipeline — the same discipline that software engineering has practiced for decades. The information requirements document becomes a Pydantic schema. The handover package becomes an API response. The BIM coordination meeting becomes an automated validation run with a timestamped audit log. The facilities management spreadsheet becomes a queryable database with sensor-bound threshold fields. The "digital twin" — a term often used loosely enough to mean anything — becomes a precise composition of three data planes: AP242 for shape, JSON for state, and a sensor stream for behaviour. Each tool in this pipeline does one thing well. AP242 STEP carries precise geometry and product structure without bloating the exchange with operational attributes it was never designed to hold. JSON over REST carries attributes — classifications, specifications, schedules, thresholds — in a format that every programming language, every database, and every API gateway can consume natively. MCP provides the agent-to-tool interface, decoupling the reasoning layer (the agent) from the execution layer (the tools). Pydantic enforces schema contracts at runtime, turning documentation into validation. ISO 19650 provides the governance framework — the information management standard that defines what must be delivered, when, and to what specification. ISO 9001 provides the quality framework — the audit trail, the acceptance criteria, the objective evidence. The call to practitioners is blunt: if your handover deliverable is a PDF, you have a technical debt problem, not a BIM problem. A PDF is a rendered snapshot of data that was once structured. It cannot be queried. It cannot be validated. It cannot trigger a maintenance work order when a sensor reading crosses a threshold. It is the information equivalent of printing a database and filing it in a cabinet. The asset deserves better. The data pipeline described here — PIM as a validated contract, AP242 for geometry, JSON for attributes, MCP for orchestration, Pydantic for enforcement, REST for exchange — is not a theoretical ambition. Every component exists, is open, and runs today. The asset is not a building. The asset is a living, queryable record. Treat it accordingly.
## Conclusion: The Asset as a Queryable System The PIM-to-AIM journey, reframed here, isn't a BIM workflow. It's a typed, validated, versioned data pipeline—the same discipline software engineers have practiced for decades. The information requirements document becomes a Pydantic schema. The handover package becomes an API response. The BIM coordination meeting becomes an automated validation run with timestamped audit logs. The facilities management spreadsheet becomes a queryable database with sensor-linked thresholds. The "digital twin"—a term often used so loosely it means almost anything—becomes a precise composition of three data planes: AP242 for shape, JSON for state, and a sensor stream for behaviour. Each tool does one thing well. AP242 STEP carries precise geometry and product structure without bloating the exchange with operational attributes it was never designed to hold. JSON over REST carries attributes—classifications, specifications, schedules, thresholds—in formats every programming language, every database, and every API can consume natively. MCP provides the agent-to-tool interface, decoupling reasoning (the agent) from execution (the tools). Pydantic enforces schema contracts at runtime, turning documentation into validation. ISO 19650 provides the governance framework—the standard defining what must be delivered, when, and to what specification. ISO 9001 provides the quality framework—the audit trail, acceptance criteria, and objective evidence. The call to practitioners is direct: if your handover deliverable is a PDF, you have a data pipeline problem, not a BIM problem. A PDF is a rendered snapshot of data that was once structured. It cannot be queried. It cannot be validated. It cannot trigger a maintenance work order when a sensor reading crosses a threshold. It's the information equivalent of printing a database and filing it in a cabinet. The asset deserves better. The data pipeline described here—PIM as a validated contract, AP242 for geometry, JSON for attributes, MCP for orchestration, Pydantic for enforcement, REST for exchange—is not a future ambition. Every component exists today, is open-source, and runs now. The asset isn't a building or a structure. The asset is a living, queryable record. Treat it accordingly.
Key Takeaways
- Information delivery is a data pipeline problem, not a file migration problem; separate concerns into three planes: AP242 STEP for geometry, JSON over REST for operational attributes, and sensor streams for behaviour. - ISO 19650 information requirements should be encoded as executable validation schemas (Pydantic models), not documents, turning handover milestones into automated quality gates with audit trails. - Agentic workflows orchestrated via MCP tools eliminate manual BIM coordination meetings; agents validate completeness, parse geometry, merge data, and trigger maintenance work orders based on sensor thresholds without human intervention. - Facilities management attributes (classification codes, maintenance intervals, warranty dates, sensor endpoints) belong in a queryable AIM database, not locked in proprietary CAD files or PDFs. - The asset lifecycle moves from static PIM (project accumulation) through validated AIM handover to a living operational record updated by maintenance events and sensor telemetry, with every state change auditable under ISO 9001. **SUMMARY** Built environment assets handoff should be redesigned as a typed, validated REST API contract rather than a file transfer; separate geometry (AP242 STEP), attributes (JSON), and telemetry (sensor streams) into composable data planes managed by agentic workflows. Information requirements encoded as Pydantic schemas enable automated LOIN validation at project milestones, eliminating manual coordination meetings and producing ISO 9001 audit evidence. Once operational, the Asset Information Model becomes a queryable, sensor-bound record where agents automatically trigger maintenance work orders when thresholds breach, closing the loop from design intent to autonomous operations.