Operations
Every write request contains one or more operations. There are three operation types — add, revise, and retract — across shape, thing, assertion, and collection records. Collections provide inline syntax for creating grouped things.
A write request can include multiple operations. CLI (wh commit submit), SDK
(client.commit.apply), and MCP (warmhub_commit_submit) writes apply
operations one at a time — if a later operation fails, earlier ones are still
in place, and you can retry just the failed ones. See Writes.
ADD Operations
Section titled “ADD Operations”ADD Shape
Section titled “ADD Shape”Create a new shape with field definitions:
{ "operation": "add", "kind": "shape", "name": "Location", "data": { "fields": { "x": "number", "y": "number", "label": "string" } }}ADD Thing
Section titled “ADD Thing”Create a new thing under an existing shape:
{ "operation": "add", "kind": "thing", "name": "Location/cave", "data": { "x": 3, "y": 7, "label": "Dark Cave" }}ADD Assertion
Section titled “ADD Assertion”Create an assertion about another thing. The about field is required:
{ "operation": "add", "kind": "assertion", "name": "Belief/cave-safe", "about": "Location/cave", "data": { "safe": true, "confidence": 0.8 }}about accepts local wrefs, canonical wrefs, or inline collection syntax.
REVISE Operations
Section titled “REVISE Operations”Revise only changes data. It does not accept an active field — to mark
an entity inactive, use a retract operation instead.
TypeScript SDK users see this as a compile error because ReviseOperation
declares active?: never.
REVISE Shape
Section titled “REVISE Shape”Update a shape’s field definitions:
{ "operation": "revise", "kind": "shape", "name": "Location", "data": { "fields": { "x": "number", "y": "number", "z": "number" } }}REVISE Thing
Section titled “REVISE Thing”Update a thing’s data:
{ "operation": "revise", "kind": "thing", "name": "Location/cave", "data": { "x": 5, "y": 3, "label": "Bright Cave" }}REVISE Assertion
Section titled “REVISE Assertion”Update an assertion’s data. The about target cannot be changed:
{ "operation": "revise", "kind": "assertion", "name": "Belief/cave-safe", "data": { "safe": false, "confidence": 0.2 }}Collection Operations
Section titled “Collection Operations”Collections are a convenience for creating grouped things (pairs, triples, sets, lists). Under the hood, the commit pipeline expands collection operations into standard thing operations — collections are things with built-in shapes.
ADD Collection
Section titled “ADD Collection”Create a collection thing explicitly:
{ "operation": "add", "kind": "collection", "type": "pair", "members": ["Location/A", "Location/B"]}The name field is optional — if omitted, a canonical name is derived from the members (e.g., Pair/Location/Av1+Bv1).
You can also create collections inline within an assertion’s about field. See Collections for the full syntax.
Retracting a Collection
Section titled “Retracting a Collection”To mark a collection inactive, use a RETRACT operation (see RETRACT Operations):
{ "operation": "retract", "name": "Pair/Location/Av1+Bv1"}RETRACT Operations
Section titled “RETRACT Operations”Mark an entity inactive. The entity’s data and version history are preserved; it is hidden from default HEAD queries.
{ "operation": "retract", "name": "Location/cave", "reason": "replaced by Location/dungeon"}The reason field is optional (max 500 chars). The kind field is an optional safety hint — the operation will error if the resolved entity’s kind doesn’t match.
Retract is the only path to setting an entity inactive. Once retracted, you can add a new entity at the same name to create a fresh identity.
Operation Rules
Section titled “Operation Rules”Data Requirements
Section titled “Data Requirements”datais required on revise for shape, thing, and assertion- Revise is a full replacement — you must include all fields in
data, not just the ones that changed - Omitted fields will be absent in the new version, which will fail shape validation if they are required
aboutis required on ADD assertion, immutable on REVISE assertion
Idempotent Revise
Section titled “Idempotent Revise”If a revise produces the same data hash as the current version, it returns operation: "noop" — no new version is created.
Illegal Operation Sequences
Section titled “Illegal Operation Sequences”Within a single chunk, the following sequences on the same target are rejected by preflight:
| Sequence | Allowed? |
|---|---|
| ADD + ADD | No — duplicate add |
| REVISE + ADD | No — can’t add something that already exists |
| ADD + REVISE | Yes — create then immediately update |
| REVISE + REVISE | Yes — multiple updates in sequence |
TypeScript callers binding an inline operation literal to a variable should
either annotate it : Operation[] or use satisfies Operation[] to keep
the operation discriminant narrowed — see SDK Write Methods — Typing
Operation arrays.
Batch Files
Section titled “Batch Files”The --file flag on wh commit submit accepts a JSON file containing an array of operations. For large datasets, prefer JSONL streaming (one operation per line):
# JSON array (small/medium batches)wh commit submit --file operations.json --message "batch update" --repo org/repo
# JSONL stream (large datasets — chunked automatically)wh commit submit --file dataset.jsonl --progress -m "bulk import" --repo org/repoThe JSON file must contain a JSON array of operation objects:
[ { "operation": "add", "kind": "thing", "name": "Location/cave", "data": { "x": 3, "y": 7, "label": "Dark Cave" } }, { "operation": "add", "kind": "assertion", "name": "Belief/cave-safe", "about": "Location/cave", "data": { "safe": true, "confidence": 0.8 } }]Generating templates
Section titled “Generating templates”Use wh shape template to scaffold operations from shape definitions (template generation lives in the shape domain):
# Single shape -> thing scaffoldwh shape template Hypothesis --repo org/repo
# Multiple shapes at oncewh shape template Hypothesis Evidence Decision --repo org/repo
# Assertion scaffold for a shaped claim about a targetwh shape template Hypothesis --kind assertion \ --about ResearchTopic/example --repo org/repo
# Write to file, then edit and commitwh shape template Hypothesis Evidence -o experiment.json --repo org/repo$EDITOR experiment.jsonwh commit submit --file experiment.json -m "add experiment" --repo org/repoThe template fills fields with placeholder values ("", 0, false) and FILL_IN: hints for fields with descriptions. Replace placeholders with real data before writing.
Shapes define the payload schema, not whether an operation is a thing or an assertion. To scaffold an assertion, pass --kind assertion; add --about <TargetShape/name> when you want a concrete target instead of the default placeholder.
Streaming large files
Section titled “Streaming large files”For large datasets, use JSONL format (one operation per line) with streaming:
wh commit submit --file dataset.jsonl --progress -m "bulk ingest" --repo org/repoToken System
Section titled “Token System”The $N (allocate) and #N (reference) tokens let you create entities and reference them within the same stream — for example, adding a thing and an assertion about it in the same chunk, or in a later chunk of the same stream. Token state is scoped to the streamId and is echoed back on each stream.append response so the next chunk can resolve #N references against earlier allocations.
#N cannot reference future tokens — order operations so adds precede the references that depend on them.
See Wrefs: Batch Tokens for the full syntax, rules, and examples.
Hit a problem or have a question? Get in touch.