| name | infrahub-managing-schemas |
| description | Creates, validates, formats, and modifies Infrahub schema YAML files — nodes, generics, attributes, relationships, and extensions. Also checks the Infrahub Marketplace for an existing published schema to reuse before modelling a domain from scratch. TRIGGER when: designing data models, adding schema nodes, validating schema definitions, planning schema migrations, looking for an existing/off-the-shelf schema or checking the marketplace for a domain (DCIM, location, routing, etc.), modeling file objects / attachments / uploads (storing PDFs, diagrams, images, certificates, documents as Infrahub objects), formatting or tidying schema files, normalising / canonicalising schema key order, cleaning up noisy schema diffs where every edit reshuffles keys, or running `infrahubctl schema format` (including as a CI gate). DO NOT TRIGGER when: populating data objects, writing checks/generators/transforms, querying live data. |
| allowed-tools | ["Read","Write","Edit","Bash"] |
| argument-hint | [namespace] [node-names...] |
| metadata | {"version":"1.2.8","author":"OpsMill"} |
Infrahub Schema Creator
Overview
Expert guidance for designing and building Infrahub
schemas. Schemas are YAML files defining nodes (concrete
types), generics (abstract base types), attributes,
relationships, and extensions.
Project Context
Existing schemas in this project:
!find . -name "*.yml" -path "*/schemas/*" -o -name "*schema*" -name "*.yml" 2>/dev/null | head -20
Infrahub config (if present):
!cat .infrahub.yml 2>/dev/null || echo "No .infrahub.yml found"
If invoked with arguments (e.g., /infrahub:managing-schemas Ipam Vlan VlanGroup),
use the first argument as the namespace and remaining arguments as node names.
When to Use
- Designing new data models or schema nodes
- Adding attributes or relationships to existing schemas
- Setting up hierarchical location trees or component/parent patterns
- Configuring display properties (human_friendly_id, display_label)
- Migrating or refactoring existing schemas
- Debugging schema validation errors
Rule Categories
| Priority | Category | Prefix | Description |
|---|
| CRITICAL | Branch-First Changes | workflow- | Load schema onto a branch, not the default branch |
| CRITICAL | Naming | naming- | Namespace, node, attribute naming |
| CRITICAL | Relationships | relationship- | IDs, peers, component/parent, on_delete |
| HIGH | Attributes | attribute- | Defaults, dropdowns, computed Jinja2, branch-agnostic, deprecated |
| HIGH | Hierarchy | hierarchy- | Hierarchical generics, parent/children |
| HIGH | Display | display- | human_friendly_id, order_weight, menu placement |
| MEDIUM | Extensions | extension- | Cross-file via extensions block, artifact targets |
| MEDIUM | Uniqueness | uniqueness- | Constraint format, __value suffix |
| MEDIUM | Migration | migration- | Add/remove attributes, state: absent |
| MEDIUM | File Formatting | format- | Canonical key order; infrahubctl schema format (offline) |
| HIGH | Validation | validation- | Load-time string-length caps (description / label / identifier), common error messages, pre-check checklist |
Schema File Basics
---
version: "1.0"
generics:
- ...
nodes:
- ...
extensions:
nodes:
- ...
Always include the $schema comment for IDE validation.
Only version is required at the top level.
Designing for Downstream Consumers
A schema node rarely lives alone. Before finalizing it,
walk through how it will be used by other parts of the
project and add the inheritance / configuration that
those features require:
This audit is the difference between a schema that
"validates" and one that "actually works in the broader
project." Skipping it forces a schema migration once the
downstream feature is wired up — at which point the data
is already loaded.
When the task spans multiple skills (schemas + transforms,
schemas + menus, etc.), load both skills' rules together
rather than treating the boundaries as exclusive.
Design for the cheaper layer
A schema choice can remove the need for Python or
denormalized data downstream. The schema is the cheapest
place to get this right — fixing it later means a
migration on already-loaded data. Before adding a field or
node, check whether a built-in or structural feature
already covers it:
| Signal | Cheaper layer | See rule |
|---|
| Building any domain from scratch (the marketplace publishes far more than DCIM / location / org — routing, security, compute, and many more) | Search the whole marketplace and reuse a published schema: infrahubctl marketplace get <ns>/<name> then inherit_from | yagni-reuse-existing-marketplace-schema |
Copying a value onto a node that's reachable by traversing a relationship (region_code when device.location.region.code exists) | An indirect relationship traversal; let consumers follow the link | yagni-denormalized-vs-indirect-relationship |
| Several sibling nodes repeating the same attributes and relationships | Extract a generic and inherit_from it | yagni-duplicate-shape-not-extracted-to-generic |
| Defining custom IP address / prefix / VLAN nodes | inherit_from the built-in primitive (BuiltinIPAddress, BuiltinIPPrefix, IpamVLAN) | yagni-custom-domain-primitives-instead-of-builtin |
An Attribute + cardinality: one relationship with no inverse on the peer | Declare the matching inverse so consumers filter in the query, not in Python | yagni-missing-inverse-forces-python-filter |
| A Profile carrying a single value that never varies across objects | An attribute default_value — a Profile only earns its cost when values vary or are re-tuned centrally | yagni-profile-over-default |
|
These are the schema-side counterparts to the "Before
writing Python" guidance in the checks, transforms, and
generators skills. The repo auditor flags them as advisory
cost-to-fix findings; catching them at design time avoids
both the finding and the later migration.
Workflow
Follow these steps when creating or modifying a schema:
- Gather requirements — Identify the node types,
their attributes, and how they relate to each other.
Ask about hierarchies, dropdowns, and display needs.
- Check the marketplace first — Before modelling
any domain from scratch, search the whole Infrahub
Marketplace and reuse a published schema when one
covers it:
infrahubctl marketplace get <namespace>/<name>, then inherit_from the pulled
generics and add only site-specific attributes.
Discovery, collections (-c), the airgap fallback,
and the required SDK version live in
../infrahub-common/marketplace-reference.md.
- Read relevant rules — Read
rules/naming-conventions.md
for naming constraints,
rules/attribute-defaults-and-types.md
for attribute kinds and defaults, and
rules/relationship-identifiers.md
for bidirectional relationship setup.
- Build the schema YAML — Start with the
$schema
comment and version: "1.0". Define generics first
(if any), then nodes. Apply naming, display, and
relationship rules from step 3.
- Audit downstream consumers — Walk the table in
"Designing for Downstream Consumers" above. If any
node will become an artifact or generator target, add
CoreArtifactTarget to its inherit_from now, per
rules/extension-artifact-target.md.
Adding it later forces a schema migration on loaded data.
- Configure display properties — Set
human_friendly_id, display_label, and
order_weight per
rules/display-human-friendly-id.md
and rules/display-order-weight.md.
- Format the file — Put the keys in the canonical
order before committing so diffs stay small. Run
when your
provides it (offline, no server); otherwise author the
order by hand. See
.
Production Patterns Worth Knowing
Seven recurring patterns — computed Jinja2 attributes,
cascade-vs-no-action deletes, menu visibility,
branch-agnostic identity, artifact targets, object
templates, and file objects — are documented at the top
of examples.md. Read those before
finalizing a schema; each pattern is easy to miss
when building from scratch and expensive to retrofit
after data is loaded.
Supporting References