Infrahub Check Creator
SkillDev toolsCreates Infrahub check definitions — Python validation logic, GraphQL queries, and YAML-driven tests for proposed change pipelines. TRIGGER when: writing validation checks, creating Python checks, building data quality guards for proposed changes, writing or running tests for a check. DO NOT TRIGGER when: designing schemas, querying live data, building transforms or generators.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Infrahub Check Creator skill
What this skill tells your AI
The instructions your AI receives, as published by opsmill/infrahub-skills in skills/infrahub-managing-checks/SKILL.md and read by ahel’s review.
Overview
Expert guidance for creating Infrahub checks. Checks are user-defined validation logic (Python + GraphQL) that run as part of a proposed change pipeline. If a check logs any errors, the proposed change cannot be merged.
Project Context
Infrahub config:
!cat .infrahub.yml 2>/dev/null || echo "No .infrahub.yml found"
Existing checks:
!find . -name "*.py" -path "*/checks/*" 2>/dev/null | head -20
Existing queries:
!find . -name "*.gql" -path "*/queries/*" 2>/dev/null | head -20
When to Use
- Writing validation logic for proposed changes
- Creating data quality guards (e.g., rack collision detection)
- Building global checks that validate all objects of a type
- Building targeted checks that validate specific grouped objects
- Debugging check failures or understanding the check lifecycle
Rule Categories
| Priority | Category | Prefix | Description |
|---|---|---|---|
| CRITICAL | Architecture | architecture- | Three components, global vs targeted, execution flow |
| CRITICAL | Python Class | python- | InfrahubCheck base class, validate(), log_error/log_info |
| HIGH | API Reference | api- | Class attributes, instance properties, methods, lifecycle, and which API surfaces a rejection (a GraphQL error is a 200) |
| HIGH | Registration | registration- | .infrahub.yml config, query name matching, parameters |
MEDIUM (HIGH for patterns-shared-module) | Patterns | patterns- | Error collection, shared utilities, scoped validation, relationship-traversal validation, sharing a module across artifact types |
| HIGH | Testing | testing- | Resources Testing Framework (YAML-driven tests), infrahubctl check commands |
Schema Features This Skill Depends On
A check is only useful if it can fetch and validate the right data. Most check failures at deploy time are actually schema-side gaps:
| If the check... | The schema (or .infrahub.yml) must... | See |
|---|---|---|
| Reads an attribute via GraphQL | Expose it on the schema node with the same name (name__value-shaped paths) | ../infrahub-managing-schemas/rules/attribute-defaults-and-types.md |
| Walks a relationship to validate related objects | Have both sides of the relationship defined with matching identifiers; otherwise the traversal returns nothing | ../infrahub-managing-schemas/rules/relationship-identifiers.md |
| Validates a node against a related node's state (child vs parent lifecycle, peer consistency) | Fetch the related node's comparison attribute in the query by traversing the relationship; a check runs one query with no lazy fetch | rules/patterns-relationship-traversal.md |
| Is targeted (per-object) | Register a CoreStandardGroup as targets: in .infrahub.yml and map parameters: to bind GraphQL variables | rules/registration-config.md |
| Needs the GraphQL response keyed to typed nodes | Select id and __typename in the query — the SDK relies on both | ../infrahub-common/graphql-queries.md |
| Should never block a merge but only annotate | Use self.log_info() instead of log_error(); log_warning() does not exist | rules/python-validate.md |
Before writing Python
If a cheaper layer can express the constraint, use it.
A schema constraint runs at load time on every write
path; a Python check runs only inside the proposed-
change pipeline, so bad data created via other paths
slips through. Walk this short ladder before reaching
for InfrahubCheck:
| Signal | Cheaper layer | See rule |
|---|---|---|
| Validating uniqueness, presence, allowed values, or regex on a single attribute | Schema constraint (uniqueness_constraints, optional: false, kind: Dropdown choices, regex) | yagni-python-validator-vs-schema-constraint |
Check whose body is a GraphQL query plus a single if len(...) > 0: raise | One .gql file plus 5 lines of Python | yagni-redundant-check-that-graphql-can-answer |
| Enforcing that a relationship is single-peered or non-optional | Schema cardinality: one, kind: Parent / Component, optional: false | yagni-python-validator-vs-schema-constraint |
Only when none of these apply should you write a Python check. The cross-node business rules, out-of-band reconciliations, and stateful assertions in rules/python-validate.md are the legitimate use cases.
When the check reads objects through the SDK (rather than only its GraphQL
query), type those calls with generated protocol classes rather than string
kinds — client.get(DcimDevice, ...), not kind="DcimDevice". Match the
--sync protocol variant to the check's client. See
protocols-adopt-typed-kinds.
Check Basics
Every check has three components:
- GraphQL query (
.gqlfile) -- fetches the data to validate, and is registered under the top-levelqueries:section of.infrahub.yml - Python class -- inherits from
InfrahubCheck, setsquery = "<query_name>", implementsvalidate() - Configuration -- declared in
.infrahub.ymlundercheck_definitions(which does not take aquery:field — see below)
from infrahub_sdk.checks import InfrahubCheck
class MyCheck(InfrahubCheck):
query = "my_query" # Must match queries[].name in .infrahub.yml
def validate(self, data: dict) -> None:
# Validation logic here
if something_is_wrong:
self.log_error(
message="Problem description"
)
Where the query is bound: the Python class (
query = "..."), notcheck_definitions. The repository config model usesextra="forbid", so puttingquery:undercheck_definitions:makes the whole repo config fail validation. This is the #1 confusion vs.generator_definitions:, which does take a top-levelquery:. See rules/registration-config.md.
Workflow
Follow these steps when creating a check:
- Understand the validation goal — What data condition should block a proposed change? Determine whether this is a global check (all objects of a type) or targeted (specific group). Read rules/architecture-types.md.
- Write the GraphQL query — Create a
.gqlfile that fetches the data to validate. Read ../infrahub-common/graphql-queries.md for query patterns. If the rule compares a node against a related node's state (child vs parent lifecycle, peer consistency), the query must fetch that related attribute by traversing the relationship now — a check runs one query with no later fetch. See rules/patterns-relationship-traversal.md. - Implement the Python class — Inherit from
InfrahubCheck, implementvalidate(). Read rules/python-validate.md for the class pattern and rules/api-reference.md for available methods. If the check calls back into Infrahub, read rules/api-error-surfaces.md too: a rejected GraphQL request still returns HTTP 200, so branching on a status code makes the check pass on the failure it exists to catch. If the logic is shared with a generator or a transform, read rules/patterns-shared-module.md before reaching for a relative import. - Register in .infrahub.yml — Add the check under
check_definitions. The query name must match the Python classqueryattribute. See rules/registration-config.md. - Add tests — Create YAML-driven test definitions (smoke, unit, integration) alongside the check so it is validated automatically in the proposed change pipeline. Read rules/testing-resource-framework.md.
- Test locally — Run
infrahubctl checkto validate against a feature branch. See rules/testing-commands.md.
Supporting References
- reference.md -- Class API,
log_error/log_info (no log_warning), lifecycle,
.infrahub.ymlregistration (with the no-query:shape that differs from generator_definitions) - examples.md -- Complete check patterns (global, targeted, minimal)
- ../infrahub-common/graphql-queries.md -- GraphQL query writing reference
- ../infrahub-common/infrahub-yml-reference.md -- .infrahub.yml project configuration
- ../infrahub-common/rules/ -- Shared rules (git integration, caching gotchas) that apply across all skills
- ../infrahub-common/rules/workflow-information-priority.md
-- Skill content first; how to consult
docs.infrahub.appon a genuine gap (e.g. deleting nodes) - ../infrahub-managing-schemas/SKILL.md -- Schema definitions checks validate against
- rules/ -- Individual rules organized by category prefix
Signals
- GitHub stars
- 26
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
infrahub-managing-checks- Source
- github.com/opsmill/infrahub-skills