OTO
tutorials

Ask the graph

oto query

and the served tools answer the same questions from the same store. This page goes through each one on the claims project from the complete tutorial, with the output it printed. Every answer carries a status, a date and a source.

The questions, and when to ask each

Ask When you want to know
entity <term> everything about one thing: its card, relationships, sources, evidence
entity <term> --history what it was before, with each validity window
entity <term> --as-of <date> what was true on a date
neighbors <term> [rel] what it is connected to, optionally along one relation
search <query> [n] which passages, cards and documents mention a phrase
by-type <Type> [state] every entity of a class, optionally by status
count · group <by> how many, and broken down by type, tag or attribute
docs [query] the documents behind the graph, and the ingest frontier
explain <term> which facts were derived by a rule, and from what
stale what was superseded, and by what
resolve <term> which id a label or alias points to
overview the whole graph in numbers
policy · pending · actions rule findings; what is on its way in; what can be done here

One thing, in full

oto query --project claims entity "Total loss settlement"
=== Total loss settlement  [Procedure]  (procedure.total-loss) ===
status=current  ·  as_of=2026-02-01  ·  valid_from=2026-02-01  ·  source_doc=total-loss-procedure
aka: total loss

A vehicle is declared a total loss when the repair estimate exceeds 70 percent of its actual cash value; ...

Relationships (incoming):
  Claims adjuster → performs
  Salvage coordinator → performs

Sources: total-loss-procedure

Evidence:
  - total-loss-procedure section 1: "A vehicle is declared a total loss when ..."

A term is a label, an alias or an id. When several entities match, the answer says so and lists the others.

Around it

oto query --project claims neighbors "Salvage coordinator"
oto query --project claims by-type Role
oto query --project claims count --type Procedure
oto query --project claims group type
Role (2):
  Claims adjuster  (role.adjuster)
  Salvage coordinator  (role.salvage-coordinator)
count = 2  (type=Procedure)
group by type — 16 nodes in 13 group(s):
      2  Document
      2  Procedure
      2  Role
      1  Assessment
      ...

By words, not by structure

oto query --project claims search "salvage" 3
Passage search: salvage
  -3.138  Salvage coordinator  ·  _Role_        cards/role__salvage-coordinator.md
  -3.073  Salvage coordinator                   entities/role__salvage-coordinator.md
  -2.723  Total loss settlement procedure       documents/total-loss-procedure.md

Search ranks passages from the entity cards and the documents. It needs no model: the passages are indexed at build time. Use it to find the entity, then entity to read it.

Over time

oto query --project claims entity coverage.collision --history
oto query --project claims entity Collision --as-of 2026-03-01
oto query --project claims stale

A correction made in conversation shows these three on a real supersession.

The documents

oto query --project claims docs
Documents (2)  ·  ingest frontier (latest as_of): 2026-03-28
  2026-01-01  Bulletin 2026-01  (doc.bulletin)
  2026-01-01  Operations handbook  (doc.handbook)

The frontier is the most recent date any fact carries. An answer about something after it is an answer the graph cannot give yet.

Derived facts

oto query --project claims explain procedure.total-loss
Nothing about Total loss settlement (procedure.total-loss) is derived; every fact shown is asserted by a document.

When a rule derived a fact, explain names the rule and the facts it was derived from. Rules says what a derived fact is.

The same questions, for an agent

oto serve --project claims --http 8765
curl -s http://127.0.0.1:8765/rpc -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
kg_entity  kg_neighbors  kg_count  kg_group_by  kg_search  kg_by_type  kg_explain
kg_policy  kg_overview  kg_stale  kg_resolve  kg_pending  kg_actions  kg_docs
curl -s http://127.0.0.1:8765/rpc -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"kg_entity","arguments":{"term":"Salvage coordinator"}}}'

The tool returns the same card the terminal printed. GET /api/graph returns the whole graph as one JSON document, which is what the explorer and any view read. Without --http, the server speaks over stdio, which is how Claude Code connects.

Two stores, one answer

oto query --project claims --backend neo4j entity "Total loss settlement"

The local SQLite build is the development store; a configured Neo4j is the production one. Both answer alike, and a test in the engine holds them to it.