← Journal
Tech·May 19, 2026

What were we talking about last time?

A closed notebook and a smartphone with a dark screen side by side on a pale wooden table, a fabric bookmark sticking out of the notebook, a cup of tea and a green plant, soft light from a window

Until 19 May, the assistant remembered everything except the conversation in progress. A screen going dark, a network hiccup, a detour through another app, and the last few minutes were gone: "yes" no longer meant anything, and "what were we talking about last time?" got "I can't find a recent conversation". The memories were intact. That day repaired the short-term memory: one conversation per person that survives interruptions, past exchanges shown as they happened and dated, and a context that no longer empties when one of its sources coughs.

Two memories, and only one that held

When we talk about memory in this app, we mean the neural memory: the cards, the links between them, what is kept for months. That is the long-term memory, and on 19 May it worked well. A week earlier, search had even learned to follow the links between memories instead of relying on word similarity alone.

But there is a second memory, which nobody mentions because between people it goes without saying. It is the memory of the last ten minutes. When you say "yes" to someone, they know to which question. When you say "him too", they know who you mean. That memory is not filed in a card: it lives in the thread of the conversation, on the server side, as the last exchanges the model rereads on every turn.

And that short-term memory was being lost. Not after an hour: after a few seconds, as soon as the link between the phone and the server broke, for whatever reason. The result was strange to live with. The assistant remembered the dentist's first name and the renewal date of a passport, but not the sentence it had just spoken. It gave the impression of someone with an encyclopaedic memory and a failing attention span, and that impression was worse than if the long-term memory had been empty, because it contradicted what you had just heard.

Early afternoon: one conductor per connection

The phone and the server talk over a permanent link, opened when the app starts. On the server side, a conductor receives what the user says, runs the model, executes its tools and sends back the reply. It is the conductor that holds the conversation history.

The flaw fit in one line: that conductor was built for each link. One link, one conductor, one history of its own. As long as the link lives, all is well. But a link dies far more often than you would imagine. The screen goes dark in your pocket: the system cuts the link to save battery. You leave the house: the wifi drops, mobile data takes over, and the link is remade. You answer a message in another app and come back: the link is remade. Each time, the app reconnects on its own, silently, showing nothing. And each time, the server built a new conductor, with an empty history, as if a stranger had just walked in.

The model then received the long-term memory, and nothing else. A "yes" said after the screen went dark became "yes to what?". A request made in two parts, the first half before the cut and the second after, no longer had a first half. And that same morning, the assistant had just learned that you could tell it who is speaking when the phone is lent to someone else, without the owner changing; that declaration lived in the same history, and it evaporated with it, at the risk of filing what the visitor had just said under the wrong name.

The fix took the form of a move. There is now a single conductor for the whole server, and it keeps every conversation in progress, one per person. Everything that depended on the link, which screen to send a card to for display, how to schedule a reminder for this particular phone, is handed to it at each turn instead of being sealed into its construction. So when a link is remade, it finds the conversation it had left: same history, same declared speaker, same thread. The rule is easy to state: a reconnection within half an hour of the last exchange resumes the same conversation; beyond that, a new one is opened.

That move forced a second one. Until then, the closing of the link served as the end signal: that was the moment the conversation was summarised and archived into the long-term memory. If the conversation has to survive the closing, that signal is worthless. So every five minutes the server reviews the conversations whose owner has been silent for more than half an hour, archives them and drops them from its working memory. Nothing piles up, and a conversation abandoned midway still ends up in the database instead of being lost at the next restart.

Late afternoon: "I can't find a recent conversation"

The thread no longer broke. One question remained, asked aloud that very day, which got a wrong answer: "what were we talking about last time?".

The material existed, though. When a conversation is archived, a summary of it is written into the long-term memory, as one memory among others. The problem was in that "among others". Before each turn, the server assembles for the model an overview of what the memory knows: the working memories, what has been mentioned in recent days, a sample of the rest. The summaries of past conversations slipped into the list of facts, with no label. The model saw "weekend in Sicily, Claire, dates to confirm" between the gate code and Paul's birthday, and had no way of knowing that this line described the conversation from twelve minutes ago rather than a plan noted one day. Asked "what were we talking about", it looked for a conversation, recognised none, and replied that it could not find a recent one. The answer was right in front of it, disguised as a fact.

