Indra¶
Helmi's context service — a standalone building block that turns raw sources into resolved entities and the claims made about them.
Named for Indra's net: an infinite net with a jewel at every vertex, each jewel reflecting every other. Which is the shape of the thing.
What it does¶
Sources arrive (meeting recordings, calendar events, emails, documents, notes) and are composed into Events. Events are parsed and chunked, then an LLM extracts partial entities — each carrying claims about who or what it is. Claims are either hard (queryable and normalizable: email, domain, alias, language, nationality) or soft (free-form, deferred). Hard claims are then normalized into an indexed, queryable projection.
Downstream of that sits entity matching and resolution — partial entities matched against existing ones, or left unresolved until enough context arrives to promote them to canonical.
Design lives on the team's Excalidraw board; it was drawn by hand. The written record:
PRD (what and why),
domain (the words and the invariants),
scenarios (worked cases the model must satisfy),
architecture (how),
interfaces (the contracts each module owner builds against).
make docs renders all of it, plus the changelog, as a browsable local site.
Scope¶
Everything through claim normalization is in scope now. Entity matching and resolution are deliberately last — they get designed against the distribution of data we actually extract, not guessed in advance.
The two open questions there (what threshold counts as a match, and what constitutes critical mass for promoting an unresolved entity) can only be answered from real numbers: hard-claim yield per source type, how often a partial entity carries an identifying claim, alias collision rate, candidate-set size per claim type. Producing those numbers is a deliverable, not a side effect.
Principles¶
- Data is never destroyed, only composed. Sources are immutable. Re-ingesting identical content is a no-op; changed content mints a new row. Every stage's output is keyed by its input and its version, so anything can be re-run without overwriting what came before.
- Multi-tenant and scope-aware from the first migration. Not retrofitted.
- Two LLM stages, nothing else. Summarization (source and event situating context) and extraction are the only stages that touch a model, and both are versioned and re-runnable. Ingestion, composition, parsing, and normalization are deterministic and testable without one.
- API-first. Callers push sources; the service owns identity, claims, and the review surface. Products own UX, the service owns truth.
Stack¶
Python 3.12+, FastAPI, pydantic v2, Postgres, SQLAlchemy 2 + Alembic.
Python because entity resolution as a field lives there — splink, dedupe,
recordlinkage, probablepeople, jellyfish, rapidfuzz have no counterpart
elsewhere — and because this service is mostly schema, which pydantic models once
and serves to the database, the API, and the extractor alike.
Status¶
Empty. Nothing built yet.