Omnigraph
Schema

Constraints

Schema annotations enforce data validity and control index creation.

Constraints are declared inside a .pg schema to control what data is allowed and how it is indexed. They come in two forms: property annotations that appear inline on a property declaration, and body constraints that appear on their own line inside a node or edge block.

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-HNSW index for approximate nearest-neighbor search instead.

@embed

Marks a Vector(N) property for automatic embedding. Optionally specify the text source:

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

Without source, the vector must be provided directly at load time.

@description("...")

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

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

@instruction("...")

Prompt-level guidance for agent systems that read the schema:

node Task {
    priority: I32 @instruction("Use 1 for critical, 2 for high, 3 for normal.")
}

Property annotations summary

AnnotationApplies toPurpose
@keyAny required scalarStable identity, implies index
@uniqueAny scalarNo duplicate values
@indexAny scalar or vectorBTree index (scalar) or IVF-HNSW (vector)
@embedVector(N)Auto-embed from text source
@description("...")Any propertyDocumentation
@instruction("...")Any propertyAgent prompt guidance

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)
}

@card(n..m)

Cardinality constraint on an edge type. Limits how many edges of this type can originate from a single source node.

edge ManagedBy: Employee -> Manager {
    @card(1..1)
}
PatternMeaning
@card(1..1)Exactly one.
@card(0..1)At most one.
@card(1..)At least one.
@card(0..)No constraint (default).

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
@card(n..m)EdgeCardinality limit

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