Skip to content

Principles & Patterns

WarmHub is a flexible platform. The examples in these docs show one way to model data — they are not the only way. This page covers the principles behind the design and the patterns that work well in practice.

Everything is versioned, nothing is deleted. Every mutation produces a new version. Deactivation hides an entity from default queries but preserves its full history. This means you can always ask “what did we know at time T?” — so don’t be afraid to write data early, even if it’s uncertain.

Commits are atomic. A commit can contain multiple operations that succeed or fail together. Use this to keep related changes consistent — add a thing and its initial assertions in the same commit rather than spreading them across multiple writes.

Names are stable, not permanent. Names identify things and appear in wrefs (references like Shape/name), but they can be changed — even on deactivated things. When a thing is renamed, existing references automatically resolve to the new name. Things are linked by identity, not by name — the name is a human-readable label on top of that link. Choose names that are meaningful and stable, but know that renaming is safe if needed.

The about reference is immutable. An assertion’s target is set at creation and cannot be changed. If you assert about the wrong thing, deactivate and create a new assertion. This immutability is a feature — it guarantees that the relationship between an assertion and its subject is stable and auditable.

Assertions are the right choice when:

  • Attribution matters — you need to know who said something about an entity, not just the current state
  • Multiple perspectives coexist — different agents or sources have different views on the same thing
  • Confidence varies — claims carry uncertainty, evidence, or scores that evolve over time
  • History of belief matters — you want to trace how understanding of an entity changed

Assertions may be unnecessary when:

  • You’re storing plain facts with a single source of truth — a regular thing with revisions may be simpler
  • The data doesn’t need attribution — if no one will ever ask “who said this?”, a thing is enough
  • You’re modeling static reference data that rarely changes — shapes and things handle this well on their own

Not everything needs to be a belief. A lookup table of country codes is fine as plain things. An agent’s assessment of whether a competitor is a threat — that’s an assertion.

Things are the foundation. Use them for:

  • Entities in your domain — the objects your system reasons about (locations, players, companies, documents)
  • Reference data — stable records that serve as targets for assertions
  • Anything with a single canonical state — if there’s one truth about this entity, it’s a thing

Things are versioned too. If a thing’s data changes, revise it — you get a new version while keeping the old one. You don’t need assertions just to track changes over time.

Shapes define structure, but WarmHub is deliberately flexible about what that structure looks like. Some guidance:

Start simple. You can always revise a shape to add fields. You don’t need to anticipate every future field up front.

One shape per concept, not per use case. A Belief shape that captures confidence and evidence can be used across many contexts. You don’t need CaveBeliefShape and PlayerBeliefShape — use one Belief shape and let the about reference distinguish what each assertion is about.

Use wref fields for relationships. If a thing references another thing, use a wref-typed field. This creates a trackable link that WarmHub can resolve and validate.

Don’t cargo-cult the examples. The docs use game-world examples (Location/cave, Belief/cave-safe) to illustrate concepts. Your shapes should reflect your domain. A financial analyst might have Company, Earnings, and Forecast shapes. A research agent might have Paper, Claim, and Evidence shapes. The modeling primitives are the same — the names and fields are yours.

Thing names appear in wrefs (Shape/name), so they should be:

  • Lowercase with hyphens for multi-word names: dark-cave, quarterly-report-q4
  • Descriptive enough to be meaningful in isolation: cave is fine if there’s only one; east-cave is better if there are many
  • Stable — don’t use timestamps or UUIDs as names unless you have a good reason. Names can be changed, but stable names make wrefs easier to read and remember.

For auto-generated names, use batch tokens ($N/#N) and let WarmHub fill them with opaque generated identifiers. Treat those names as stable IDs, not sequences.

An agent writes observations as assertions about entities it encounters:

  1. Define a Location shape (or whatever your domain entities are)
  2. Define an Observation or Belief shape with fields like confidence, source, evidence
  3. The agent adds things as it discovers entities
  4. The agent creates assertions about those things as it learns
  5. Other agents (or humans) query those assertions to build on that knowledge

Multiple agents write to the same repo. Each commit is attributed, so you can trace who said what:

  • Agent A and Agent B can both assert about the same thing
  • Their assertions coexist — WarmHub doesn’t force consensus
  • A downstream process can compare, reconcile, or aggregate their views

As knowledge changes, revise assertions rather than deactivating and recreating:

  • revise updates the assertion’s data while preserving its identity and history
  • The about reference stays the same (it’s immutable)
  • You can query the full version history to see how understanding evolved

Only deactivate when an assertion is truly no longer valid — not just outdated.

Don’t over-assert. Not every piece of data needs to be an assertion. If you’re the only writer and there’s no uncertainty, a plain thing is cleaner.

Don’t under-commit. Group related operations into a single commit. Five separate commits for five related changes means five points where things could be inconsistent. One atomic commit is better.

Don’t treat shapes as tables. A shape is a type definition, not a SQL table. You don’t need a shape for every noun — you need shapes for the kinds of entities in your domain.

Don’t copy example names. Location/cave is a teaching example. Use names from your actual domain.

Don’t fight immutability. If you find yourself wanting to change an assertion’s about target, that’s a signal to deactivate and create a new one. The immutability is there to protect the integrity of your knowledge graph.