The first fix gave those summaries their own section, at the top of the overview, with what sets them apart from a fact: a relative date, "12 min ago", and the length of the exchange, "4 turns". And an instruction, in the same section: when the user asks what we were talking about, whether it remembers, or says they have forgotten what we were saying, lean on those summaries first, before any search through the cards. The same summaries were removed from the other lists, so as not to appear twice under two labels.

Three minutes later: reading the conversation itself

The section lasted three minutes before being redone, because it rested on a compromise that had no reason to exist.

The summary written at archiving time was designed for search by similarity of meaning: short, dense, computed to be found later from a clue. It is an index, not a record. Yet the conversations themselves are kept, every turn of them, in a table of the database. To answer "what were we talking about", the index is a detour: the material is right there, whole.

So the overview now reads that table directly. It lists the latest conversations, newest first, each with its summary, its age and its number of turns. And for the most recent one, it unpacks the last exchanges as they happened, "You: can you make me a list for the weekend", "Me: there, I've noted all of that", with long excerpts shortened. The model no longer has to guess what the previous session was about: it has it in front of it, word for word, and can answer with its content rather than a paraphrase.

There is a lesson in method in those three minutes. When the data exists in its raw form, it is better to show it than to show what was derived from it. The summary keeps its role, that of being found by similarity weeks from now; for today's question, the transcript is the right answer.

Early evening: one source failing no longer empties everything

The last flaw of the day only showed once in a while, and that is what made it hard to catch.

The memory overview handed to the model is assembled from several sources: recent conversations, working memories, what was mentioned in recent days, the sample of the rest, and the personal rules. They are queried in parallel, so their waiting times do not add up. But they were queried under an all-or-nothing rule: if a single one of the requests failed, a delay on the database side, a passing refusal, the whole lot was dropped and the model received an empty overview. It then replied, in perfect good faith, that it did not remember. It literally had nothing.

The rule became "whatever answers is kept". Each source is awaited separately; the one that fails is noted in the logs and replaced by an empty list, the others go through. A context missing one source is better than no context at all, by far: a model that has the recent conversations but not the sample of the rest answers almost as usual; one that has nothing answers like a stranger.

Two measures came with this change. The first concerns the model itself: it happened that the remote service returned an empty reply on the first call of a turn, an overload dressed up as success. The user then heard the fallback sentence, the one announcing a technical hiccup, put in place a week earlier for genuine failures. That first call is now retried once, after a short pause, before giving up. Once only, and only the first: in the middle of a chain of tools, replaying a call would mean doing twice what has already been done, creating two cards, scheduling two reminders.

The second measure is a trace. On every turn, the server writes into its logs what it actually handed to the model: how many recent conversations, how many memories from each layer, how many rules, and the size of the whole. Before, when someone reported "it forgot", there was no way to tell whether the model had misread a full memory or correctly read an empty one. Those are two unrelated flaws that produce the same symptom, and you cannot fix what you cannot tell apart.

What the day taught

Three flaws with nothing in common produced, for weeks, one and the same complaint: "it doesn't remember what we just said". A history tied to a fragile link. Conversation records disguised as facts. A memory that emptied entirely over one late source. None of these flaws touched the memories themselves; all of them touched the way they were handed to the model at the right moment.

That is what makes short-term memory so particular. A gap in the long-term memory often goes unnoticed: you do not notice what you do not ask for. A gap in the short-term memory shows within a second, because it contradicts what you have just lived. Someone who forgets an appointment from three months ago is absent-minded; someone who forgets the previous sentence was not listening. The assistant gave the second impression when it had the first flaw, and barely even that.

Since 19 May, a conversation picked up after a dark screen, a journey or a detour through another app is the same conversation. "What were we talking about last time?" gets the answer, in the words of last time. And when something is missing, it is possible to know why. The long-term memory means you can come back in months; the short-term memory means you can come back in a minute. It took both for talking to the app to feel like talking to someone.

Read next
XNeuronal is available on AndroidA memory that works things out is almost here