the lab · LetMeCheckThatBot
LetMeCheckThatBot.
It turns the group chat
into the interface.
Every group chat has the same dead moment: someone makes a claim, nobody believes it, and to settle it one person leaves the conversation, googles it, and pastes a link into a room that has already moved on. LetMeCheckThatBot does that part for you, in the thread. You say robot, is that actually true, and it fact-checks the claim to your face, with a source, before the moment passes.
It is the second of two agents I run in the open, the opposite shape from Penny. Penny works alone, for one person. This one lives in a Telegram group as its most useful member: anything you would leave the chat to look up, read, find, or hear, it does right there, so nobody leaves.
It is quiet by default. You summon it by saying robot, so it never noises up a room it was not invited into. Then it does the two jobs the room actually wants: it settles the argument with a citation, then memes the chat about it.
I designed and built it around one product decision: the conversation stays the interface. That forced the system to ingest every modality silently, retrieve old context quickly, choose when not to speak, and keep the model bill under a hard cap. It has run long enough for those choices to become operating constraints instead of demo decisions.
It reads every kind of message, and answers in every kind.
Text is the easy part. The bot turns every artifact that lands in the room into text on the way in, keeps it all in one memory, and answers back in whatever format the moment wants.
- text
- read in place
- voice note
- Whisper, to a transcript
- photo, screenshot
- vision, read word for word
- pasted link
- headless browser, full page
- video link
- yt-dlp, title and transcript
- video, GIF
- sampled into frames
- any file
- contents pulled in
- an answer
- in the thread, with a source
- a video or clip
- found and posted as the file
- a meme
- built and dropped in
- a voice memo
- spoken aloud, on the laptop
- a quick poll
- an either-or, to the room
- a flashback
- the room's best day, after a week quiet
One memory in, one voice out. Everything below is the records.
Four real exchanges. Actual screenshots.
Not mockups. Screenshots from a live group: settling a myth with a source, posting a video, meme-ing the chat, answering out loud in a voice memo. Click through, or let them rotate.
The reason it works is that it never stops reading
This room does not talk in text. It talks in voice notes, links, screenshots, and videos, so the bot treats every artifact as readable, each turned into text the moment it lands and filed away, with no reply. That silent reading is the trick, because the question almost always arrives weeks after the thing it is about.
The trace below is the minute that explains the whole bot. A voice note and a menu photo go by without a peep. Weeks later, robot, what was that thai place from like a month ago searches the whole history by meaning.
That is the part that took the work. The persona was cheap: I wrote it once and have barely touched it. Reading every artifact as it lands, then finding the right one out of tens of thousands later, is what makes it a member of the room instead of a search box you @-mention.
It has run daily since 2022, on the room's own message count
The room has passed 92,000 messages as of July 2026, all read, transcribed, and remembered. The chart below is the first 87,787 through June 2026, drawn by the bot on request.
All of it runs on a key hard-capped at $5 a month, less than a Telegram Premium subscription, and the cap has never been hit. A multi-user agent that reads everything, remembers everything, and answers in its own voice costs less than the chat app it lives in.
A $5 cap invites a fair question: is a model this cheap any good? I measured it against GDPval, OpenAI’s set of real professional work. The $5 model came within eight points of the experts, 76 to their 84 in a standard setup. The jobs and scores are in the benchmark explorer, with the method below.
Drop a link and it looks at the actual page.
Drop a link and it does not guess from a search snippet. These four are live full-page grabs through the bot’s own browser, including this page.
How it reads a link, and a video, and an image the translator layer
Each kind of artifact gets its own reader, and they all output the same thing: text. A pasted link is fetched and opened in a headless Chromiuma full web browser running invisibly, with no window, driven entirely by code., scrolled the whole way to wake the lazy-loaded parts, and captured top to bottom. If the link is a video, yt-dlpan open command-line tool that pulls a video’s title, description, and transcript. pulls its title, channel, description, and transcript. A screenshot or image is handed to a vision modelan AI model that can look at an image and read or describe what’s in it. that transcribes the words inside it verbatim. A video or silent GIF is sampled into frames and read across them. A shared file has its contents pulled in. A voice note nobody played goes to a local Whisperan open speech-to-text model that turns voice notes into text. container and comes back as a transcript. Once everything is text, one memory holds it all, and the bot can answer about a menu photo or a music video the same way it answers about a typed line.
This is why ingest happens the instant a thing lands. The question arrives weeks after the artifact. If the voice note was not transcribed on arrival, the answer is not there when someone asks what that restaurant was. Silent ingest is the whole memory.
Under one diagram: read everything, answer on call
The whole system has two halves: read everything while the room is talking, answer only when someone calls it. The diagram below is the whole machine.
One agent, a loop, nineteen tools the answering half
The core is the primitive Penny uses and the one Anthropic argues for in Building Effective Agents: an augmented model in a loopthe whole architecture in five words: one AI model that can read, decide, and call tools in a repeating cycle until it has an answer.. The bot reads the recent thread, decides whether to act, and if it acts it calls a toola capability the model can invoke on its own: search the web, read a link, build a meme, look up a memory., reads the result, and decides again, up to four passes before it owes the chat an answer. There are nineteen: it searches the web, reads and screenshots links, digs through Reddit, finds a video and clips the part that matters, builds memes and gifs, reads images and the text inside them, transcribes voice notes with one local Whisper container and answers out loud through another, synthesizing its reply into a Telegram voice memo with a local Kokoroan open text-to-speech model; it generates the spoken voice locally on the laptop with no cloud call. model, recalls the chat’s own history by meaning, and can even put a quick either-or to the group.
One detail earned its place the hard way: not every model honors the function-callingthe standard way a model asks to use a tool: it emits the tool’s name and arguments in a fixed, machine-readable format. contract, so the loop carries a recovery path that parses malformed calls back into real ones instead of giving up. That single piece of defensiveness is the difference between a loop that works on one model and a loop that works on whatever model I drop underneath it.
How the memory actually works SQLite, local embeddings, indexed recall
The moment a message lands and the translators have turned it into text, the row is handed to a single background worker. The worker calls a local embedding model, Qwen3-Embedding-0.6B quantized to Q8shrinking a model’s numbers so it runs on modest hardware, trading a sliver of precision for speed and size., running on Ollamaa tool for running AI models locally on your own computer, with no cloud and no per-use bill. on the same ThinkPad, and gets back a list of 1,024 numbers: the message’s coordinates in meaning-space. That vectora list of numbers that captures a message’s meaning, so similar ideas land near each other. is written straight into the message’s own row in SQLitea tiny database that lives in a single file on disk, with no separate server to run., next to the text. There is no separate vector database and no embedding API. The worker takes one call at a time so it never crowds the GPU that Penny is also using, and the whole thing costs nothing per message.
A hosted embedding API would have quietly turned more than 92,000 messages into a recurring bill, which is most of why this runs locally. Cost is the smaller half. The bigger half is dependency: a model on my own shelf cannot raise its price, deprecate its weights, rate-limit me, or go down at the wrong moment.
Recall does not pick between keyword and meaning, it blends them. It embeds the question once, uses a binary-quantized sqlite-vec indexa vector-search extension inside the same SQLite file. It narrows the room to the most likely candidates without adding another database service. to retrieve candidates from that room, then re-scores those candidates against the full 1,024-dimension vectors before merging the strongest hits with exact keyword matches. So “that thai place” finds the right night whether you remember the words or only the feeling. The index stays inside the same SQLite file, so search is fast without adding another service. The full vectors remain the durable asset; the index is replaceable.
It also sketches each regular from their own messages, so it knows who is in the room before it speaks. The result is a multimodal RAGretrieval-augmented generation: fetch the few relevant memories first, then answer from them, instead of guessing. “Multimodal” means it works for images and audio too, beyond plain text. over the group chat: the room’s whole history, in every modality, instead of the last fifty lines.
One primary model, two narrow fallbacks, and why it is this cheap MiMo v2.5 over OpenRouter
The bot reaches models through OpenRouter. MiMo v2.5 remains primary because it tool-calls reliably, holds a large contextthe context window: how much text the model can hold in mind at once. A bigger one means it can read more of the room before answering., and stays within a dedicated key hard-capped at $5 a month. Gemini 2.5 Flash Lite is the hosted fallback for a provider or model failure. If both hosted paths fail, a small local Functionary model can answer from local knowledge with a narrowed tool set. This is not the old budget cascade that quietly traded quality for price. The fallbacks protect availability, not a silent downgrade.
A $5 cap invites an obvious question: is a model this cheap any good? So I measured it. I gave the same model real work from GDPval, OpenAI’s set of actual job tasks across 44 occupations, each with a human professional’s own finished work and an expert grading checklist. Then Claude Sonnet 4.6, a model from a different company, scored its work and the human’s the same way. I ran one task from each of 44 jobs. The standard setup averaged 76, this bot’s harness averaged 70, and the human experts averaged 84. It also failed quietly: asked to build a musician-payroll spreadsheet it produced a flawless one with every pay rate off by about a dollar, so every paycheck was wrong. The failures look like finished work. The narrow, real thing it proves is that the floor for this kind of work is higher, and far cheaper, than it looks. Every task, output, and score is published, so you can judge it yourself in the benchmark explorer.
When the room goes quiet, it hands back the room’s best day
Everything above keeps people in the chat while they are talking. This is the move after they stop. After a week of real silence, the bot does not post a hollow “miss you guys.” It reaches into the room’s own past and hands back its best day, in the room’s own words.
Why it waits a week, then speaks first the trigger, the payload, the silence
A bot that pings on a schedule is noise. So the trigger is a dying room: a full week of real silence, never the calendar. The payload is the room’s own best day, this same day in an earlier year, posted back as a flashback in everyone’s own words. The notification is suppressed, so it surfaces only when someone next opens the chat. You find it; it never pings you.
It argues in memes too six, in its own voice
The fact-checks above are text. The other register is the image: when words will not do, it builds a meme through memegen.link and drops it in the thread. Six below, in the format it posts, one for each thing it is actually for: staying in the room, remembering everything, the trigger word, pulling records, reviving a dead room, and costing almost nothing.
LetMeCheckThatBot grew out of Everything Bot, an earlier, still-public version of the same idea: an agent that lives in a group chat, answers when summoned, and remembers the thread. This is where that idea got hardened into something I run every day.
The fastest way to understand it is to put it in a chat.
It is free, it never leaves the thread, and you can remove it in two taps. Say robot, then ask.