Call aontu from Go
Embed the engine with the Go port: the same three calls, with errors returned instead of thrown.
Rendered from
docs/how-to/call-from-go.md
in the engine repository, where a correction belongs, and where the
test suite executes every example on this page.
The Go port is a library first: module github.com/aontu-lang/aontu/go,
package aontu, kept in parity with the canonical TypeScript engine
for the subset it implements. The same three calls, in Go’s idiom:
import aontu "github.com/aontu-lang/aontu/go"
a := aontu.New()
out, err := a.Generate("a: 1 b: $.a") // out = map[string]any{"a":1, "b":1}
v, err := a.Unify("a: *1 | number") // v.Canon() == `{"a":*1|number}`
v, err = a.Parse("a: number") // AST, not yet unified
Nothing throws or panics for an ordinary conflict: every method
returns an error, and Generate returns (nil, err) on any
unresolved or conflicting value, so check it. Generated output uses
Go’s natural types (map[string]any, []any, int64, float64,
string, bool, nil), plus *big.Int and *Decimal for the two
exact leaves, both of which marshal their exact digits as raw JSON
numbers (exact numbers in
Go).
When a source’s relative @"file" loads should resolve from somewhere
other than the process working directory (typically the directory of
an entry file), construct with a base:
abs, _ := filepath.Abs(file)
a := aontu.NewWithBase(filepath.Dir(abs))
(The aontu CLI does exactly this for a file argument.) Absolute
paths are unaffected.
One difference from the TypeScript port to plan around: the Go port
ships no MCP binary: its role is embedding, so Get, Why, Diff
and AgentsMd are library calls instead
(give an agent an entrypoint).
For every problem in one pass rather than the first error, use
Check (collect errors).
The full surface is the Go API reference; to parameterise a model from code, inject host values. The two ports answer alike by construction, and one shared test suite is what pins it.