Skip to content

Modules

The intellia modules command group manages the modules registry — bundles of existing app site and/or workflow roots, registered as a single catalogue entry. See Modules for the concept.

Registering a public module — one that enters the catalogue every organization installs from — is restricted to Hutly’s internal authoring organization, and to a Hutly superadmin. A module with an intellia- slug is a first-party module, which must be public and declare a family (see Naming and the reserved namespace). A private module is registered by an Admin or Owner of the organization it belongs to, and is visible and installable only there. list is available to any organization browsing the catalogue.

Naming and the reserved namespace

Names starting with intellia belong to Intellia’s own modules. Only a first-party module may create an agent, knowledge base, workflow, schedule or webhook slug starting with intellia-, or a table name starting with intellia_. A first-party module:

  • has a slug starting with intellia-, such as intellia-erp-base;
  • is visibility: public;
  • declares family in module.yaml (1–16 lowercase letters or digits, starting with a letter), and names every object under it: intellia-<family>-… for slugs and intellia_<family>_… for tables.

Any other module, public or private, names its objects after its own slug, <slug>-… for slugs and <slug_with_underscores>_… for tables, so a module acme-crm has workflows such as acme-crm-sync and tables such as acme_crm_lead. intellia modules check reports an object outside that prefix as an error. Registering the module returns it as a warning instead and still registers the module, because an existing workflow’s slug cannot change. An object of any other module whose name starts with intellia is refused.

When you name an agent, knowledge base, schedule, webhook or workflow “Intellia …” without giving it a slug, the platform derives a slug with its kind in front, such as agent-intellia-helper or workflow-intellia-sync. A slug or table name you type yourself in the reserved space is refused.

Each module owns the reserved objects it installs, and neither a deploy nor an activation takes over another module’s object. A first-party deploy adopts a reserved object this module installed or one no module installed. Activation adopts only the reserved objects this module installed, plus a dependency’s table, which it adopts as it stands.

Error Meaning
reserved_namespace A slug or table name you supplied is in the reserved space, and its detail field says which name to change; or a module slug starts with intellia- but the module is not public.
module_object_taken A reserved object of that name already belongs to another module, or to this organization (owner names it).
module_namespace_violation A first-party module has objects outside intellia-<family>- / intellia_<family>_, or another module has objects starting with intellia (names lists them).
module_family_required A first-party module has no family in module.yaml.
module_dependency_missing A dependency kept from the module’s last registration is no longer registered. Remove it from dependsOn; write dependsOn: [] to clear the stored edges, since an absent key keeps the last registration’s edges.
module_bundle_unresolved A first-party module’s closure, or the closure of a dependency (reason names it), could not be assembled, so nothing was registered.
module_deploy_header_invalid The first-party deploy claim names a slug outside the reserved space, or came from a sandbox token.

intellia modules define

Register a module. Its version goes up only when its content changed since the last registration. Every --root must reference an app site or workflow that already exists in the org, and carries its own required description.

intellia modules define \
  --slug acme-portal \
  --name "Acme Portal" \
  --description "Bundles the Acme storefront site with its nightly sync workflow." \
  --root "app_site:3f9e2b3a-2222-4c11-9b8e-111111111111:the storefront" \
  --root "workflow:7c1d44f0-3333-4d22-8c9f-222222222222:nightly sync"

intellia modules define \
  --slug acme-portal \
  --name "Acme Portal" \
  --description "Bundles the Acme storefront site with its nightly sync workflow." \
  --visibility private \
  --category "e-commerce" \
  --tags "portal,acme" \
  --root "app_site:3f9e2b3a-2222-4c11-9b8e-111111111111:the storefront" \
  --pretty
Option Description
--slug <slug> Module slug, unique in the public catalogue and within your org (required)
--name <name> Module display name (required)
--description <description> Module description (required)
--visibility <visibility> public or private; omit to keep the stored value (a new module is private). public requires Hutly’s internal authoring org and a Hutly superadmin; an intellia- slug requires public
--category <category> Optional category
--tags <csv> Comma-separated tags
--root <spec> Root as <kind>:<resourceId>:<description> — kind is app_site or workflow (repeatable)
--pretty Pretty-print JSON output

intellia modules get

Fetch a single module by id, including its roots.

