Author and validate Neo4j Ontology Graph Specification (ontology graph spec) documents. Use when writing or editing an ontology, defining nodes and relationships with properties, Neo4jType data types, constraints (key/unique/must_exist), labels, and endpoint cardinality, in YAML or JSON, or validating an ontology document against the live-resolved spec schema. Does NOT handle Cypher or loading an ontology into a database — use neo4j-cypher-skill. Does NOT cover generic graph data modeling advice — use neo4j-modeling-skill.
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
neo4j-cypher-skill (ontology Cypher procedures do not exist yet — later work there)neo4j-modeling-skillIdentify what is being modeled: entity types (nodes), connections (relationships + direction), properties per element, identifying keys, mandatory fields, cardinality. If the domain or required shape is unclear, ask the user what is being modeled and which questions the ontology must answer. Do NOT guess a domain.
YAML or JSON per user preference; default YAML (more readable). Apply the Core Facts below. Load references/format-reference.md when anything beyond the minimal example is needed (full labels object, constraint objects, extensions, full data-type grammar).
# From the skill directory:
uv run scripts/validate.py <document.{yaml,yml,json}>
# From the repo root:
uv run neo4j-ontology-skill/scripts/validate.py <document.{yaml,yml,json}>Exit 0 = valid · exit 1 = schema violations (one line per field path) · exit 2 = parse/read/fetch error. PEP 723 script — uv resolves deps (jsonschema, pyyaml) itself.
The validator fetches the schema live — nothing is vendored. Resolution order: --schema <path-or-url> (explicit, no fallback) → the document's own schema field when it is a URL → the published current alias → transitional repo raw fallback. The document's schema URL decides which version it validates against: set it to the published versioned URL of the version being authored (older versions validate against their published schema).
Fix every reported error; re-run Step 3. Repeat until exit 0. Validation is MANDATORY — never present an ontology as done with a non-zero exit.
schema, id (unique ontology id string), version (STRING — user-defined revision label; quote it in YAML: version: "1"). Root rejects unknown fields (additionalProperties: false).schema value: the published URL of the version being authored, e.g. https://neo4j.com/docs/ontology-graph-spec/1.0.0/schema.json. Root key is plain schema, NOT $schema.nodes / relationships are maps keyed by LOCAL IDS, not labels/types. Label lives in label or labels.identifier; relationship type lives in type. Endpoints reference node ids (from.node / to.node) — label renames never break references.label: X is shorthand for labels: {identifier: X}. Use the full labels object only when implied or optional labels exist.STRING, INTEGER, FLOAT, BOOLEAN, DATE, DURATION, POINT, UUID; temporal tokens contain a space (ZONED DATETIME, LOCAL TIME); parameterized tokens use angle brackets (LIST<STRING>, VECTOR<FLOAT32>). UUID and VECTOR<...> have no LIST arm. No unions, no nested lists. dimension (integer|null) sits on the property, paired with VECTOR types.key: true, unique: true, must_exist: true (snake_case — NOT mustExist). Single-property shorthands; key = unique + exists per Neo4j key-constraint semantics.constraints is a MAP id → constraint object {type: EXISTS|KEY|PROPERTY_TYPE|UNIQUE, properties: [p1, ...], name: optional} — required for composites (≥ 2 properties) and nameable constraints. properties must name properties declared on the SAME element.count exact, or min_count/max_count ranged; absent = unconstrained (0..*).extensions shape per element — node: indexes/display/custom; relationship: indexes/custom; root: tables/mappings/custom; labels/property/constraint/index: custom only. Unknown extension keys rejected. custom is free-form — arbitrary owner data, never validated by the spec schema.properties: {}, aliases: [], custom: {}); omit them.library.ontology.yaml — 2 nodes, 1 relationship:
schema: "https://neo4j.com/docs/ontology-graph-spec/1.0.0/schema.json"
id: library
version: "1"
name: Library
nodes:
author:
label: Author
properties:
id: { type: STRING, key: true }
name: { type: STRING, must_exist: true }
book:
label: Book
properties:
isbn: { type: STRING, key: true }
relationships:
wrote:
type: WROTE
from: { node: author, max_count: 1 }
to: { node: book }Validates exit 0 via scripts/validate.py. Full YAML+JSON worked examples in references/format-reference.md.
Load on demand:
labels object, constraint objects, extension shapes, data-type grammar, gotchas, YAML+JSON exampleshttps://neo4j.com/docs/ontology-graph-spec/ — immutable /<version>/schema.json per spec version, moving alias /current/schema.jsonPublished: the ONT-31 URLs above are live and are the canonical schema source. If the published host is unreachable, the validator falls back to the raw schema from neo4j/ontology-graph-spec main (moving). Ontology Cypher procedures do not exist yet; applying an ontology to a database is out of scope here.
schema, id, version present; version a quoted string; schema = the published versioned URL under plain schema key$schemanodes/relationships keyed by local ids; relationship from/to reference node idslabel or labels.identifierdimension on the property with VECTOR typestype ∈ EXISTS/KEY/PROPERTY_TYPE/UNIQUE) for composites/named; constraint properties exist on the same elementcustomuv run scripts/validate.py <file> exits 0 (every reported error fixed and re-validated)neo4j-contrib/neo4j-skills
39247b9
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.