replai
The story
A firm came to us with fifteen years of service history locked inside a CRM nobody had touched in a decade, and a question that sounded simple: could the people answering their mail be given something that already knew all of it.
The answer turned into three products that ship together. A pipeline that gets that history out of a legacy system and into a queryable index. replai, an email assistant that reads an incoming mail, retrieves what the firm already knows about it, drafts a reply grounded in that evidence, and then stops, every draft waits for a person. And chatty, a hard fork of an open-source chat product, rebuilt to run inside the same network on the same identity and the same models.
The one constraint that shaped everything
On-premises is not a deployment preference here, it is the point. The mailbox, the documents, the CRM history and every model stay inside the customer's own network. That single requirement decides more than it looks like it does: it rules out every hosted embedding API, it makes a GPU a capacity planning problem rather than a line item, and it means the interesting engineering is in what you can build with a llama.cpp container and a Postgres instance rather than in which vendor to call.
It also makes the guardrails enforceable instead of aspirational. The model runtime refuses to start against an endpoint that resolves to a public address. A hard fork of a chat product had an outbound code-fetching path removed because a product whose premise is that nothing leaves the network cannot ship one. Those are tests and startup checks, not paragraphs in a policy document.
Three things that happened more than once
The articles below read forward, in the order the work happened. But three patterns run the whole length of it, and they are the part I would actually want somebody to take away.
A certificate the firm cannot issue. It closed the SOAP route into the legacy CRM before the project properly started, because an NTLM channel binding needed one. Five weeks later it killed the mutual-TLS transport carrying logs between two hosts, and an SSH tunnel went in instead. Then it decided how the identity provider is reached, and produced a chat session that died fifteen minutes after every apparently successful login. Four dead ends, four different technologies, one organisational fact, and I did not recognise it as the same thing until the third time.
Controls that report success. A collection that answered "no attachments" when it meant "not enumerable on this build". A cache key that would have paid for a hundred thousand model calls and matched none of them, with nothing logging a problem. A retrieval source created, tested green, acknowledged, enabled, and never once queried. A log tunnel running healthy with zero bytes through it. A tool-approval policy that was both unreviewable and inert. Every one of them passed its own check.
Measurements overruling documents. Fourteen seconds of profiling invalidated most of a written specification, including a chunking rule that was inverted. A backfill documented at seven minutes turned out to take three and a half hours once somebody asked which machine the number came from. A design was specified in full and then shelved by a disk measurement. An eval set was 57.1% unusable, and benchmarking against it unfixed would have selected the model best at retrieving invoice references.
That last pattern is why the final article is about tests whose subject is the documentation rather than the code.
How I think about it
- Measured, not assumed. Almost every decision in these articles was settled by profiling the real corpus or timing the real server, and several of them overruled a written specification. Where a number appears below, it was measured.
- The failures are most of the value. A SharePoint 2010 farm fails in ways no documentation predicts, and an error message that is true of every possible cause is worse than no error message at all.
- Nothing sends itself. Every draft this system writes needs a person to accept it and a second, separate confirmation to put it on the wire. That is a design commitment, not a missing feature.
Three parts: the pipeline that gets the history out, replai built feature by feature on top of it, and the fork that shares its identity and its design.
Articles
I · The pipeline · 10 articles
- Fifteen years of history, and one door into it2026-07-16
- A 401 has six meanings, and only one of them is the password2026-07-19
- The same service answers in two languages, and both answers are right2026-07-22
- A server that refuses to count, and the query that ran at five rows a second2026-07-25
- The empty feed that wasn't empty2026-07-28
- I profiled the corpus and it overruled half the specification2026-07-31
- L0 to L3: files, not a database2026-08-03
- Turning reasoning off was worth 46×, and the cache key that would have thrown it all away2026-08-05
- 16,400 files nobody has validated in fifteen years2026-08-07
- Two retrieval arms, and a harness built to refuse a number2026-08-09
II · replai · 10 articles
- On-premises from the first commit, and the guardrail that catches the cloud metadata address2026-08-12
- Ten formats, one chunker, and the header that would embed itself twelve times2026-08-15
- One mail becomes one draft, and only one of the nine stages is the model2026-08-18
- Every draft arrives with a verdict on itself, and no model wrote it2026-08-20
- Two decisions before anything leaves the building2026-08-22
- Does confidence predict how much you changed?2026-08-25
- A foreign hit earns its place, or it does not arrive2026-08-27
- Logs that scrub themselves, and the three holes the allow-list does not close2026-08-29
- The certificate that did not exist, twice, and three unauthenticated servers that used to be safe2026-09-01
- The customer has no IT department, and the only admin surface was a Python shell2026-09-02
III · The fork · 4 articles
- One account for two products, and a refusal that has never fired2026-09-03
- A hard fork, and the five inherited defaults that pointed out of the network2026-09-05
- One design system, two products, and the colour they deliberately do not share2026-09-07
- What an on-premises promise has to be written down as2026-09-10