I took the history of a WhatsApp group of pilots’-course alumni — graduates of the Israeli Air Force flight academy — and turned 10,951 messages from February 2023 to June 2026 into a searchable site with 1,494 recommendations sorted into categories, including a count of how many people endorsed each one. The most interesting thing that came out of the project is a failure: I added a chatbot that knows every tip, the group was excited, and usage stayed thin. People use the ordinary search box.
The problem: WhatsApp is not built to retain knowledge
I am a member of a large community of pilots’-course graduates. Our group runs to several hundred people and it is an extraordinary asset — no request goes unanswered, from tips for handling the bureaucracy of Bituach Leumi (Israel’s national insurance institute) to recommendations for service providers.
The problem is that every tip disappears into the message stream within hours. The knowledge exists, it just isn’t retrievable. WhatsApp search helps only if you remember the exact word somebody typed two years ago.
The pipeline: from a stream to an index
The flow: WhatsApp’s own “Export Chat”, a script that parses the text file into structured JSON, a script that splits that first export — slightly smaller than the message count the site shows today — into 87 overlapping batches, then a multi-agent extraction pass that pulls the recommendations out of each batch. The overlap is not decoration: a recommendation in a group chat often spreads across several messages from several people, and a clean cut in the middle simply loses it.
The first extraction returned 2,436 raw tips. The interesting stage is the merge: when five people recommend the same mortgage adviser in three separate conversations over two years, that is not five tips — it is one tip with five endorsers. A per-category merge done by the model, plus a programmatic cross-batch combine, brought it down to 1,511 canonical tips in the first build.
Here is what the running version holds today:
| Category | Tips |
|---|---|
| Service providers | 497 |
| Finance and benefits | 433 |
| Bureaucracy and the state | 372 |
| Tips and guides | 192 |
Of the 1,494 tips, 824 carry contact details and 331 collected more than one endorsement. The record holder has nine: a discount on arnona (municipal property tax) for people serving miluim, Israel’s reserve military duty. That endorsement count is the most useful signal on the site, and it existed in no single message — only the merge created it.
The longest part was privacy, not extraction
The rule I converged on: the provider is public, the recommender is not. A provider’s name and phone number are shown in full — that is the recommendation. The recommender appears as a censored phone number plus initials, and personal numbers written inside free text are masked.
The less obvious decision: group-affiliation markers — Hebrew phrases like “one of ours” or “a member of the community” — count as a high-severity finding and block publication. Being identified as a member of this particular group is itself sensitive, even with no name attached.
Two scripts do the work: an idempotent last transform that runs over the data files before every deploy, and a read-only gate that exits with an error code if any high-severity finding survives. Idempotence is the point — the extraction masks the author field but not numbers written inside a summary or a quote, so every rebuild reintroduces the leaks. A one-off manual cleanup would have lasted exactly until the next run.
The privacy audit that produced those two scripts also surfaced a genuine bug: one provider’s phone number had been stamped onto 23 unrelated records by a merge step. Nothing in the output looked broken — every record read as perfectly plausible. That is the class of bug that eyeballing a sample does not catch, so it now has its own rule in the gate: if a rebuild reintroduces it, the build fails.
In the multi-tenant version I built afterwards — a local MVP, one control plane over two groups, with the site’s theme itself stored as data — the gate is a hard publish blocker: publish returns 409 for as long as a single high-severity finding exists. Warning-level findings, such as a provider’s number inside a paragraph, don’t block; they go into a review queue.
The Thursday refresh
A routine task refreshes the site from the new messages every Thursday. It is deliberately not autonomous end to end: it hands me the comments waiting on the site along with a recommendation, waits for a fresh chat export, reads the messages since the last update, proposes tips to add — and only deploys after I approve. The reason for the human step is that publishing something about a person that should not have been published is irreversible. The timestamp at the bottom of the site reads 9 July 2026 — which also shows the cost of that approval step: a week I don’t get to it is a week the site doesn’t move.
The chat everyone wanted and hardly anyone uses
The chat runs on Claude Sonnet through AWS Bedrock (I have a pile of credits there), inside a Lambda behind API Gateway. It has exactly one tool: search over the processed tips. The raw message corpus is deliberately not loaded into it — message bodies can surface members’ names. Rate limits per IP (ten questions an hour, twenty-five a day) plus a global daily ceiling keep a bored visitor from running up my bill, and questions are stored fully anonymously — timestamp, question, answer, no IP, no identity — which the interface says out loud.
Then: excitement in the group, thin usage in practice. What won was the search box — includes on a lowercased string over an array that lives entirely in the browser, debounced by 120 milliseconds. No server, no model, no cost.
My explanation, and this is interpretation rather than measurement: people arrive already knowing what they want — “mortgage”, “arnona” — and they want to see everything, immediately. The chat returns one paragraph after a few seconds and you have to trust that it didn’t miss anything. The search returns forty cards you can scan with your eyes in two seconds.
The rule I took away: put the model where the question is ambiguous or the answer has to be assembled. Where the user already knows the search term and the corpus fits in a browser tab, the model is a downgrade in disguise. Here it earned its place in extraction and merging — work that happens once, offline — not at query time.
Knowledge also goes stale
I ran a content audit across the corpus: 63 agents went through the tips one at a time, judging each on what it says rather than on how old it is, and flagged 174 as potentially no longer relevant. The largest cluster is time-bound events (72) — promotions, webinars and job posts whose date has passed — followed by superseded regulation (33) and one-off requests (25).
Of the 174 flagged I have removed 31 so far — the highest-confidence ones; the rest are still queued for a human pass. After that removal and the weekly additions since, the site holds fewer tips than the first build did, not more. That is the part it is easy to forget when building a knowledge base: a knowledge site that only ever grows eventually turns into a graveyard.
What is left of it
The value was not in the model, it was in the change of shape: from a stream into an index. The model was the only tool I know of that could do that extraction over spoken Hebrew full of typos and half-quoted threads, but it did it once, off to the side, and then left the picture. What stayed in the users’ hands is a list you can search.
If you have a group or an internal channel that accumulates knowledge and keeps losing it, this is what that work looks like when I do it.