---
title: "aontu: Type-safe system definitions, as guardrails for coding agents"
description: "aontu is a language for the ontology of a software system: the entities it contains, the types they must have, and the relations that must hold between them. The definition is machine-checkable, so a change proposed by a coding agent is admitted or refused with the offending line named."
source: "https://aontu.dev/"
---

# Your agents write the code. _aontu_ holds the definition.

aontu defines the entities in a software system, their types, and the relations between them. Use it to check changes proposed by a coding agent: a change is **admitted or refused**, with the source line named when a constraint fails.

[Start the tutorial](https://aontu.dev/docs/tutorial) [Try it in your browser](https://aontu.dev/playground) [Read the docs](https://aontu.dev/docs)

![](https://aontu.dev/brand/aontu-logo.svg)

## Write down what the system _is_

Define which fields a service needs and what values they allow. Types, defaults, and data use the same notation, so you can write them in one document and check them together.

`type()` marks `spec` as schema and keeps it out of the output. `&: $.spec.service` applies that schema to every service, including entries you add later. `tier:*1` supplies a default: `api` gets 1, `auth` specifies 3, and a tier of the wrong kind is refused.

system.aontu

```aontu
spec: type({ service: { owner:string tier: *1 } })

services: { &: $.spec.service }
services: api: owner: "platform"
services: auth: { owner:"identity" tier:3 }
```

aontu system.aontu

```json
{
  "services": {
    "api":  { "owner": "platform", "tier": 1 },
    "auth": { "owner": "identity", "tier": 3 }
  }
}
```

## Check relations between services

Add `calls`, a relation that must stay acyclic, then make the two services call each other. The document fails to evaluate because the calls form a cycle. The refusal names the edge, `$.services.api.calls.0`, and points to the constraint:

the edge an agent added

```aontu
spec: type({ service: { owner:string tier: *1 calls?:rel() & acyclic() } })

services: { &: $.spec.service }
services: api: { owner:"platform" calls: [path($.services.auth)] }
services: auth: { owner:"identity" calls: [path($.services.api)] }
```

aontu system.aontu → exit 1

```aontu-diagnostic
[aontu/relation_cycle]: Cannot relate value at path $.services.api.calls.0

 Cannot relate value: path($.services.auth)
  --> system.aontu:1:54
  1 | spec: type({ service: { owner:string tier: *1 calls?:rel() & acyclic() } })
                                                           ^ value was: path($.services.auth)
```

The refusal includes the `relation_cycle` error code, a class, and an exit status. A repair loop can use these to decide what to fix. The [error-code reference](https://aontu.dev/errors) lists each class and the action it calls for.

## 28 verbs for checking, changing, and sharing a model

Validate data, query a path, explain a value, and check whether a schema change breaks compatibility. Fetch, lock, and publish the packages a model depends on. The TypeScript and Go command lines are checked against one shared test suite. See the reference for each command's output formats and exit codes.

`vet`

does this data satisfy the schema?

`model`

read one document: a path's value, why it holds, an overlay that changes it

`subsume`

is this schema a widening of that one?

`breaking`

which changes break an earlier version?

`trim`

which entries are redundant?

`relations`

run the declared identity checks

`hash`

pin what a document means, not how it is spelled

`sync`

resolve the dependencies, lock them, and verify every pin

`add`

take on a dependency the project does not have

`get`

add a dependency, or raise its minimum version

`remove`

drop a dependency, and the vendor tree it held

`why`

why is this package in the closure?

`publish`

publish this package, a dry run until you say otherwise

`pkg`

the remaining package operations, one step at a time

`agentsmd`

write the AGENTS.md stanza for a definition

`reaches`

is there a path from one entity to another?

`view`

draw the model: tree, graph, matrix, layers, poset

`jsonschema`

export the model, and name what the export cannot carry

`template`

read a generator written in the target's own syntax

`trace`

what wrote this line of generated output?

`render`

write the files a generator answers, or hold them to it

`allow`

may this role change that path?

`fmt`

one agreed form for the source, so layout is never argued about

`init`

scaffold a model, some data, and the checks that hold them

`explain`

what does this error code mean?

`help`

the verbs, and the topics behind them

`lsp`

the language server, for an editor

`mcp`

the same reports, over stdio, for an agent

Every flag and exit code is in the [API and CLI reference](https://aontu.dev/docs/reference-api). With no file, `aontu` starts a REPL.

## Made to be driven by a program

An agent can retrieve a path, ask which source lines contributed to a value, and propose an edit. The CLI provides these operations, and every page on this site is also available as markdown.

-   ### Query a path

    `aontu model get $.services.auth` retrieves one slice; `--keys` lists what exists; `why` names every contribution to a value and the line that wrote it.

-   ### Act on a validation result

    `vet` branches its exit code (valid, invalid, incomplete, or the definition itself is unusable) so a repair loop knows which thing to fix, and a CI gate knows what to block.

-   ### An MCP server

    `aontu mcp` runs locally over stdio and answers with the identical reports the CLI prints. No hosting, no key, no network.

-   ### A published grammar

    GBNF and Lark files ship in the package for constrained decoding, held by a test to accept every canonical form the suite produces, so a model can only emit definitions that parse.

## Evaluation limits

aontu has no user-defined functions, clock, or randomness. Evaluation runs within configured budgets. The [trust contract](https://aontu.dev/docs/trust) states the conditions for termination, deterministic output, and access to files or host values.

Statements combine by [unification](https://aontu.dev/docs/unification). Compatible statements narrow the result; contradictory statements produce an error. Adding a statement later does not give it priority over an earlier one.

## Install

npm

```sh
npm install aontu@0.73.0
```

Go

```sh
go install github.com/aontu-lang/aontu/go/cmd/aontu@latest
```

MIT licensed. Source, issues and the design record are on [GitHub](https://github.com/aontu-lang/aontu).
