Writes
All mutations in WarmHub flow through one operation pipeline. Operations
arrive as a flat stream and apply one at a time, each in its own database
transaction. There is no durable batch envelope — graph history lives on
each thing’s version trail (wh thing history).
Operation Kinds
Section titled “Operation Kinds”| Operation | Effect |
|---|---|
add | Create a thing, shape, assertion, or collection at version 1 |
revise | Append a new version with changed data |
retract | Withdraw a thing/shape/assertion/collection from default reads (name remains reserved) |
Use retract for lifecycle changes. revise changes data only and does not
accept active.
Atomicity
Section titled “Atomicity”CLI, SDK, and MCP writes (wh commit submit, client.commit.apply, and
warmhub_commit_submit) apply
operations one at a time. If a later operation fails, earlier ones are still in
place — the per-operation results array tells you what succeeded, what no-op’d,
and what failed, so you can retry just the failed ones. Request-level failures
such as authentication, malformed operation JSON, rate limits, or infrastructure
errors still reject the whole request.
Use #N references or structured collection about to chain operations within
a request — a dependent operation fails with a DEPENDENCY_FAILED or
UNRESOLVED_TOKEN error when its prerequisite didn’t land.
Submitting Operations
Section titled “Submitting Operations”Via CLI
Section titled “Via CLI”# Single operationwh commit submit --add temp-1 --shape Sensor \ --data '{"location": "Building A", "type": "temperature"}' \ -m "Add sensor" --committer Agent/bot-1
# Multiple operations — repeat --add paired with --data (≤20 ops)wh commit submit \ --add Sensor/temp-1 --data '{"location":"A"}' \ --add Sensor/temp-2 --data '{"location":"B"}' \ -m "Two sensors"
# Batch from JSON filewh commit submit --file ops.json -m "Bulk import"
# Stream large datasets from a JSONL filewh commit submit --file dataset.jsonl --progress -m "100k import"
# Stream from stdinproducer | wh commit submit --stream -m "Pipe ops"
# Resume a partial seed — skip already-existing addswh commit submit --file dataset.jsonl --skip-existing -m "Resume seed"The --committer flag is optional. The shorthand flags (--add, --data,
--shape, --about, --kind, --retract, --reason) are repeatable and
pair by index. See Commit Create Deep-Dive.
committer is a wref, not a free-form label —
Agent/bot-1 resolves to the Agent shape’s bot-1 thing, and that thing
must already exist in the repo. A bare name like eval-runner is rejected
with a “Thing wref required” error. Use a cross-repo wref
(wh:other-org/other-repo/Agent/bot-1) to attribute writes to an agent
that lives in another repo.
Via MCP
Section titled “Via MCP”{ "name": "warmhub_commit_submit", "arguments": { "committer": "Agent/claude", "message": "Add sensor with reading", "operations": [ { "operation": "add", "kind": "thing", "name": "Sensor/temp-1", "data": { "location": "Building A", "type": "temperature" } }, { "operation": "add", "kind": "assertion", "name": "Reading/temp-1-v1", "about": "Sensor/temp-1", "data": { "value": 72.5, "unit": "fahrenheit" } } ] }}Via SDK
Section titled “Via SDK”await client.commit.apply(orgName, repoName, "Add sensor", [ { operation: "add", kind: "thing", name: "Sensor/temp-1", data: { location: "Building A" } },])
// Direct streaming surface for large or chunked workloadsawait client.stream.append({ orgName, repoName, streamId: crypto.randomUUID(), operations: [...],})client.stream.append() is the low-level stream wire API and returns backend
entry statuses (success, noop, failed). The commit-oriented surfaces
(client.commit.apply(), OperationBuilder.commit(), CLI, and MCP) normalize
those to the public commit statuses shown below: applied, noop, and
error.
HTTP-Oriented Clients
Section titled “HTTP-Oriented Clients”WarmHub does not mount a REST endpoint for writes. HTTP clients should use the SDK, CLI, or MCP surfaces; see the HTTP API note.
The Pipeline
Section titled “The Pipeline”When a chunk of operations is submitted, each one:
- Validates against shape and structural constraints (preflight)
- Resolves wref references and stream-local tokens (
$N/#N) - Pins version references (bare wrefs → current HEAD version)
- Computes data hashes (server-side only — clients never compute hashes)
- Records a new thing version in its own transaction
A failed operation is recorded in the per-op results array. Successful operations earlier in the same chunk remain.
Operation Results
Section titled “Operation Results”A write request returns per-operation results:
{ "operationCount": 3, "partial": true, "statusCounts": { "applied": 2, "noop": 0, "error": 1 }, "operations": [ { "opIndex": 0, "name": "Sensor/temp-1@v1", "operation": "add", "version": 1, "dataHash": "abc123", "status": "applied" }, { "opIndex": 1, "name": "MissingShape/bad", "operation": "add", "status": "error", "error": { "code": "NOT_FOUND", "message": "Shape not found" } }, { "opIndex": 2, "name": "Sensor/temp-2@v1", "operation": "add", "version": 1, "dataHash": "def456", "status": "applied" } ]}Every operation row carries status (applied, noop, or error) on all
surfaces. Clean-success responses may omit the top-level partial and
statusCounts fields for backward compatibility. MCP may also omit opIndex
on rows from an ordinary clean-success response where result indexes match
local array positions; resumed submissions and partial responses always
include opIndex so callers can correlate every result with its submitted
operation. Idempotent revises (same data hash) return operation: "noop".
With skipExisting: true on an add, an existing target also returns
operation: "noop".
There is no commitId — graph history lives in per-thing version trails,
visible through wh thing history.
Subscriptions
Section titled “Subscriptions”Successful operations emit per-operation write events. Subscriptions match against those events to fire webhook calls or scheduled actions. See Subscriptions.
Key Rules
Section titled “Key Rules”- Per-operation atomicity. Each operation succeeds or fails on its own.
- Data hashes are server-computed. Clients store hashes from results and compare against DB values.
- Convenience wrappers exist (
wh thing revise,wh assertion create,wh thing retract) but they all call the same write pipeline. - Auditing is per-thing. Use
wh thing history <wref>for the version trail and attribution for each version.
Hit a problem or have a question? Get in touch.