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
- A schema property declares an
x-gridheim-runeformula. - ThorAPI code generation emits the generated model field with
@com.valkyrlabs.valkyrai.runes.Rune. - The generated object carries the formula inline with the model contract.
- ValkyrAI intercepts reads of the annotated field with
RuneAspect. RuneValidationServicevalidates formula references against fields, getters, and collection element types on the model class.RuneContextBuilderresolves the model instance into formula values, including nested dot paths and collection projections.RuneEvaluationServiceprojects 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:
subtotalresolves from a field, JavaBean getter, or map key on the target objectlineItems.extendedAmountresolves as a collection projection- arrays and collections become OpenXLS ranges
- empty collections map to
0for 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: