Chronos - The AI Co-Historian
Working with an archive is, for the most part, an exercise in patience. A single volume can hold several hundred pages of blackletter type or handwriting, and the facts a researcher actually wants - who lived where, which goods were traded in what house and so on - sit across thousands of short, near-identical entries. Reading them is slow and turning them into structured data which you can sort, count, or place on a map is even slower, and honestly: it is the kind of work that often never gets finished.
To take on that mechanical labour without taking over the scholarship behind it we built Chronos: The AI Co-Historian. It is an AI agent that sits alongside a historian and does the boring parts of the job: converting scanned page into structured records, finding streets on old maps, and cross-reference entries across different sources. Chronos does not replace the researcher’s judgement but unlocks a smoother way of interaction with the primary sources.

A real concern when using AI for historical applications is that the models misread old type, quietly invent plausible-looking details, and fabricate complete sections. Rather than hiding that, we deisgned Chronos around it. Every record produced by Chronos can be traced back to the exact bounding box of the scan it came from. When the agent reports e.g. that a wine merchant named Abendantz traded in the Papagaygasse, it can show you the exact position in the primary source that says so - allowing you to inspect and correct potential errors. This design makes the collaboration between Chronos and you interactive and trustworthy: you can always check the work against the page in the split of a second.
In the rest of this article we will demonstrate a small scale demo project from beginning to end, because the easiert way to explain Chronos is to show how you can work with it.
The merchant register and the map
The project begins with two scans, both digitised by the Universitätsbibliothek Johann Christian Senckenberg in Frankfurt.
The first is the Handlungs-Adreß-Kalender von Frankfurt am Main auf das Jahr 1812, a commercial address calendar of the kind most German cities printed each year. It is part almanac, part business directory, part postal timetable, and it runs to 168 scanned pages set in Fraktur. At its heart is an alphabetical list of the city's merchants and manufacturers. Each entry is terse: a name, a street, and a phrase describing what the person dealt in.

The second is the Geometrischer Grundriss von Frankfurt am Mayn, an engraved city plan from 1811. It is a single sheet so finely worked that the scan measures nearly eleven thousand pixels across. It names hundreds of streets, squares, inns, gates and churches directly on the plan, and a legend divides the city into fourteen quarters.
Put side by side, the two sources almost ask to be joined. The directory knows who traded what, and gives an address; the map knows where those addresses actually are. Neither, on its own, can show you the geography of commerce in the city, but together they can reveal meaningful insights.
Reading the directory
The first thing we usually do when analyzing a book with Chronos, is to get a rough overview over the source. So we instructed Chronos to get an overview of the trader directory it sampled pages across the volume. Chronos then spawns many sub-agents that follow Chronos’s prompt to describe a single page each.

Based on these summaries Chronos reads through the book, sampling across sections rather than reading every page. Using this method Chronos reconstructed the table of contents of our commercial address book and, just as importantly, the page numbering. The first few pages are unpaginated, but once the printed page numbers begin they sit a fixed distance from the scan numbers, until later in the book a couple of unnumbered insert leaves slip in.
This is the resulting table of contents:
Now that we know that the interesting pages are scans 35-86 we can start extracting entries. Looking at the first page we can observe a clear structure. Every entry has a name, street and a description of the wares they sell.

Then we instruct Chronos to these entries of every page using a specific json schema:
{
"name": "Johann Valentin Albert",
"street": "in der Döngesgasse, am Liebfrauenberg",
"house_number": null,
"quarter": null,
"trade": "mit Galanterie= Kunst= und Spielwaaren, en gros und en détail …",
"raw_text": "Johann Valentin Albert, in der Döngesgasse, …",
"page": 35,
"printed_page": 1,
"bbox": { "x":0.14, "y":0.31, "w":0.72, "h":0.06 }
}The schema does two jobs. Firstly it tells the model precisely what to pull out of these sixty pages. Secondly it carries the bbox property - the position of the entry on the page, in fractions of the page's width and height - which is what later lets any record be shown back on its source. The bounding box is what introduces provenance into the system. Using the specialized data viewer in Chronos you can easily jump to each image crop to verify if the retrieved data is correct.
Chronos worked all pages in parallel and extracted the 871 entries. The outcome still required some post processing, because the merchant’s entries occasionally ran over a page break, so its final line appears at the very top of the next scan, but after a few messages back and forth Chronos solved this issue as well, fixing broken entires across the break, so that e.g. Fahr-thor became Fahrthor again.
What the directory can now tell us
Once the merchants are structured records rather than printed lines, you can start asking the source questions. The simplest is also the most revealing: what did these people actually trade in? Chronos sorted each entry’s description into eighteen broad categories. Setting aside the entries that name no goods at all, the commercial character of the city comes through clearly.