intellia modules get 3f9e2b3a-2222-4c11-9b8e-111111111111
intellia modules get 3f9e2b3a-2222-4c11-9b8e-111111111111 --pretty
Option Description
--pretty Pretty-print JSON output

intellia modules list

List the platform-wide public catalogue — every public module, regardless of which organization authored it — plus your own organization’s modules if it’s an authoring organization (including any private ones it owns).

intellia modules list
intellia modules list --pretty
Option Description
--pretty Pretty-print JSON output

intellia modules project

Project a registered module’s source into a portable, reviewable YAML tree on disk — everything the module bundles (app sites, apps, workflows, tables, agents, knowledge bases), rewritten as !ref-linked files under --out. This does not deploy, activate, or install anything; it only writes the tree so it can be reviewed, diffed, or checked into version control. Deploying a projected tree back into an organization is a later capability.

When the module has a captured source bundle (see deploy below), project unpacks that bundle directly instead of re-projecting from live records — the authored tree (comments, structure, anything the DB projection can’t recover) wins, and a drift warning prints if a workflow or table in the module was edited after the capture. Projection from live records is the fallback, used only when no bundle exists (a module predating source capture). Pass --projected to force live-record projection regardless of a captured bundle.

intellia modules project 3f9e2b3a-2222-4c11-9b8e-111111111111 --out ./acme-portal
intellia modules project 3f9e2b3a-2222-4c11-9b8e-111111111111 --out ./acme-portal --projected
Option Description
--out <dir> Output directory for the projected source tree (required)
--projected Skip the captured source bundle and always project from live records
--pretty Pretty-print JSON output

When falling back to live-record projection, the emitted tree follows a fixed layout:

acme-portal/
  module.yaml               # module metadata, dependsOn, and roots, each a !ref
  app-sites/<slug>.yaml      # one file per app_site root: its own site, or attachTo a dependency's site
  apps/<app-slug>/
    manifest.yaml            # the app's manifest, refs rewritten to !ref
    <artifact filename>      # the app's artifact bytes
  workflows/                 # every workflow the module's roots pull in
  tables/                    # shared tables referenced by those workflows
  agents/                    # shared agents referenced by those workflows
  knowledge-bases/           # shared knowledge bases referenced by those workflows
  functions/                 # inline function code from those workflows (if any)
  scripts/                   # inline bash-step code from those workflows (if any)

App artifact bytes are not returned inline by the API — the module’s source bundle carries a presigned S3 URL per artifact, and the CLI downloads the bytes directly from S3 into apps/<app-slug>/<filename>.

A projected tree holds only the module’s own resources. When one of its pages calls a workflow that a module it depends on installs, the page’s manifest names that workflow by its slug and the module, instead of pointing at a file:

workflows:
  - !ref ../../workflows/post-entry.yaml
  - slug: get-my-roles
    module: erp-base

Deploy needs no copy of the dependency’s tree for this. It checks that the module is in dependsOn, that it is registered in the organisation, and that it installed a workflow with that slug, and stops before writing anything when one of those does not hold. A !ref into a dependency’s own tree beside this one still works.

intellia modules deploy

Deploy a projected module tree (the layout project emits) into the configured organization and register it. This is the code/CI authoring channel — the transport the deploy-modules CI action uses to publish curated modules committed under modules/ into Hutly’s internal authoring org. It is not required for every module; a module authored interactively (via Sammy) is registered directly with define.

intellia modules deploy ./acme-portal
intellia modules deploy ./acme-portal --pretty

Deploy walks the tree in dependency order:

  1. Site checks — before anything is written, deploy reads every app site the tree declares and refuses the whole deploy when the site belongs to another module, when a declared path already holds a page another module registered or an unregistered page whose content differs from the tree, or when an attachTo site’s owner has not recorded its page paths.
  2. Workflow closure — every workflow the tree contains (the module’s own workflow roots plus any workflow an app manifest references), reusing the standard workflow deploy so tables, agents, and knowledge bases the workflows pull in are deployed and the state machines published. A manifest workflow that belongs to another module’s tree is not deployed here; that module deploys it.
  3. App sites and apps — for each app_site, its artifact is published, its embedded manifest approved (the server resolves the manifest’s workflow slugs to the ids just deployed), and each app attached at its path. An attachTo file adds its apps to the named dependency module’s site, which must already be deployed, and never renames or reconfigures that site. A re-deploy that changes nothing keeps the registry version with any CLI, since the version ignores artifact version ids. From CLI 1.11.1, a page whose built file matches the artifact version it already serves also keeps that version instead of appending an identical one.
  4. Registry — the module is registered with its roots resolved to the ids deployed above, in module.yaml order. Deploy then checks that the platform recorded the page paths it sent, and stops with Module "<module>" registered, but the platform did not record its app page paths, … when the platform is older than the CLI. Registering also gives the authoring org the starter rows a table’s seed: declares, the rows a consumer org gets at activation, and like activation it writes them only into a table that is still empty. A table that could not be seeded comes back as a warning naming it.

