Skip to main content

Rune Contract

Gridheim Runes are generated, deterministic calculated fields owned by the ValkyrAI OpenAPI and ThorAPI integration layer.

A Gridheim Rune is not a persisted value, a hand-written Spring service, a controller endpoint, a memory client, or a SWARM participant. It is a formula expression stored as an OpenAPI extension on a component property. ThorAPI emits that formula onto the generated Java model field as @Rune, and ValkyrAI evaluates the value in real time.

The server runtime lives in com.valkyrlabs.valkyrai.runes and evaluates through OpenXLS by projecting model properties into workbook named ranges. com.valkyrlabs.gridheim.core.Rune remains as a deprecated compatibility annotation for older generated sources and delegates to the same evaluator.

Canonical Path

  1. A schema property declares an x-gridheim-rune formula.
  2. ThorAPI code generation emits the generated model field with @com.valkyrlabs.valkyrai.runes.Rune.
  3. The generated object carries the formula inline with the model contract.
  4. ValkyrAI intercepts reads of the annotated field with RuneAspect.
  5. RuneValidationService validates formula references against fields, getters, and collection element types on the model class.
  6. RuneContextBuilder resolves the model instance into formula values, including nested dot paths and collection projections.
  7. RuneEvaluationService projects model values into OpenXLS named ranges, evaluates the formula, and adapts the result to the Java field type.

Example

SalesOrder:
type: object
properties:
lineItems:
type: array
items:
$ref: "#/components/schemas/SalesOrderLineItem"
subtotal:
x-gridheim-rune: =SUM(lineItems.extendedAmount)
type: number
format: double
description: Calculated subtotal across line items
total:
x-gridheim-rune: =subtotal + tax + shipping
type: number
format: double
description: Calculated order total

ThorAPI should generate a Java field equivalent to:

@Rune("=SUM(lineItems.extendedAmount)")
public Double subtotal;

Runtime Contract

The generated field is calculated on read. The formula result is not persisted unless application code explicitly writes it somewhere else.

The runtime maps formula references from the model object into OpenXLS:

  • subtotal resolves from a field, JavaBean getter, or map key on the target object
  • lineItems.extendedAmount resolves as a collection projection
  • arrays and collections become OpenXLS ranges
  • empty collections map to 0 for numeric formulas
  • OpenAPI formula text remains spreadsheet-style; ValkyrAI rewrites model references into OpenXLS named ranges internally

This keeps the authoring model compositional: schema authors define formulas on OpenAPI component properties, ThorAPI generates model annotations, and ValkyrAI evaluates with the Gridheim/OpenXLS formula runtime.

Why This Matters

Runes keep business math:

  • schema-authored
  • generated into code
  • visible to clients and docs
  • deterministic at runtime
  • compatible with spreadsheet-style formula thinking

Do not hide durable business math in custom service methods when it should be part of the object contract.

Related: