Skip to content

Store and query records with the object store

MCPAPIIntermediate~15 min

The object store is the record-oriented surface over structured storage: an object is a node with an objectType, presented as a flat record { id, type, ...fields }. It's the friendly path for typed records — you do CRUD on fields, not on graph nodes.

This guide uses the object store from MCP (how an agent works) and GraphQL, on a competitor collection — the same example as the market-research tutorial. For the CLI, see Work with objects from the CLI; for the full contract, see Object store API.

Before you start

  • Hadron connected over MCP (an agent host like Claude Code) or GraphQL access.
  • A memory to write to — the examples use acme.com::market.
  • Recommended: a declared schema on the competitor collection (see Give a memory a structured schema). With a schema, writes are validated; without one, fields are free-form.

1. Create records

Create an object with its collection (type) and flat fields. key gives it a human-meaningful id; omit it for a generated one.

{
  "tool": "hadron_create_object",
  "memoryUrn": "acme.com::market",
  "type": "competitor",
  "fields": { "name": "Letta", "stage": "series-a", "fundingUsd": 12000000 },
  "key": "letta"
}
mutation {
  createObject(
    memoryRef: "acme.com::market"
    type: "competitor"
    fields: { name: "Letta", stage: "series-a", fundingUsd: 12000000 }
    key: "letta"
  )
}

Either returns the flat record:

{ "id": "019f7d…", "type": "competitor", "name": "Letta", "stage": "series-a", "fundingUsd": 12000000 }

On a schema-governed memory the fields are validated — a missing required field, an out-of-enum value, or a wrong type is rejected. id and type are reserved and can't be field names.

2. Query the collection

findObjects returns { objects, total } for one collection. Filter three ways — match (equality shorthand), where (full predicate), and sort.

The equality shorthand — every series-A competitor:

{
  "tool": "hadron_find_objects",
  "memoryUrn": "acme.com::market",
  "type": "competitor",
  "match": { "stage": "series-a" }
}
query {
  findObjects(memoryRef: "acme.com::market", type: "competitor",
              match: { stage: "series-a" }) { objects total }
}

The payoff query — series-A competitors funded over 10 million, highest first. match and where are AND-combined; where is the same grammar as hadron_find_nodes:

{
  "tool": "hadron_find_objects",
  "memoryUrn": "acme.com::market",
  "type": "competitor",
  "match": { "stage": "series-a" },
  "where": { "path": ["fundingUsd"], "as": "number", "gt": 10000000 },
  "sort": { "fundingUsd": "desc" }
}
query {
  findObjects(
    memoryRef: "acme.com::market"
    type: "competitor"
    match: { stage: "series-a" }
    where: { path: ["fundingUsd"], as: number, gt: 10000000 }
    sort: { fundingUsd: "desc" }
  ) { objects total }
}

limit and offset page the results; total is the full match count.

3. Update — a shallow merge

updateObject merges the fields you pass into the record: the patch wins, unmentioned fields are kept, and the merge is atomic server-side.

{
  "tool": "hadron_update_object",
  "ref": "019f7d…",
  "fields": { "stage": "series-b", "fundingUsd": 40000000 },
  "reason": "Series B announced"
}
mutation {
  updateObject(ref: "019f7d…",
               fields: { stage: "series-b", fundingUsd: 40000000 },
               reason: "Series B announced")
}

name survives because the patch didn't mention it. The merged result is re-validated against the schema.

Merge, not replace

updateObject merges; updateNode / hadron_update_node replaces the whole properties bag. Reach for the node op only when you want wholesale replacement.

4. Delete

Soft by default — the object disappears from reads but the row is retained. hard: true removes it permanently. Deletion is non-recursive.

{ "tool": "hadron_delete_object", "ref": "019f7d…", "hard": false }
mutation { deleteObject(ref: "019f7d…", hard: false) }

Objects are nodes

A record created here is the same node the graph APIs see: findNodes / hadron_find_nodes with objectType: competitor returns it, and hadron_validate audits it against the schema. Use the object store for record CRUD; drop to the node API when you need edges, content, or the loc hierarchy.