Textiles dominate, and by a wide margin - cloth and silk together account for more dealers than the next two categories combined, which fits Frankfurt’s long standing as a textile market. Behind them sit the colonial-goods grocers, dealing in spices, coffee and sugar, then the wine trade. The category that rewards a second look is the cluster of bankers and bill-brokers: fifty firms whose business was money rather than goods, an early glimpse of the financial city Frankfurt would become.
Where they clustered
A second question is geographic even before any map is involved: where were these businesses? Sorting the same records by street shows how tightly commerce concentrated.
A handful of lanes - the Fahrgasse, the Döngesgasse, the Schnurgasse - hold far more merchants than anywhere else, seeming to be the hot spots for traders.
Placing the merchants on the 1811 map
Georeferencing usually means assigning a real-world latitude and longitude. Here goal is narrower: we want to place each merchant at the right spot on the 1811 map.
The difficulty is that the map does not come with a search function - after all its just a picture. So the first task was to build that missing index - a gazetteer.

Chronos cut the enormous sheet into a grid of tiles small enough for a vision model to read carefully, and worked through them one at a time, recording every label it could find together with its position. The result was a catalogue of 456 named features - 147 streets, but also squares, inns, gates, churches and individual buildings - each tied to a coordinate on the plan.
Matching the directory’s addresses to that catalogue sounds straight forward but is full of small traps. The same street appears as Mainzergasse in the directory and Mayntzer Gasse on the map; addresses arrive wrapped in prepositions and house-sign names, as in “in der Döngesgasse, am Liebfrauenberg”; the long ſ and the ß have to be normalised before strings can be compared. Chronos worked it way from exact matches outward to looser ones - prefix, then substring, then fuzzy similarity - and kept a hand-curated table of known aliases so that spelling variants did not silently get dropped.
Loose matching, though, is where a pipeline like this can start halucinating, so every placement was checked again. For each located street Chronos took a tight crop around the proposed spot, looked again, and nudged the point onto the centre of the actual label. The verification pass earned its keep: one entry had matched the “Berg” buried inside Römer Berg and landed in the wrong place entirely, and then was thrown out. Repeated close-up passes also settled a more deflating truth - that the smallest lanes, the Borngasse and the Kruggasse and a dozen others, are simply not labelled on the 1811 sheet, however hard one looks.
In the end 468 merchants were placed and confirmed - about four in five of the entries that had a usable address - alongside twenty locations drawn from the postal section. The hundred or so that remain unplaced are less failures of effort than honest gaps: streets the engraver never named, or entries that gave a house sign and no street at all. Plotted all together, the located merchants trace the same commercial spine the street counts had hinted at, now as visible geography.
Building something a historian can use
A dataset that lives only in a JSON file is quite hard validate. The last thing Chronos did was turn the results into a small web application, overlaying the geo-located traders, the original source crops and the map.
Go ahead and check the website out for yourself if you want!
If this blog post motivated you to learn more about Chronos, that’s great! You can find the open-source code on our Github (make sure to leave a ⭐) or join our Discord if you have any questions.
Every Tuesday at 11:00 am CEST, Niclas Griesshaber and Lorenz Hufe are available for questions on Discord are available for Q&A, installation help, and general discussions about AI for history.






Looks great Lorenz! I liked this part: 'Chronos then spawns many sub-agents that follow Chronos’s prompt to describe a single page each.' I suspect it could work for Newton papers too at some point 😀