Find the record that doesn't fit.
A Spotlight plugin for data.
Anomaly shows your agent which datasets cover your story and which checks fit them. It runs those checks and flags every record that stands out as a lead you can trace.
Records flow in from the sources an agent fetched. Detectors test every one, most pass straight through, and the few that don't fit come out as leads for a person to check.
Sources and detectors meet at a domain.
A domain is a type of data, such as lobbying or procurement. A source says which domain it covers, and a detector says which domain it reads. When a detector joins several tables, the domain publishes their shape, so any source that fills it works with every detector in that family. No source is ever wired to a detector.
Look through the catalogue.
The catalogue is every data source, domain and detector an agent can look up. It is generated from the repository, so what you see here is exactly what anomaly.context returns.
An agent asks the questions and code does the counting.
Anomaly sits between an investigating agent, such as Spotlight, and the data. The model chooses what to look at, and deterministic code computes every flag. Pick a step to see what runs there.
Ask
A journalist or agent starts with a question about a person, a company or a beat.
Look up
anomaly.contextlists the data for the domain and the detectors that fit it.Fetch
The agent gets the tables itself, following each source's SKILL.md.
Run
anomaly.oneshotruns the detector's SQL in a sealed DuckDB. The same tables always give the same result.Lead
Each flagged record comes back as a JSON line with its detector, inputs and parameters.
Gate
A person accepts or dismisses each lead. A detector never decides what's true.
Install it once, then three commands do the work.
Anomaly is a local Python package with no account, server or API key of its own. It needs Python 3.11 or later and uv.
git clone https://github.com/buriedsignals/Anomaly.git && cd Anomaly && uv syncuv run python -m anomaly.context --domain lobbyinguv run python -m anomaly.context --source global/opensanctionsuv run python -m anomaly.oneshot --table examples/donations.csv --request examples/zscore_request.json --approvedRequest format, domain detectors and every refusal rule are in docs/catalogue.md. The run command uses a small example in the repository and flags one donation. Without Spotlight, Anomaly can also run a full standalone case: see the README.
Join the Lab.
↳ now open
Indicator Lab
The Buried Signals tool suite, a monthly live workshop and Lab Newsletter, office hours every two weeks, and the training course.
$22.95/month · billed monthly, cancel anytime.
Join Indicator LabNewsletters
1,000+ journalists already reading.