Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

AKS Full Grammar Reference

This is the authoritative grammar specification for AKS (Architecture Knowledge Syntax). Every ```aks example in this document is validated against the real parser by crates/archkit-frontend/tests/docs_aks_conformance.rs — if it’s written here, it parses.

Grammar style: off-side rule (indentation-sensitive) with explicit end <keyword> block closers. Parser: hand-written lexer + recursive-descent parser in crates/archkit-frontend/src/aks/.


1. High-Level Structure

Every AKS file contains exactly one workspace block. The workspace name must be a quoted string. Nine kinds of declaration may appear inside, in any order.

workspace "Commerce"
  module commerce@v1

  shape Service
    id: String
  end shape

  entity checkout_api: Service
    has tag critical
  end entity
end workspace

Rules:

  • Must start with workspace "name" (quoted string, not a bare identifier)
  • Optional module <name>@<version> immediately after the header
  • Declarations: shape, event, entity, relationship, lattice, policy, operation, project, view
  • Every block closes with end <keyword>, including end workspace
  • Indentation is significant: spaces only, one level per block

2. Module Declaration (Optional)

workspace "Demo"
  module archkit_core@v2.0
end workspace

Rules:

  • Optional; appears immediately after the workspace header
  • Syntax: module <identifier>@<version> — the version is free text to end of line (v1, 2.0, 1.2.3-beta all work) and must be non-empty
  • end module is optional

3. Shapes (Data Structures)

shape Account
  id: String
  email: String
  balance: Float?
  tags: String[]
  fallbacks: String?[]
  metadata: Json
end shape

shape EmptyShape
end shape

Rules:

  • shape <identifier> followed by newline
  • Fields are name: TypeExpr, one per line, indented
  • end shape required; empty shapes allowed

Type expressions (implemented):

SyntaxMeaning
Namenamed type (String, Int, Float, Bool, or any shape name — names are not validated at parse time)
Jsonuntyped JSON (the only special-cased type name)
T?optional
T[]list
suffix stackingString?[] = list of optionals

Not implemented (do not use): [T] prefix lists, {k: T} map types, (T1, T2) tuples, T1 | T2 unions. The AST reserves nodes for map/tuple/union, but no surface syntax produces them.


4. Events

Events use identical field syntax to shapes; the keyword marks async message/event semantics.

event OrderPlaced
  order_id: String
  customer_id: String
  amount: Float
end event

5. Entities (Instances / Nodes)

Header forms

entity plain_node
end entity

entity account1: Account
end entity

entity payments_db database
end entity

entity stripe external system
end entity
  • entity <id> — generic kind
  • entity <id>: <ShapeName> — with shape reference
  • entity <id> <kind> — with element kind. Kind vocabulary: database, queue, container, component, person, and the two-word phrase external system. Any other word in kind position is a parse error.

Body

entity checkout_api: Service
  has tag critical
  has tag revenue_path
  has owner: payments_team
  has sla: "4 hour response"
  has config: {timeout: 30, retries: 3}
  has regions: ["us-east", "eu-central"]
  derived from: "service-catalog:checkout_api"
  verified by: "arch-review:AR-2026-041"

  edge payment_service calls
    has protocol: https
    verified by: "trace:prod:checkout/payment"
  end edge

  edge notification_queue sends data to
    has async: true
  end edge
end entity

Body items (all optional, repeatable):

  • has tag <identifier> — attach a tag
  • has <key>: <value> — attach a property (the has keyword is required; bare key: value lines are not valid in entity bodies)
  • provenance clauses (§7)
  • edge <target> <phrase> … end edge — local edges (§6 phrase vocabulary); edge bodies take has properties and provenance clauses
  • expands to <kind> … end <kind> — sub-language blocks (§12)

6. Relationships (Global Edges)

relationship user uses api
end relationship

relationship frontend calls backend
  has protocol: "JSON-RPC"
  has timeout_ms: 5000
end relationship

relationship db serves api
  evidenced by: "trace:prod:db-query"
  verified by: "test:integration"
end relationship

Rules:

  • relationship <from> <phrase> <to> followed by newline
  • Body (optional): has <key>: <value> properties and provenance clauses
  • end relationship required

Edge phrase vocabulary — these normalize to a closed EdgeKind set:

  • Multi-word (pre-tokenized by the lexer): depends on, sends data to, receives data from, reads from, writes to, connects to, owned by, contained by, extended by, implemented by, used by, provided by, served by, cached by, monitored by
  • Single-word: calls, publishes, subscribes, precedes, follows, triggers, owns, contains, extends, implements, uses, produces, consumes, exports, imports, serves, caches, monitors
  • Any other single word is accepted as a custom phrase (EdgeKind::Custom). Custom multi-word phrases are not possible.

7. Provenance (Evidence Tracking)

Provenance clauses may appear in entity, edge, and relationship bodies:

entity user_service
  derived from: "doc:requirements"
  evidenced by: "trace:prod:user-table"
  observed in: "runbook:user-mgmt"
  verified by: "test:user-factory"
  deprecated by: "doc:migration-2026"
end entity

Verbs (closed set, pre-tokenized): derived from, evidenced by, observed in, verified by, deprecated by.

Format: <verb>: <value> where value is a string or identifier; repeatable.

replaces is not a provenance verb. Express supersession as a property: has replaces: "old_notification_queue".


8. Lattices (Ordered Domains)

Only chain lattices are implemented:

lattice Criticality
  order low < medium < high
end lattice

lattice Severity
  order minor < moderate < major < critical
  bottom minor
  top critical
end lattice

Rules:

  • lattice <identifier> followed by newline
  • order a < b < c — a single ascending chain
  • Optional bottom <element> (must be the chain’s first element) and top <element> (must be the last)
  • end lattice required
  • Lowering computes the reflexive-transitive closure automatically

Explicitly rejected (reserved for future partial orders): level, covers, join, meet, incomparable — using them is a parse error, not a silent no-op.


9. Policies (Governance Rules)

policy revenue_reliability
  applies to tag: revenue_path
  when source.env: prod
  unless source.experimental: true
  requires monitoring.enabled
  must have owner
  forbids tier: best_effort
  requires reaches via depends on where target.owner: platform
end policy

Structure:

  • policy <identifier> followed by newline
  • Selector (required): applies to tag: <tag> | applies to entity: <id> | applies to shape: <name> | applies to relationship: <phrase>
  • Conditions (optional, repeatable): when <predicate>, unless <predicate>
  • Requirements (optional, repeatable): requires <predicate>, forbids <predicate>, must have <predicate> (alias of requires), must not <predicate> (alias of forbids)
  • end policy required

Predicates:

  • Free text to end of line (monitoring.enabled, source.owner: platform) — captured as a simple predicate and interpreted during evaluation
  • Lattice comparisons: <expr> at least <expr>, <expr> at most <expr>, <expr> above <expr>, <expr> below <expr>
  • Reachability: reaches via <edge-phrase> with optional where <predicate> (nestable). Reachability predicates currently lower as advisory (info) diagnostics — they parse and are preserved, but are not evaluated against the graph yet.

10. Operations (Behavior Property Bags)

operation DataSync
  action: "synchronize replicas"
  timeout_sec: 3600
  retry: 3
end operation

Rules: operation <identifier>, body is bare key: value lines (no has prefix here), schema is user-defined. end operation required.


11. Projects (Bundles)

project checkout_system
  includes entity user
  includes entity api
  has team: payments
  deployment: production
end project

Rules:

  • project <identifier> followed by newline
  • Body may contain, in any order:
    • includes <free text> — repeatable; stored as includes_<n> properties
    • has <key>: <value> or bare <key>: <value> — both accepted here
  • end project required

12. Views (Projections)

view revenue_overview
  kind: system
  schema: c4
  include: tag: revenue_path
  include: entity: payments_db
  exclude: tag: experimental
  focuses_on: checkout_api
  layout
    rankdir: LR
    fontsize: 12
end view

Body keywords:

  • kind: <identifier> — view type (defaults to system)
  • schema: <identifier> — rendering schema (defaults to c4)
  • include: <selector> / exclude: <selector> — repeatable
  • focuses_on: <entity> — highlight one entity (note the spelling: focuses_on, not focus_on)
  • layoutbare keyword, no colon, followed by an indented block of key: value pairs; the block ends at dedent (there is no end layout)
  • end view required

Selectors: entity: <name>, tag: <tag>, relationship: <phrase>. No other selector types exist.


13. Sub-Language Blocks (expands to)

Entities can embed domain-specific sub-language blocks:

entity pricing_rules
  expands to expression
    o quantity
  end expression
end entity

Rules:

  • expands to <kind> followed by newline and an indented block
  • The block body is captured as a raw token stream (it must still lex as AKS: tokens like *, =, + are rejected by the lexer)
  • Closed by end <kind> at the parent indentation

The expression sub-language:

  • o <name> — variable reference; o 42 / o "lit" — constants
  • <> <op> with left: / right: ports — operation trees. Known limitation: operation trees currently parse but fail lowering (“unexpected end in operation”); only variable/constant expressions survive the full pipeline today. Track before relying on <> forms.

14. Property Values

Values in has k: v, operation/project/layout bodies:

FormExample
string"4 hour response" (double quotes only; escapes \n \t \" \\)
integer5000 (no negative literals, no exponents)
float3.14
booleantrue, false
identifierhttps, payments_team (colon-joined idents like a:b also parse)
list["us-east", "eu-central"], [1, 2, 3]
object{timeout: 30, retries: 3, cache: true} (nestable)

15. EBNF Summary

workspace       = "workspace" STRING newline module? decl* "end" "workspace"
module          = "module" IDENT "@" line_text newline ("end" "module")?

decl            = shape | event | entity | relationship | lattice
                | policy | operation | project | view

shape           = "shape" IDENT newline (indent field* dedent)? "end" "shape"
event           = "event" IDENT newline (indent field* dedent)? "end" "event"
field           = IDENT ":" type_expr newline
type_expr       = ("Json" | IDENT) ("?" | "[" "]")*

entity          = "entity" IDENT ((":" IDENT) | kind_phrase)? newline
                  (indent entity_item* dedent)? "end" "entity"
kind_phrase     = "database" | "queue" | "container" | "component"
                | "person" | "external system"
entity_item     = "has" "tag" IDENT newline
                | "has" IDENT ":" value newline
                | provenance
                | edge
                | expands_to
edge            = "edge" IDENT edge_phrase newline
                  (indent (has_prop | provenance)* dedent)? "end" "edge"
expands_to      = "expands" "to" IDENT newline indent raw_tokens dedent "end" IDENT

relationship    = "relationship" IDENT edge_phrase IDENT newline
                  (indent (has_prop | provenance)* dedent)? "end" "relationship"
edge_phrase     = EDGE_PHRASE_TOKEN | IDENT          (* see §6 vocabulary *)
provenance      = PROVENANCE_VERB ":" line_text newline   (* see §7 verbs *)

lattice         = "lattice" IDENT newline indent
                  "order" IDENT ("<" IDENT)+ newline
                  ("bottom" IDENT newline)? ("top" IDENT newline)?
                  dedent "end" "lattice"

policy          = "policy" IDENT newline indent
                  ("applies" "to" selector newline)
                  (("when" | "unless") predicate newline)*
                  (("requires" | "forbids" | "must have" | "must not") predicate newline)*
                  dedent "end" "policy"
selector        = ("tag" | "entity" | "shape" | "relationship") ":" value

operation       = "operation" IDENT newline (indent kv* dedent)? "end" "operation"
project         = "project" IDENT newline
                  (indent ("includes" line_text | has_prop | kv)* dedent)? "end" "project"

view            = "view" IDENT newline (indent view_item* dedent)? "end" "view"
view_item       = ("kind" | "schema") ":" IDENT newline
                | ("include" | "exclude") ":" selector_type ":" IDENT newline
                | "focuses_on" ":" IDENT newline
                | "layout" newline indent kv* dedent
selector_type   = "entity" | "tag" | "relationship"

has_prop        = "has" IDENT ":" value newline
kv              = IDENT ":" value newline
value           = STRING | INT | FLOAT | BOOL | IDENT
                | "[" (value ("," value)*)? "]"
                | "{" (IDENT ":" value ("," IDENT ":" value)*)? "}"

16. Common Errors

Missing end marker — every block needs its closer:

entity user
  has tag actor
# error: expected 'end entity'

Mismatched end:

entity user
end shape        # error: expected 'end entity', found 'end shape'

Bare property in entity body (entity bodies require has):

entity user
  role: storage  # error: expected newline — write `has role: storage`
end entity

Unquoted workspace name:

workspace Ecommerce   # error: expected string — write workspace "Ecommerce"

Tabs in indentation — the lexer rejects tabs outright.


17. Reserved Words

Reserved (cannot be used as bare identifiers in most positions):

workspace module shape event entity relationship lattice policy
operation project view end edge has tag with includes excludes
focuses on renders shows hides groups orders by expands
when unless requires forbids above below
order level top bottom join meet covers incomparable

Notes:

  • with, renders, shows, hides, groups, orders, by, on, focuses, excludes are reserved but currently consumed by no grammar rule (reserved for future view syntax)
  • at least, at most, must have, must not, applies to, the edge phrases (§6), the provenance verbs (§7), and external system are pre-tokenized multi-word phrases

  • Lexical detail (tokens, indentation, phrase tables): LEXICAL_RULES.md
  • Working examples (validated in CI): ../examples/
  • Overlay files (annotate blocks) are a separate dialect handled by archkit-project, not this grammar — see docs/guides/PROJECT_SYSTEM.md
  • Parser source: crates/archkit-frontend/src/aks/parser/
  • Lexer source: crates/archkit-frontend/src/aks/lexer/
  • Conformance test: crates/archkit-frontend/tests/docs_aks_conformance.rs