[ AxiomCore · Documentation ]
Imports, amends and variants
Choose the Acore keyword that matches the ownership and trust boundary, compose backend sources with amends, and select variants.
Acore has separate keywords for reusing source, composing source, consuming a compiled contract and promoting a model. They are deliberately not synonyms. This page also covers variants, which select part of a backend contract at build time. Backend examples were checked with Axiom CLI 0.149.1.
| Intent | Syntax | What crosses the boundary |
|---|---|---|
| Reuse trusted source in the same build | import "./shared.acore" | A source module |
| Compose Acore or extracted backend input | amends "./base.acore" | Build-time authoring input |
| Consume a compiled contract in Acore UI | use contract Tasks from "tasks" audience "mobile" | A .axiom selected by AxiomDeps.toml and a lock |
| Consume a typed package export in Acore UI | use theme AppTheme from "theme" export "default" | A verified theme or component-library export selected by a package lock |
| Share a pure function | use function normalize from "./shared/title.acore" | Selected pure functions, not executed at import |
| Promote a backend model | entity task(model: Models.Task) | A resolved model reference; no file is loaded |
import
import "./shared.acore"
import "acore:math"import loads trusted source within one build. It does not create a release
boundary.
- In a general module, every top-level property of the imported module,
including
hiddenones, becomes available by name. Imported values are not added to your output. - In a backend source,
importdoes not add the imported file's models or endpoints to the contract. Useamendsto compose declarations, anduse functionto share pure functions. importrejects a compiled.axiomfile and tells you to useuse contractinstead.acore:URIs load standard library modules.
use contract
use contract Tasks from "tasks" audience "mobile"Tasks is the local facade name and tasks is an alias in the frontend
project's AxiomDeps.toml and lock. The alias must resolve to a compiled
.axiom file. The compiler exposes only the operations, fields, audience and
policy metadata selected for that audience. It never loads the backend's
.acore source or runs an extractor. Because of this indirection, you can
change a contract's version or location in the manifest and lock without
editing every source file.
Declare the alias in the frontend's own manifest. Paths are relative to the manifest.
type = "frontend"
[contracts.tasks]
artifact = "../backend/backend.axiom"
baseUrl = "http://127.0.0.1:8080"The backend has its own AxiomDeps.toml with type = "backend". That file
selects backend syntax and may declare audiences = ["mobile"] for typed
Audience.mobile references. Frontend dependency settings do not change it.
Operations are inferred from the contract and filtered by audience. Omit the
dependency's audience key when the contract has one audience or no audience
restrictions; set it when a diagnostic lists several choices. The source's
audience "mobile" must agree with the resolved lock. New manifests need
neither format nor an operations list.
axiom contract resolve
axiom ui check main.acore --target webaxiom contract resolve writes the lock to .axiom/axiom.ui.lock.json by
default; pass --lock to choose a path you commit. Without a lock, ui check
fails with AUI010: cannot read committed UI lock.
use theme and use component
use theme Material from "material-theme" export "default" appearance "light"
use component Controls from "controls" export "PrimaryButton"Both aliases resolve through the committed package lock. The declaration must
match the artifact kind and name an export present in the locked package.
appearance is accepted only on use theme. Editor analysis provides
diagnostics, completion and definition links from that verified surface.
Package source is neither executed nor merged into the consumer. Acore UI also
accepts use extension Name from "alias" export "name"; see
Extension reference.
amends
amends composes authoring input before a contract is built.
In a general module, amends deep-merges the base module with your file:
name = "base"
port = 8080
retry { attempts = 3 timeout = "5s" }amends "./base.acore"
port = 9090
retry { attempts = 5 }axiom eval child.acore keeps name and retry.timeout from the base and
takes port = 9090 and retry.attempts = 5 from the child.
In a backend source, amends accepts a local Acore base or a supported
extractor input:
amends "./base.acore"
amends "axiom-openapi:./openapi.yaml"
amends "axiom-fastapi:./main.py:app"
amends "axiom-go:./cmd/api"After an amend, Models and Routes hold the amended models and endpoints.
Change an amended endpoint with override; do not redeclare its transport.
override endpoint Routes.get_user_by_id {
cache(strategy: CacheStrategy.cacheFirst, ttl: 5m)
}| Situation | Result |
|---|---|
| You redeclare an amended endpoint | AXB002: endpoint 'name' already exists in an amended source; use an explicit override |
| You amend several sources, for example a gateway over two services | Their declarations are deep-merged into one contract |
| Two amended sources declare the same model or endpoint | AXB002: independently amended sources both declare /models/Name. Ordering never silently changes a released surface. |
You amend a .axiom file | Rejected. A compiled contract is immutable. |
You write a top-level extends "..." | Rejected as ambiguous. amends is the one spelling for source composition. |
override accepts endpoint and model. An extractor input must already be
cached; otherwise the build reports AXB005 and asks you to refresh extraction.
Promote a model
project(id: "also-entity", version: "1.0.0")
model Task { id: String title: String } also entity
projection publicTask(entity: Entities.Task, fields: [.id, .title])entity task(model: Models.Task) promotes an already declared or extracted
model. For a local model whose entity has the same shape and a conventional
identity key, append also entity to create Entities.Task; the older
Entities.task spelling still works. Promotion does not import a file, run an
extractor or cross a trust boundary. See
Domain and security models.
Contract build flow
Diagram source
flowchart LR
A["Backend .acore or extractor input"] -->|"amends"| B["axiom build"]
B --> C["Local .axiom, unsigned"]
B --> D["Cloud release .axiom, signed"]
C --> E["Frontend AxiomDeps.toml"]
D --> E
E -->|"axiom contract resolve"| F["Lock file"]
F -->|"use contract"| G["Frontend source"]The frontend resolves its AxiomDeps.toml into a lock. A local unsigned
.axiom is accepted with a warning. A Cloud-released contract carries a
signature and public-key proof, which is verified. A missing lock is a hard
error: Axiom never falls back to backend source or network discovery.
Variants
A variant selects endpoint and model names while the contract is materialized, then prunes the rest.
variant default(include: ["*"])
variant mobile(
include: ["public_*", "profile"],
exclude: ["admin_*"],
includeModels: ["User", "Profile"],
cache: CachePolicy(strategy: CacheStrategy.networkFirst, ttlSeconds: 60)
)
variant operations(
include: ["admin_*", "internal_metrics"],
cache: CachePolicy(strategy: CacheStrategy.networkOnly, ttlSeconds: 0)
)| Argument | Type | Applies to |
|---|---|---|
include | List<String>? | Endpoint names, as glob patterns such as public_* |
exclude | List<String>? | Endpoint names; narrows include |
includeModels | List<String>? | Model names. Without it, every model is kept. |
excludeModels | List<String>? | Model names |
cache | CachePolicy? | A cache policy for the variant |
axiom build main.acore --variant mobile --out backend.axiomcheck,build,explainandevaluse thedefaultvariant unless you pass--variant(-vforeval).- With no
variantdeclarations, an implicitdefaultincludes everything. Once you declare any variant, also declarevariant default(include: ["*"]), or commands without--variantfail withVariant 'default' not found. - A variant that excludes a model a selected endpoint needs fails, for example
Variant 'mobile' excludes model 'A' required by endpoint 'a'. - An explicit endpoint cache policy takes precedence over a variant cache policy, which takes precedence over project defaults.
Variants reduce what a consumer receives; they are not authorization. Protect the backend independently and use signed audience and security declarations for reviewable access boundaries.