Deploy is idempotent by natural key: workflows match by slug, tables by name, agents and knowledge bases by slug, app_sites by slug, apps by path. A re-deploy removes a page its tree no longer has only when this module registered that page on its last deploy, or, on a site the module owns but has no record of yet, when no other module registered it. Pages another module added to the same site stay. The module upserts by its organization and slug. The committed tree stays id-free — a re-run against the same org updates every resource in place and produces no duplicates. A tree that declares visibility: public in its module.yaml can only be deployed into Hutly’s internal authoring org. Each app site goes in one file; a tree that declares the same site in two files stops at load.

These refusals stop the deploy before anything is written:

Message What to do
App site "<site>" is owned by module "<module>"; choose another site slug Give this module’s site its own slug.
Page "<path>" on app site "<label>" belongs to another module; choose a different path Move this module’s page to a free path.
Module "<module>" is not registered in this organisation; deploy "<module>" first Deploy the module you attach to, then this one.
App site "<site>" is not owned by module "<module>"; attach to a site "<module>" owns Name a site the dependency owns in attachTo.
App site "<site>" of module "<module>" has no recorded page paths; deploy "<module>" with CLI 1.10.0 or newer first Re-deploy the owner with this CLI.

Deploy the owner of a site that other modules attach to with CLI 1.10.0 or newer. An older CLI sends no page paths, so register refuses it with module_attach_owner_paths_required, and before that refusal it has already removed every page on the site that is not in its own tree, other modules' pages included. If a deploy fails after it wrote pages, for example on a dropped connection, run the same deploy again without changing the tree. A page at one of the module’s paths that no module has registered is taken as the module’s own only when it holds exactly the content the tree would publish there, which is what the failed deploy left. Deploy then updates it in place, on the module’s own site and on a site it attaches to alike. Any other unregistered page at that path, such as one a person made by hand, stops the deploy before anything is written, with Page "<path>" on app site "<label>" exists but was not registered by any module and its content differs from this tree; remove it, or register it with its owner, then deploy again. If you changed the tree after the failed deploy, remove the pages it left and deploy again.

A first-party tree declares its family next to its visibility:

slug: intellia-erp-base
visibility: public
family: erp

A bridge joins two optional modules, for example stock and sales. It declares both in dependsOn and sets bridge: true in module.yaml. The in-app catalogue leaves a bridge out; the in-app installer adds it to an install plan once every module it depends on is installed or being installed (an older installed version is upgraded alongside), so it arrives with whichever of them comes last. Omitting bridge keeps the stored value.

define has no --family option, so a first-party module is first registered with deploy; a later define keeps the stored family. Before writing anything, deploy stops a tree whose slug, visibility and family do not agree (see Naming and the reserved namespace).

After deploying, modules deploy captures the deployed directory as a source bundle — registered against the module, every app_site it deployed, and every artifact version it published — so intellia source list <kind> <id> / intellia source pull <kind> <id> -o <dir> can recover the exact authored tree later. Capture defaults to the nearest ancestor directory holding module.yaml or .intelliarc.yaml; use --source-root to capture a different directory instead. A module whose workflow TypeScript imports files from outside its own directory — a shared contracts/ folder in a repo of several modules — must deploy with --source-root <repo root>, or the captured bundle omits those files and source pull cannot rebuild the workflows.

Option Description
--source-root <path> Directory to capture as the source bundle (default: nearest module.yaml/.intelliarc.yaml ancestor)
--pretty Pretty-print JSON output

intellia modules activation (step-by-step)

Drive a module activation session one step at a time. This is the underlying machine intellia modules activate walks automatically; use the activation subcommands directly when a hole needs interactive resolution (a missing secret or integration) between begin and deploy. See Modules for the concept.

intellia modules activation begin <moduleId>

