Pack
Definition
A Pack is a bundle of authored configuration that adapts the generic Axonis platform to a specific customer domain. The term is overloaded, so be precise:
- A domain pack is the whole authored bundle for one domain — a directory under
loom/packs/domains/<name>/containingmanifest,domain,profiles,accountability,experiences,signal_policies,decision_templates,task_templates, andlens. - An experience pack is one part of that bundle: the UI/UX, vocabulary, and monitor-layout config that drives how
Beacon presents the domain (ES alias
experience, authored inexperiences.yaml).
The key idea: the data model always uses the platform's canonical DES terms internally (Signal, Insight, Edition, Block, Task); a Pack remaps those nouns to the customer's language and configures the surfaces around them, without changing the underlying objects. loom is the only writer of packs; cortex reads them and passes presentation config through to Beacon.
Authoring/validation: loom/loom/domain_loader.py, loom/loom/domain_schema.py. Cortex consumption:
cortex/cortex/pack_tools.py, cortex/server/middleware/mcp_initialize.py. Reference: cortex/docs/PACK_CONFIG_REFERENCE.md.
Lifecycle
Author → materialize → read, the same flow as a Profile. An operator edits the YAML; loom load-domains deep-merges it
with org-level defaults, validates ~23 cross-reference checks (domain_schema.py), and explodes each part into the ES
intelligence index (one experience doc per domain, id <domain>_experience_v<version>, etc.). Cortex reads the
relevant docs at MCP initialize and passes the vocabulary straight through to Beacon. Packs are versioned by a
version: field in the YAML; a re-load re-materializes.
Journey through the code
Authoring: loom/loom/domain_loader.py (_load_domain, explode_domain) validates and writes the exploded docs;
loom/loom/domain_schema.py runs the cross-reference checks. Consumption: at session start,
cortex/server/middleware/mcp_initialize.py reads the experience / domain / profile docs from ES and injects pack
config into the MCP initialize response, so Beacon receives navigation, vocabulary, monitor layout, and entity-page
config. cortex passes the vocabulary dict through verbatim — it does not interpret the values itself
(PACK_CONFIG_REFERENCE.md:541).
Data shape
The experience pack (experiences.yaml, PACK_CONFIG_REFERENCE.md:524): experience_pack_id, version, name,
description, vocabulary{} (per-noun and per-verb label remapping for monitor / explore / entity / signal / insight /
investigation / edition / attestation / block / task / decision), ui.nav{show_modules[], hide_modules[],
landing_page}, ui.home{title, subtitle}, monitor{layout, blocks[]} (each block: block_template_id, title,
type, kpis[], uds_model), explore{welcome, input_placeholder, suggested_actions[]}, entity_page{enabled,
layout}. Storage: ES intelligence index, experience alias. The upstream stub schema
(axonis-core/.../schemas.yaml:52) only models id/name/description/profile_id/content{} — the real structure lives in
the authored YAML.
Invariants
- One experience doc per domain. Org
defaults.experiencesare deep-merged under the domain's overrides. - Vocabulary is presentation-only — the internal data model always uses canonical DES terms.
- Cross-references validated at load — a Profile's
experience_pack/accountability/domain_packrefs must resolve.
Related products
product.profile— Profiles live inside a domain pack and reference its Experience and Accountability parts; the Experience pack's vocabulary remaps the nouns a Profile's user sees.product.signal/product.insight/product.edition/product.task— a Pack supplies the signal policies, decision templates, accountability routing, and labels that shape these objects' behavior per domain.product.lens—lens.yamlis a part of the domain pack (entity-resolution config).
Open questions
- Terminology — the product spec must keep "experience pack" vs "whole domain pack" vs sub-packs (accountability / decision / task) distinct.
- Under-specified contract — the authored YAML is far richer than the
axonis-corestub schema; the golden contract is not pinned down. - Coverage —
signal_policies.yamlandlens.yamlalso live in the domain dir; whether this spec covers them or they get their own treatment is open.
Realized by: component.cortex.domain-loading, component.cortex.pack-reference