Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Browsing the Index

Browsing is how you reach an exact record and everything connected to it, with no loss and no ranking in the way. It is the deterministic half of lmmol — and, for LLM agents, often the more useful half. This chapter walks the index top-to-bottom.

The shape of the index

index.json                          the root: types, counts, where to go
  └─ index/list/<type>/root.json     a type's listing: count + shard list
       └─ index/list/<type>/<n>.json  one shard: up to 1000 {id, name}
            └─ nodes/<type>/<id>.json  the entity itself (+ forward edges)
                 └─ index/.../<id>.json  backlinks: who points *at* it

Each level is a plain static JSON file. You can crawl the whole thing with nothing but an HTTP client and the rules below.

1. The root

curl https://lmmol.com/index.json

The root lists every entity type, its count, and the navigation into its listing. Use it to discover what exists and how big each set is before you crawl.

2. Listings (paged by shards)

A type can have hundreds of thousands of entries, so listings are sharded into files of up to 1000 entries each.

# How is the protein listing sharded?
curl https://lmmol.com/index/list/protein/root.json

root.json gives you the total count and the list of shards. Then fetch a shard:

# The first shard: up to 1000 {id, name} pairs
curl https://lmmol.com/index/list/protein/0.json

Each shard entry is a compact { "id": "...", "name": "..." }. That is enough to show a list, pick an id, and drill in — without downloading full nodes. To enumerate an entire type, iterate shard 0.json, 1.json, … up to the count.

3. Nodes (the entities)

Once you have an id, fetch the node:

curl https://lmmol.com/nodes/protein/P38398.json

A node carries its name, synonyms, attributes, outbound_source_links (URLs to the authoritative records), and its forward edges — its own cross-references out to other entities. See Concepts & Terms for the full field list and the edge shape.

Forward edges answer "what does this entity point to?" For the reverse — "what points at it?" — use the backlink indexes.

Edges stored on a node are one-directional. The cross-reference indexes give you the inbound side, so the graph is fully navigable from any node, in any direction.

Disease → its proteins and trials

curl https://lmmol.com/index/disease/MONDO_0016419.json
# -> { "proteins": [...], "trials": [...] }

This is the join that the Mondo normalization makes possible: a protein's disease and a trial's condition resolve to the same Mondo id, so this one file gives you both sides at once.

Gene → its proteins

curl https://lmmol.com/index/gene/BRCA1.json
# -> { "proteins": [...] }

Clinical associations (ClinVar)

Gene ↔ disease links backed by clinically-significant variants, each carrying a significance label (e.g. Pathogenic, Likely pathogenic):

# Diseases associated with a gene
curl https://lmmol.com/index/clinvar/gene/BRCA1.json
# -> { "diseases": [ { "id": "MONDO_...", "name": "...", "significance": "Pathogenic" }, ... ] }

# Genes associated with a disease
curl https://lmmol.com/index/clinvar/disease/MONDO_0016419.json
# -> { "genes": [ { "symbol": "BRCA1", "significance": "Pathogenic" }, ... ] }

Browsing as an alternative to vector RAG

Vector RAG embeds a query, fetches the nearest chunks, and hopes the right facts landed in the window. The browse index removes the guesswork: every fact is reachable by following ids and paths — no embeddings, no similarity threshold, no truncation, nothing hidden. For an LLM agent that already knows an entity (a gene symbol, an accession, a Mondo id), the most reliable retrieval is not a similarity search — it is:

nodes/<type>/<id>.json           # the record, exactly
index/disease/<id>.json          # everything linked to it, exactly
index/clinvar/gene/<symbol>.json # the clinical associations, exactly

No relevance score can lose a record this walk would find. Search (next chapter) is one optional entry point into this graph for when you only have a fuzzy description — not a replacement for it.

A complete walk

A worked example: start from a disease, collect its proteins, and read one.

# 1. The disease's neighborhood
curl https://lmmol.com/index/disease/MONDO_0016419.json

# 2. Pick a protein id from the "proteins" array, then read it
curl https://lmmol.com/nodes/protein/P38398.json

# 3. Follow that protein's gene, then the gene's clinical associations
curl https://lmmol.com/index/clinvar/gene/BRCA1.json

Three deterministic hops, no ranking, no loss. Recipes turns walks like this into reusable scripts.