Work with objects (structured records) from the CLI¶
The hadron object command group is the collection-oriented CRUD-and-query
surface over structured storage. An
object is a node with an objectType, presented as a flat record
{ id, type, ...fields } — so you work with typed records, not graph nodes.
Reach for it when a memory holds many records of the same shape (competitors,
invoices, incidents) and you want database ergonomics from the terminal:
create / get / update / find / delete. This guide walks all five on a
competitor collection — the same example as the
market-research tutorial.
The same object store is on GraphQL and MCP too — see
Object store API.
Before you start¶
- The
hadronCLI, installed and signed in — see Install the hadron CLI. - A memory to write to. The examples use
acme.com::market. - Recommended: a declared schema on the
competitorcollection (see Give a memory a structured schema). With a schema, writes are validated against the collection; without one,objectTypeand fields are free-form.
The flat-record model¶
An object is { id, type, ...fields }:
idandtypeare the reserved envelope — they can't be field names.- The node's typed
propertiesare the top-level fields. locandnameare auto-derived and hidden.
--key sets a human-meaningful natural id — a single loc segment, no : —
and you can omit it for a server-generated id. So --type competitor --key
letta lands at node loc competitor:letta, addressable by the node URN
acme.com::market::competitor:letta.
1. Create¶
object create takes the collection (--type) and the fields as a JSON
object (--fields, or --fields-file to read from a file):
hadron object create -m acme.com::market --type competitor \
--fields '{"name":"Letta","stage":"series-a","fundingUsd":12000000}' \
--key letta --json
{ "id": "019f7d…", "type": "competitor", "name": "Letta", "stage": "series-a", "fundingUsd": 12000000 }
On a schema-governed memory the fields are validated against the collection —
a missing required field, an out-of-enum value, or a wrong type is rejected
before anything is written. Omit --json for human-readable output;
--name overrides the auto-derived node name.
2. Read — get¶
Read one object by its id (the value printed on create) or its node URN:
Both print the same flat record. A ref that names nothing readable — or a node
that isn't an object — is a clean not-found (exit code 4), not an error.
3. Update — a shallow merge¶
object update merges the fields you pass into the existing record: the
patch wins on a key collision, and unmentioned fields are preserved. The merge
is atomic server-side.
hadron object update 019f7d… \
--fields '{"stage":"series-b","fundingUsd":40000000}' \
--reason "Series B announced" --json
{ "id": "019f7d…", "type": "competitor", "name": "Letta", "stage": "series-b", "fundingUsd": 40000000 }
name survived because the patch didn't mention it. --reason is recorded in
the object's revision history.
Merge, not replace
This is the key difference from node update --properties, which
replaces the whole properties bag. object update --fields merges.
If you want replace semantics, drop to the node layer.
The merged result is re-validated against the schema, so a merge can't leave a record in a non-conforming state.
4. Find — query a collection¶
object find (alias ls) queries one collection and prints the matching
objects plus a total. Three ways to filter:
--match— an equality shorthand: a JSON object{ field: value, … }, ANDed into aneqpredicate per field (the comparison type is inferred from the schema).--where— the full structured predicate, the same JSON grammar assearch --where. AND-combined with--match.--sort— a single-field shorthand:{ "<field>": "asc" | "desc" }.
The equality shorthand:
The full predicate — series-A competitors funded over 10 million, highest first (the market-research payoff query, from the terminal):
hadron object find -m acme.com::market --type competitor \
--where '{"and":[
{"path":["stage"],"eq":"series-a"},
{"path":["fundingUsd"],"as":"number","gt":10000000}
]}' \
--sort '{"fundingUsd":"desc"}' --json
--limit and --offset page the results.
5. Delete¶
object delete (alias rm) is soft by default — the object disappears
from reads but the row is retained. --hard removes the row permanently.
Deletion is non-recursive; an object is a single record.
--yes skips the confirmation prompt (use it in scripts and agent runs).
Which layer? object vs. node¶
object and node write to the same substrate — an object is a node
with an objectType. Pick by what you're doing:
Reach for hadron object when… |
Drop to hadron node / hadron search when… |
|---|---|
| You want flat typed records — CRUD by field, query by value. | You need the graph: edges, loc hierarchy, or non-record nodes. |
You want merge-on-update (update --fields). |
You want replace-on-update (node update --properties). |
| The record is self-contained. | The node carries content/markdown, edges, or children. |
The node-level structured surface (node --object-type / --properties,
search --where / --sort-property) is documented in the
hadron CLI reference and
Structured storage and queries.
Related¶
- Give a memory a structured schema — declare the collection the objects validate against.
- Query nodes by their properties — the
wheregrammarobject find --wherereuses. - Build a market-research agent with structured memory — the same competitor example, across every surface.
- Object store API · Store and query records with the object store — the same five operations on GraphQL and MCP.
- Structured storage and queries — the full contract and the surface matrix.