Authoring workflow
Status: Current v0.5 canonical. The single source of truth for how a Gaia knowledge package is authored — for both humans and agents.
Gaia has one authoring model with two tiers. This page states it and closes the gaps that earlier docs left ambiguous.
The model
Tier 1 — direct SDK authoring (recommended). Write the DSL directly in
Python. Run gaia sdk once to drop a self-contained reference plus a
one-page CHEATSHEET.md next to your work, read the cheat sheet, then
author your statements in src/<pkg>/__init__.py (and your own modules).
This is the primary path for everyone — humans and agents alike.
gaia sdk # writes ./gaia-sdk/CHEATSHEET.md + full reference
# read CHEATSHEET.md, then author directly:
# src/my_package/__init__.py
gaia build compile ./my-package-gaia
gaia run infer ./my-package-gaia
Tier 2 — the gaia author CLI (optional convenience). gaia author
<verb> CRUDs DSL statements through structured, JSON-enveloped commands.
It is a convenience layer over Tier 1 — useful when you want machine-checked
appends, identifier-collision guards, and a post-write compile check — not a
separate or "agent-first" authoring path. Use it when it helps; skip it when
you'd rather write Python directly.
What this resolves
- Recommended path = direct SDK authoring (Tier 1).
gaia authoris Tier 2, optional. Start withgaia sdk, not the CLI. - One on-disk format. A Gaia package is plain Python (
.py). There is no second serialized format. CLI output is confined to the package's composedauthored/submodule (see below). gaia authorAPPENDS and is NOT idempotent. Re-running the samegaia authorcommand writes the statement again; a later binding of the same name shadows the earlier one.gaia author listreports shadowing (the earlier binding is stampedshadowed_by). If you re-run a command, expect a duplicate — edit the source or rename rather than relying on dedup.- No "agent-first" framing. Both humans and agents author directly
first; the CLI is optional for either. There is no privileged agent entry
point —
gaia sdkis the shared starting move. - Auxiliary files live under
authored/. When the CLI manages priors or reviews, they land inauthored/priors.py/authored/reviews/…(created viagaia pkg add-module, routed there bygaia author <verb> --file <name>.py). Hand-authored packages may keep a top-levelpriors.py; both are loaded by the engine. - Mixing contract. Hand-authored DSL lives in your own modules (the
package root
__init__.pyand any siblings you write). CLI-authored DSL lives inauthored/. The two compose by import, never by interleaving in one file: the package-root__init__.pyimports theauthoredmodule, copies its public runtime bindings into root globals for package local references, and merges onlyauthored.__all__into its own__all__. Only names in the merged root__all__become the package's exported public surface. Exported names must be localKnowledgeobjects; returned helpers from relation verbs are allowed and are typed as relation interfaces in manifests.
The authored/ submodule
gaia build init / gaia pkg scaffold create:
my-package-gaia/
src/my_package/
__init__.py # hand-authored DSL + authored import block
authored/
__init__.py # CLI-authored statements land here (__all__ literal)
priors.py # optional CLI-managed sibling (gaia pkg add-module)
The package-root __init__.py ends with:
__all__: list[str] = [...] # your hand-authored public exports
from . import authored as _authored
for _gaia_name, _gaia_value in vars(_authored).items():
if not _gaia_name.startswith("_"):
globals()[_gaia_name] = _gaia_value
del _gaia_name, _gaia_value
__all__ = [*__all__, *_authored.__all__]
gaia author never writes the package-root __init__.py; every CLI write
goes into authored/. This keeps hand-authored and CLI-authored statements
in separate files that compose cleanly. Author commands default to internal
writes; pass --export only for bindings that belong in the curated public
surface. For relation verbs, --export exports the returned relation helper;
for direct formula operands, name the formula with claim(..., formula=...)
instead of exporting the implicit lift helper.
Pre-canon alpha packages. You do not add the authored import block by hand. On the first
gaia author <verb>write, the CLI automatically createsauthored/and appends the authored import block plus the__all__merge to your package-root__init__.py. The only manual step for an alpha-era package is relocating any pre-existing CLI-style statements that currently live in the root__init__.pyintoauthored/if you want them CLI-managed there. There is no migration tooling: CLI-authored and hand-authored.pyare byte-identical, so a detector would false-positive — hence the move is manual and the appended block is byte-identical to the scaffolded one. If your root__all__is a tuple, the merge preserves it as a tuple.
See also
gaia sdk— generates a self-contained SDK reference plus a top-tierCHEATSHEET.mdinto its--outdirectory at runtime (see the model).- Language reference — the static DSL surface reference.
gaia author/gaia pkg scaffold— the optional Tier-2 CLI.