Domains
Folders and subfolders as the catalog structure. DOMAIN.md, keywords, featured artifacts, the prose body, and discovery rendering knobs.
A domain is a directory in the registry. It groups related artifacts and gives them shared context. finance is a top-level domain; finance/ap is a subdomain; finance/ap/pay-invoice is the canonical path of an artifact under it.
Domains exist whether or not you do anything special. Any subdirectory in your registry path is a domain by default. The optional DOMAIN.md file at the directory root adds metadata: a description, keywords, featured artifacts, the prose body that an agent reads when it navigates here, include: patterns that pull in artifacts from elsewhere, and discovery-rendering knobs.
When you don't need DOMAIN.md
For a small or in-progress catalog, nest folders. The directory tree is the domain hierarchy, and each artifact's canonical ID is the directory path under the registry root.
~/podium-artifacts/
└── personal/
├── hello/
│ └── greet/ # type: skill
│ ├── SKILL.md
│ └── ARTIFACT.md
└── deploy/
└── check-config/ # type: command
└── ARTIFACT.md
load_domain("personal") returns the two subdomains; load_domain("personal/hello") returns the greet artifact. No DOMAIN.md needed. A domain without a DOMAIN.md has no projection to embed, so it never appears in search_domains results; it stays reachable through load_domain enumeration.
When to add one
Add a DOMAIN.md when:
- A description should appear in
load_domainoutput. - Keywords should surface in
search_domains. - Artifacts from another domain should appear in this domain.
- Some paths should be excluded from this domain.
- A folder should be unlisted, hidden from enumeration, and still reachable by ID.
- Discovery rendering needs subtree-specific overrides.
DOMAIN.md lives at the root of a domain directory:
~/podium-artifacts/
└── team-finance/
└── finance/
└── ap/
├── DOMAIN.md ← the metadata file
├── pay-invoice/ # type: skill
│ ├── SKILL.md
│ └── ARTIFACT.md
└── reconcile-invoice/ # type: skill
├── SKILL.md
└── ARTIFACT.md
DOMAIN.md schema
---
unlisted: false
description: "AP-related operations"
discovery:
max_depth: 4
fold_below_artifacts: 5
featured:
- finance/ap/pay-invoice
deprioritize:
- finance/ap/_archive/**
keywords:
- invoice
- remittance
- reconciliation
- 1099
- vendor master
include:
- finance/ap/pay-invoice
- finance/ap/payments/*
- finance/refunds/**
- _shared/payment-helpers/*
- _shared/regex/{ssn,iban,routing-number}
exclude:
- finance/ap/internal/**
---
# Accounts Payable
Operations and artifacts for the AP function: invoice processing,
vendor remittance, payment reconciliation, and 1099 reporting. This
domain applies to tasks involving money flowing out of the company to
vendors.
For inbound payments and AR, see `finance/ar/`.| Field | Description |
|---|---|
unlisted | When true, the folder and its subtree are removed from load_domain enumeration. Artifacts inside are still reachable via load_artifact, still appear in search_artifacts (subject to per-artifact search_visibility:), and can be imported into other domains. Default false. |
description | One-line summary used wherever this domain appears as a child or sibling in another load_domain response. |
discovery.* | Per-domain overrides of the discovery rendering rules. See Discovery rendering below. |
include | List of glob patterns and artifact IDs to import into this domain. Imported artifacts keep their canonical home; they appear here additionally. |
exclude | Applied after include. Removes paths. |
The prose body below the frontmatter is long-form context, returned by load_domain only when this domain is the requested path. For a domain appearing as a child or sibling in another response, only the frontmatter description is returned.
Description: frontmatter vs body
A domain has two slots for prose:
- Frontmatter
descriptionis a one-liner. It's what you see when this domain appears as a child or sibling in anotherload_domainresponse. - Prose body is long-form context, returned only when this domain is the requested path.
Resolution for the requested domain's description: the body if present, otherwise the frontmatter description, otherwise a synthesized fallback (the directory basename, title-cased and de-slugged).
For a load_domain("finance", depth=2) call, the response includes finance's body (because finance is the requested path) plus a two-level subtree of subdomains, each rendered with their short description only. To read another domain's body, the agent calls load_domain on it directly.
Body length is recommended ≤ 2000 tokens; lint warns above.
Keywords
discovery.keywords is an author-curated list of terms agents should associate with this domain: synonyms, jargon, distinguishing terminology. They're returned verbatim in load_domain output for this domain, and they're indexed for search_domains retrieval (alongside the description and the truncated body).
Keywords are the cheapest way to make a domain findable. If your AP domain is the right place for "1099" questions but the description doesn't mention 1099, add it to keywords.
Featured artifacts
discovery.featured is an author-curated list of canonical artifact IDs that should surface first in this domain's "notable" list:
featured:
- finance/ap/pay-invoice
- finance/ap/reconcile-invoiceFeatured entries appear before any signal-driven entries in the notable list. If featured: alone exceeds the configured notable_count cap, it's truncated in author-supplied order and no signal entries are added.
discovery.deprioritize is the inverse: a list of glob patterns whose matching children rank last and are excluded from "notable" unless space permits.
Imports
include: brings artifacts from other domains into this one for discovery purposes. Glob syntax: * (one segment), ** (recursive), {a,b,c} (alternatives).
include:
- finance/ap/pay-invoice # exact match
- finance/ap/payments/* # one-level wildcard
- finance/refunds/** # recursive
- _shared/payment-helpers/* # cross-domain
- _shared/regex/{ssn,iban,routing-number} # alternationImportant properties:
- Imports do not change canonical paths. An artifact has exactly one canonical home (the directory where its
ARTIFACT.mdlives, plusSKILL.mdfor skills). Imports add appearances under other domains.search_artifactsreturns the artifact once, with its canonical path and (optionally) the list of domains that import it. - Imports are dynamic. When an artifact is added at a path matched by a glob, this domain picks it up automatically. No
DOMAIN.mdre-ingest needed. - Authoring rights. Editing a domain's
include:requires write access to the layer that contains the destinationDOMAIN.md. Importing does not require any rights in the source path; only that the artifact resolves under some layer the registry has ingested. - Visibility. Enforced per layer at read time. A caller who can't see the source layer doesn't see the imported artifact under this domain either.
exclude: removes paths after the include set is computed.
Unlisted folders
Setting unlisted: true removes a folder and its entire subtree from load_domain enumeration. Artifacts inside still:
- Are reachable via
load_artifact(<id>)if the host has visibility. - Appear in
search_artifactsresults normally (subject to per-artifactsearch_visibility:). - Can be imported into other domains via
include:.
Use case: a _shared/ folder that holds reusable helpers. Mark it unlisted so it doesn't clutter load_domain output, then import its contents into the domains that actually need them.
---
unlisted: true
---unlisted: true propagates to the whole subtree.
DOMAIN.md across layers
If multiple layers contribute a DOMAIN.md for the same path, the registry merges them:
| Field | Merge |
|---|---|
description and prose body | Last-layer-wins. |
include | Additive across layers. |
exclude | Additive across layers; applied after the merged include set. |
unlisted | Most-restrictive-wins. |
discovery.max_depth, discovery.notable_count, discovery.target_response_tokens | Most-restrictive-wins (lowest value). |
discovery.fold_below_artifacts | Most-restrictive-wins (highest value). |
discovery.fold_passthrough_chains | Most-restrictive-wins (true over false). |
discovery.featured, discovery.deprioritize, discovery.keywords | Append-unique. |
When a workspace-local-overlay DOMAIN.md is involved, the consumers that expose load_domain apply the merge client-side after the registry returns its result for the registry-side layers: the MCP server and the language SDKs. podium sync materializes by the sync.yaml scope rather than by domain enumeration, so it does not apply this merge.
Discovery rendering
The rendering of load_domain output is governed by configurable rules. Tenant defaults live in registry.yaml; per-domain overrides live in DOMAIN.md's discovery: block.
| Knob | Type | Effect |
|---|---|---|
max_depth | int (≥1) | Cap on the depth of the rendered subtree below the requested path. Default 3. |
fold_below_artifacts | int (≥0) | A subdomain whose visible artifact count (recursive) is below this threshold collapses into its parent's leaf set. Default 0 (no folding). |
fold_passthrough_chains | bool | Collapse single-child intermediate domains. Default true. |
notable_count | int (≥0) | Cap on the notable list per domain. Default 10. |
target_response_tokens | int | Soft budget per load_domain response; the renderer tightens depth and notable count to fit. Default 4000. |
featured | list of canonical artifact IDs | Surfaced first in the notable list. |
deprioritize | list of glob patterns | Children matching are ranked last and excluded from "notable" unless space permits. |
keywords | list of strings | Author-curated terms. Per-domain only; no tenant default. |
Tooling
These commands call registry HTTP endpoints. Each requires a running registry server, passed with --registry <url> or the PODIUM_REGISTRY environment variable. A Local deployment reads the catalog from disk and runs no server, so these commands need a Single node or Clustered deployment; podium serve --standalone --layer-path <dir> starts one against the same catalog directory.
podium domain show <path>prints theload_domainoutput for a path. Useful for verifying yourDOMAIN.mdingested correctly.podium domain search <query>runssearch_domainsfrom the CLI. Useful for verifying that yourkeywordsanddescriptionmake the domain findable for the queries you care about.podium domain analyze [<path>]is operator-facing. It reports sparsity per node, pass-through chains, and candidates for split or fold. The command is useful at operational scale and is not part of the day-to-day authoring loop.