Omnigraph
Schema

Constraints

Schema annotations enforce data validity and control index creation.

Constraints and annotations in a .pg schema control what data is allowed and how it is indexed. They come in four forms: property annotations, type annotations, body constraints, and edge cardinality.

Property annotations

These appear after the type on the same line as a property.

@key

Marks a property as the stable external identity of the node type.

node Person {
    name: String @key
}
  • At most one @key per node type.
  • The property must be required (not nullable).
  • Key values are immutable after creation.
  • Implies @index — no need to add both.

@unique

Ensures no two rows share the same value in this column.

node Account {
    email: String @unique
}

@index

Creates a BTree index for fast lookups, range scans, and sort operations.

node Event {
    timestamp: DateTime @index
}

For Vector(N) properties, @index creates an ivf_flat vector index with the L2 distance metric, used by nearest() queries.

@embed

Marks a Vector(N) property for automatic embedding from a named text source:

node Document {
    body:      String
    embedding: Vector(1536) @embed(body)
}

The source property must be a String.

@description("...")

A human-readable description of the property, surfaced in tooling:

node Task {
    status: enum(pending, done) @description("Current lifecycle state.")
}

Property annotations summary

AnnotationApplies toPurpose
@keyAny required scalarStable identity, implies index
@uniqueAny scalarNo duplicate values
@indexAny scalar or vectorBTree index (scalar) or ivf_flat vector index (vector)
@embed(prop)Vector(N)Auto-embed from a named text source
@description("...")Any propertyDocumentation

Type annotations

These appear on a node or edge header, after the type name and before the body.

@description("...")

Documents the type itself:

node Task @description("Tracked work item") {
    slug: String @key
}

@instruction("...")

Prompt-level guidance for agent systems that read the schema. This is valid on node and edge types, not on individual properties.

edge DependsOn: Task -> Task @instruction("Use only for hard blockers")

@rename_from("...")

Migration hint used by omnigraph schema plan to match a renamed node, edge, or property to an accepted schema:

node Account @rename_from("User") {
    full_name: String @rename_from("name")
}

edge ConnectedTo: Account -> Account @rename_from("Knows")

Type annotations summary

AnnotationApplies toPurpose
@description("...")Node, EdgeDocumentation
@instruction("...")Node, EdgeAgent guidance
@rename_from("...")Node, Edge, PropertySchema migration rename hint

Body constraints

These appear on their own line inside a node or edge block, after the property declarations.

@range(prop, min..max)

Restricts a numeric property to a closed range. Checked at load and mutation time.

node Score {
    value: F64
    @range(value, 0.0..100.0)
}

@check(prop, regex)

Validates a string property against a regular expression.

node Account {
    slug: String @key
    @check(slug, "^[a-z0-9\\-]+$")
}

@unique(p1, p2, ...)

Composite uniqueness constraint across multiple properties.

node Reading {
    sensor_id: String
    timestamp: DateTime
    value:     F64

    @unique(sensor_id, timestamp)
}

@index(p1, p2, ...)

Composite BTree index across multiple properties.

node Event {
    category:  String
    timestamp: DateTime

    @index(category, timestamp)
}

Body constraints summary

ConstraintScopePurpose
@range(prop, min..max)NodeNumeric range validation
@check(prop, regex)NodeString regex validation
@unique(p1, p2, ...)Node, EdgeComposite uniqueness
@index(p1, p2, ...)Node, EdgeComposite BTree index

Edge cardinality

@card(n..m) is part of the edge declaration header, not a body constraint:

edge ManagedBy: Employee -> Manager @card(1..1)

It limits how many edges of that type can originate from a single source node.

PatternMeaning
@card(1..1)Exactly one.
@card(0..1)At most one.
@card(1..)At least one.
@card(0..)No constraint (default).

Constraint evaluation order

All constraints are evaluated during data ingestion (omnigraph load) and mutations (omnigraph change). If any constraint fails, the entire operation is rejected and no data is written. The schema compiler also validates that constraint references (property names, types) are consistent at compile time.

On this page