Naming as Navigation
Every thing and assertion in a repository has a name, and all names share one namespace. A name can contain /, as in catalog/electronics/phones/pixel-9. The slashes give the name segments, and glob patterns match against those segments. A good naming scheme lets an agent list part of a repository, guess the names of things it has not seen, and subscribe to changes in one part of it.
Names and Shapes are separate
Section titled “Names and Shapes are separate”A name says where a Thing sits in the repository. Its Shapes say what it is. The two are stated separately:
{ "operation": "add", "name": "catalog/electronics/phones/pixel-9", "shapes": ["Product"], "data": { "title": "Pixel 9" }}- The first segment of a name is not a Shape. In
catalog/electronics/phones/pixel-9,catalogis just the first part of the name. The Thing’s Shape isProductbecause the write says so inshapes. - Names are unique across the repository, whatever the Shape. Once
brands/googleis aBrand, an add ofbrands/googleunder another Shape is refused. Plan names so that things of different Shapes do not need the same name. For example, a pull requestpr-456and an assertion about it cannot both be calledpr-456. - A Shape is itself a Thing, named
hub/shapes/<Name>. TheProductShape is the Thinghub/shapes/Product. Thehub/prefix is reserved: only Shapes live there, and a Thing named underhub/is refused.
The web app uses the same name in its URL, and the short wref.ai form mirrors it:
app.warmhub.ai/orgs/acme/repos/catalog/things/catalog/electronics/phones/pixel-9 ─┬── ──┬──── ───────────────┬────────────────── org repo thing name
wref.ai/acme/catalog/catalog/electronics/phones/pixel-9 ─┬── ──┬─── ───────────────┬────────────────── org repo thing nameBoth forms resolve to the same Thing. The name is the address.
A segment does not have to exist as its own Thing. catalog/electronics/phones/pixel-9 can exist with no Thing named catalog/electronics or catalog/electronics/phones. A glob such as catalog/electronics/** matches against the name string, so it finds pixel-9 either way.
Two ways to move through a repository
Section titled “Two ways to move through a repository”By name. Segments group related things. From catalog/electronics/phones/pixel-9, an agent can list every phone (catalog/electronics/phones/*), every electronics item (catalog/electronics/**), or the whole catalog (catalog/**).
By assertion. Assertions link a thing to another thing regardless of where their names sit. A Review assertion named reviews/pixel-9/agent-1 can be about catalog/electronics/phones/pixel-9, and a SuppliedBy assertion can link the same phone to brands/google.
catalog/ brands/├── electronics/ ├── google ◄──── SuppliedBy ────┐│ ├── phones/ ├── apple ││ │ ├── pixel-9 ──── supplied-by/pixel-9 (SuppliedBy) ────────────┘│ │ └── iphone-16 └── samsung│ └── laptops/│ └── macbook-air reviews/└── home/ └── pixel-9/ └── kitchen/ └── agent-1 (about: catalog/electronics/phones/pixel-9) └── instant-pot-duoAn agent can use names to find the right set of things, then follow assertions to related things whose names are elsewhere in the repository.
Why this matters for agents
Section titled “Why this matters for agents”Scoped reads
Section titled “Scoped reads”An agent cannot load a whole repository, but it can read one part of it:
# Everything under catalog/electronics/wh thing list --match "catalog/electronics/**"
# Only the phoneswh thing list --match "catalog/electronics/phones/*"
# Phones in every top-level categorywh thing list --match "catalog/*/phones/*"Add --shape to filter by Shape as well as by name. The two filters are independent. --shape includes Things that reach the Shape through composition; --declared-shape matches only Things that declare it directly:
# Every Product, wherever its name sitswh thing list --shape Product
# Products whose names start with catalog/electronics/wh thing list --shape Product --match "catalog/electronics/**"Predictable names
Section titled “Predictable names”If an agent sees sensors/hq/floor-3/conference-a/temp, it can guess that sensors/hq/floor-2/conference-a/temp may exist. If it sees reports/2024-q1/summary, it can guess at reports/2024-q2/summary. A consistent scheme lets an agent find things it has not seen yet by changing one segment.
A flat name such as sensor-hq-floor-3-temp holds the same information, but globs cannot select on its parts.
Names that describe the thing
Section titled “Names that describe the thing”The wref articles/tech/2024/transformer-scaling tells an agent the category, year, and topic before it reads any data. The Shape, Article, says what fields the data has. Together they describe a thing without a read.
Subscription match
Section titled “Subscription match”Subscriptions accept the same glob syntax in their match filter, so an action can run on changes to one part of a repository:
{ "shape": "Sensor", "all": [ { "operation": "add" }, { "kind": "thing" }, { "match": "sensors/hq/**" } ]}A subscription on Things names their Shape, in shape at the top of the filter or as the subscription’s shapeName. The match then narrows it by name: any Sensor added under sensors/hq/, on any floor, triggers the action. Patterns can use ** (sensors/**/temp), * for one segment (catalog/*/phones/*), or braces (sensors/hq/floor-{3,4}/**). An array of patterns matches any of them ({"match": ["sensors/hq/**", "sensors/warehouse/**"]}); put two match predicates in all to require both.
Designing your names
Section titled “Designing your names”Start from how the data is read
Section titled “Start from how the data is read”Order segments by how people and agents select the data. Ask: “What are the most common ways someone will want to select part of this?”
Product catalog. Category, then subcategory, then item:
catalog/electronics/phones/pixel-9catalog/electronics/laptops/macbook-aircatalog/home/kitchen/instant-pot-duocatalog/outdoor/camping/rei-half-domeThis supports catalog/electronics/** (one category), catalog/electronics/phones/* (one subcategory), and catalog/**/camping/* (one subcategory across categories).
Sensor network. Location, then sensor type:
sensors/hq/floor-3/conference-a/tempsensors/hq/floor-3/conference-a/humiditysensors/hq/floor-3/hallway/motionsensors/warehouse/zone-b/tempsensors/hq/floor-3/** selects one floor, and sensors/**/temp selects every temperature sensor.
Research corpus. Source, then year, then topic:
papers/arxiv/2024/attention-mechanisms-surveypapers/arxiv/2023/transformer-efficiencypapers/acl/2024/multilingual-ragPut the most-filtered segment first
Section titled “Put the most-filtered segment first”Lead with the segment you filter on most often. If most reads are by region, put region first. If most are by date, put date first.
# Category first: most reads browse by product typecatalog/electronics/phones/pixel-9
# Region first: most reads are limited to one geographycatalog/us/electronics/phones/pixel-9Neither order is always right. Pick the one that matches how the data will be read.
Give each Shape its own prefix
Section titled “Give each Shape its own prefix”Because all names share one namespace, a top-level segment per kind of record keeps names from colliding and makes each kind easy to select: catalog/ for products, brands/ for brands, reviews/ for review assertions. The prefix is a naming convention only. The Shape still comes from shapes, and --shape filters on it.
Keep segments meaningful and stable
Section titled “Keep segments meaningful and stable”Each segment should carry information:
# Every segment says somethingcompanies/acme/filings/10-k/2024
# "data" and "records" add nothingcompanies/acme/data/records/filings/10-k/2024Use stable identifiers rather than timestamps or UUIDs, unless you have a reason. Names can be changed with a rename. Stored references follow the Thing, but the old name stops resolving, so any wref text kept outside the repository (docs, scripts, other systems) breaks, and a producer that still computes the old name creates a second Thing. Keep names stable once others refer to them. See Retract, Rename & Schema Changes.
Stay flat when segments do not help
Section titled “Stay flat when segments do not help”If a set of things has no natural grouping, flat names are fine:
currencies/usdcurrencies/eurcurrencies/jpyTwo levels below the prefix are often enough. At five levels, check whether each one helps an agent select data.
Use names for grouping and assertions for relationships
Section titled “Use names for grouping and assertions for relationships”Segments express grouping: a product belongs to a category and subcategory. Assertions express relationships: a product is supplied by a brand, or one paper cites another.
Do not put a relationship in a name:
# Don't: the supplier relationship is in the namecatalog/electronics/made-by-samsung/phones/galaxy-s24
# Do: group by category, and record the supplier in an assertioncatalog/electronics/phones/galaxy-s24 └── supplied-by/galaxy-s24 (SuppliedBy assertion) about: catalog/electronics/phones/galaxy-s24, supplier: brands/samsungA name answers “where is this in the repository?” An assertion answers “what is this related to?”
Querying by name
Section titled “Querying by name”Glob matching
Section titled “Glob matching”--match on read commands takes a glob pattern:
| Pattern | Matches |
|---|---|
catalog/electronics/* | Names exactly one segment below catalog/electronics/ |
catalog/electronics/** | Names at any depth below catalog/electronics/ |
catalog/*/phones/* | Phones in every top-level category |
sensors/**/temp | Names ending in temp at any depth below sensors/ |
catalog/{electronics,home}/** | Names under either catalog/electronics/ or catalog/home/ |
companies/acme/filings/10-*/* | One segment that starts with 10- (10-k, 10-q) |
hub/shapes/* | The repository’s Shapes |
* never crosses a /. ** crosses any number of segments.
A pattern of ** alone matches every Thing but no Shape. To list Shapes, name the prefix: hub/shapes/*.
# One floorwh thing list --match "sensors/hq/floor-3/**"
# Every temperature sensorwh thing list --match "sensors/**/temp"
# Several categorieswh thing list --match "catalog/{electronics,home,outdoor}/**"The same patterns work in MCP queries and in the SDK’s query methods.
Combining names and assertions
Section titled “Combining names and assertions”A common sequence is to select by name, then read assertions:
# 1. Find the phoneswh thing list --match "catalog/electronics/phones/*"
# 2. Read what has been asserted about one of themwh thing about catalog/electronics/phones/pixel-9
# 3. Read a related brandwh thing view brands/google
# 4. Read what has been asserted about the brandwh thing about brands/googlePatterns in practice
Section titled “Patterns in practice”Ingestion pipeline
Section titled “Ingestion pipeline”A scraper adds product listings by category:
catalog/electronics/phones/pixel-9catalog/electronics/phones/iphone-16catalog/electronics/laptops/macbook-aircatalog/home/kitchen/instant-pot-duoA Product subscription with match: "catalog/electronics/**" runs a classification action for each new item. The action adds assertions such as reviews/..., prices/..., and similar/... about the product. Agents then select products by name and read the assertions for ratings, prices, and alternatives.
Multi-agent research
Section titled “Multi-agent research”Three agents study companies from different angles:
# Thingscompanies/acmecompanies/globexpairs/acme-v-globex (a Bond with ends companies/acme and companies/globex)filings/acme/10-k/2024filings/globex/10-k/2024
# Assertions, one prefix per kindtheses/acme-growth (about: companies/acme) agent-1risk-flags/acme-debt (about: companies/acme) agent-2comparisons/acme-v-globex (about: pairs/acme-v-globex) agent-3An agent reviewing Acme can:
- List
filings/acme/**to see every filing. - Read the assertions about
companies/acmeto see each agent’s view. - List what refers to
companies/acme(wh thing refs companies/acme) to findpairs/acme-v-globex, read the comparison about that pair, then listfilings/globex/**.
Sensor monitoring with alerts
Section titled “Sensor monitoring with alerts”sensors/hq/floor-3/conference-a/tempsensors/hq/floor-3/conference-a/co2alerts/hq/floor-3/conference-a/co2-high-2024-03-15A Sensor subscription with match: "sensors/hq/**" runs a threshold check for any sensor data under HQ. When CO2 exceeds the limit, the action adds an Alert Thing whose name repeats the sensor’s location, so */hq/floor-3/conference-a/** finds both the sensors and the alert. A second subscription, on Alert with match: "alerts/**", sends notifications.
Anti-patterns
Section titled “Anti-patterns”Treating the first segment as the Shape. Product/pixel-9 is a valid name, but Product in it does not make the Thing a Product; only shapes does. Use a lowercase prefix such as catalog/ so a name is not mistaken for a Shape.
Relationships in names. If one thing’s identity appears in another thing’s name (catalog/reviewed-by-agent-1/phones/pixel-9), use an assertion instead.
UUID-only names. catalog/f47ac10b-58cc-4372-a567-0e02b2c3d479 is valid, but an agent cannot learn anything from it. Prefer readable names when the domain has natural identifiers. Otherwise use deterministic source identifiers, such as upstream IDs, content slugs, or run-scoped sequence numbers.
Inconsistent depth. If most products are catalog/<category>/<subcategory>/<item> but some are catalog/<item>, globs select unpredictably. Keep things of the same kind at the same depth.
Name segments in place of Shapes. If segments separate different kinds of data (entities/person/jones and entities/company/acme), those kinds probably need separate Shapes (Person, Company), each with its own fields. Shapes say what a thing is; names say where it sits among things of that kind.
Too many segments. data/raw/ingested/pipeline-v2/batch-003/electronics/phones/pixel-9 has segments no read filters on. Keep only the segments that agents select by.