Begin an activation session for a registry module. <moduleId> is a module id from the catalogue (intellia modules list). Prints { sessionId, preview }, where preview carries the module summary, any unresolved holes (secrets/integrations), and the derivedSlug (empty for workflow-only modules).

intellia modules activation begin 3f9e2b3a-2222-4c11-9b8e-111111111111

intellia modules activation get <sessionId>

Print an activation session’s current state, including its step (preview → holes → configure → accepted → deploying → done/failed).

intellia modules activation get 7c1d44f0-3333-4d22-8c9f-222222222222

intellia modules activation holes <sessionId>

Recompute and print the session’s unresolved holes (secrets/integrations still required before the session can be accepted).

intellia modules activation holes 7c1d44f0-3333-4d22-8c9f-222222222222

intellia modules activation configure <sessionId>

Set the activated module’s app_site slug and any params. Omit --slug for a workflow-only module (no app_site to slug).

intellia modules activation configure 7c1d44f0-3333-4d22-8c9f-222222222222 \
  --slug acme-portal \
  --params '{"region":"au"}'
Option Description
--slug <slug> app_site slug for the activated module (optional; provide it for modules that carry an app_site)
--params <json> JSON-encoded params object

intellia modules activation accept <sessionId>

Accept the session. This is a strict gate — it rejects (409, activation_holes_unresolved) if any holes remain unresolved. On success the session advances to accepted.

intellia modules activation accept 7c1d44f0-3333-4d22-8c9f-222222222222

intellia modules activation deploy <sessionId>

Start the async clone of the module’s resources into the org. The session moves to deploying, then done or failed as the worker progresses; poll with activation get to watch it land.

intellia modules activation deploy 7c1d44f0-3333-4d22-8c9f-222222222222

intellia modules activate

One-shot activation walker: begin → (holes gate) → configure → accept → deploy → poll until the session reaches done or failed. <target> is either:

  • a registry moduleId — the standard catalogue path, or
  • an existing directory — an uploaded-origin module tree (the layout intellia modules project emits, typically after Sammy has edited it). Uploaded origin currently supports workflows and agents only; a tree that also bundles tables, knowledge bases, or app_site apps fails loud rather than activating a partial module.

If the session has unresolved holes, the command stops and prints the activation subcommands needed to resolve them and continue manually — a one-shot activation cannot resolve holes interactively.

intellia modules activate 3f9e2b3a-2222-4c11-9b8e-111111111111
intellia modules activate ./acme-portal
Option Description
--pretty Pretty-print JSON output

Activating over existing tables

When a module’s table already exists in the organisation, activation compares the two schemas. Identical tables are adopted as they are. If the module’s version adds to the table — a new column, index, unique constraint or foreign key, a default, a description, or a required flag being dropped — activation applies those changes and reports each one in the activation’s warnings, for example: Table "stock_ledger" was updated to the module's schema: Add column "qty".

Activation never removes anything. Columns, unique constraints and indexes on the organisation’s table that the module does not declare are left in place, so a customer’s own columns survive re-activation, and a module version that no longer declares a column leaves that column and its values where they are.

What activation does not apply is a tightening of something the module declares: making a column required, changing which table a column links to, or dropping a foreign key the organisation added to a column the module declares without one. The activation fails once, names every such step, and does not retry:

Cannot activate: table "stock_ledger" in this organisation needs changes that
activation does not make on its own — Make "qty" required. Apply them with
`intellia tables push` or remove the table, then re-activate.

Two other conflicts fail once the same way, with the server’s reason after the table name, and do not retry: a column whose type or Data Dictionary link differs from the module’s, and a unique constraint, foreign key or required new column that the table’s existing rows violate:

Cannot activate: table "stock_ledger" in this organisation — Cannot add a
unique constraint on (sku): 3 duplicate group(s) exist. Remove the
duplicates first.

intellia modules check reports the same judgement from the declarations alone before anything is deployed, and names what a dependent module leaves in place, for example leaves in place: column "legacy".

intellia modules hide <moduleId> / intellia modules unhide <moduleId>

Toggle an activated module’s visibility for the org, without deactivating it. hide moves it to the hidden state; unhide moves it back to active.

intellia modules hide 3f9e2b3a-2222-4c11-9b8e-111111111111
intellia modules unhide 3f9e2b3a-2222-4c11-9b8e-111111111111
Option Description
--pretty Pretty-print JSON output