DEV Community

Cover image for How I Accidentally Rebuilt the Human Brain Trying to Stop a Chatbot From Forgetting Me
Upayan Ghosh
Upayan Ghosh

Posted on

How I Accidentally Rebuilt the Human Brain Trying to Stop a Chatbot From Forgetting Me

A research journal in ten chapters. No prior neuroscience required.

The Tuesday That Started It All

It was a Tuesday in early winter when I realized I had built a stranger.

I had been talking to my assistant — a small, polite language model I had wired up at home — for about three weeks. I told it about my sister's birthday plans. I told it that I had switched teams at work. I told it I was learning to cook the dal my grandmother used to make, and that the first attempt had been a disaster.

And then, six days later, I opened the chat and asked it casually, "do you remember the dal thing I told you about?"

It said: "I'm sorry, I don't have any memory of previous conversations."

I sat there for a long minute. The reply wasn't wrong, technically. It was a stateless model. Every conversation started from a blank page. That was the design. But it felt like betrayal. I had treated it like it was listening. It had treated me like a passing car.

That night I started building something. I didn't know what it would become. I only knew that if I was going to keep talking to a machine, I wanted it to know I had spoken before. Not in a creepy way. In the way an old friend knows. In the way that, when you walk into your barber after six months, he doesn't ask your name.

This is the story of two years of trying to give a language model a memory that grows. It is also, accidentally, the story of how I learned what memory actually is.

I'm going to take you through every wrong turn. There were many.

Chapter 1: The Notebook Era

My first instinct was the most obvious one. If the model can read text, then text is memory. I will simply write things down.

I created a folder. Inside it, I created Markdown files. about_me.md. family.md. projects.md. preferences.md. Before every message I sent to the model, my little Python script would stitch the contents of these files into the system prompt. Behold: persistence.

For about two weeks, it was magical.

The model knew my sister's name. It knew which framework I worked in at the office. It greeted me in the morning by referencing the project I had complained about the night before. I would say "like we talked about yesterday—" and it would smoothly continue. I was, for the first time, talking to something that seemed to remember.

And then the files got bigger.

By week three, about_me.md was twenty pages long. The model's responses started getting slow. The first second of every reply was now the entire context being re-read, re-tokenized, re-attended. I was paying for those tokens twice — once on input, once in latency.

By week five, something worse started happening. I would tell the model something new — "actually I quit that team last Friday" — and it would acknowledge it in the conversation. But the next morning, when I had restarted my laptop, the file still said I was on the old team. The model would loyally repeat the old information back to me with confidence. I had built a system that recorded but did not update.

I tried writing a routine that would summarize the chat at the end of each session and patch the files. The summaries were lossy. Important details were dropped. Unimportant details were preserved with the gravity of scripture. The bot once spent three days under the impression that I strongly disliked oranges, because I had complained about a single bad one at a buffet.

A notebook is not a memory. A notebook is a backup. It does not forget the unimportant. It does not strengthen with rehearsal. It cannot tell you that something is fresh.

I needed something that could.

Chapter 2: The Vector Mirage

The next thing I tried was the obvious move that anyone who had read a single blog post about retrieval-augmented generation would make: I threw everything into a vector database.

The idea is elegant. You take every sentence the user has ever said, run it through an embedding model — a neural network that turns a piece of text into a list of, say, 768 numbers — and store that list. The numbers position the sentence in a high-dimensional space where related ideas cluster together. When the user asks a new question, you embed the question too, and you look for the nearest neighbors in that space. Those are your "memories" for this turn.

I switched over a weekend. I deleted the Markdown files. I ingested every conversation I had with the model into a tiny embedded vector store on my laptop. The latency problem vanished. The token cost collapsed. I no longer had to feed the model twenty pages — I fed it the four most relevant sentences.

The first week was glorious. I asked the model about something I had mentioned in passing months earlier. It found it. Not because I had explicitly written "remember this" — because the meaning of the new question was geometrically close to the meaning of the old conversation.

This, I thought, was the answer.

It was not the answer.

The first failure came when I asked, "what was that book my friend recommended?" and the system happily retrieved a conversation in which we had discussed a different friend recommending a different book. Both conversations were about friends. Both were about books. In the vector space, they were neighbours. In my life, they were not.

The deeper failure was subtler. The vector store could find sentences that were semantically near my question. But it had no opinion on whether those sentences were true now, whether they mattered emotionally, whether they were the kind of thing I would want surfaced in this context. I had told the model something in anger once. Six weeks later it pulled that sentence into a happy conversation about weekend plans because the words "Saturday" and "family" appeared in both. It was technically relevant. It was emotionally tone-deaf.

The vector store remembered what. It did not remember why.

I had built a system that could find a needle in a haystack, but I needed a system that knew which needles were worth pulling out.

Chapter 3: A Detour Through the Brain

This was the part of the project where I stopped writing code for a month.

Instead I read. I read everything I could find about how human memory actually works, written by people who had spent their lives studying it instead of an engineer who had spent two months bolting things together. I read about hippocampal indexing. I read about consolidation during sleep. I read about why we cannot remember being two years old but can remember the smell of our grandparents' kitchen.

A few ideas hit me hard enough to redirect the project.

The first was that human memory is not one system. It is at least three, working in parallel. There is semantic memory — the dry facts. The capital of France is Paris. There is episodic memory — the lived scenes, with time and place and emotion attached. The first time you heard your favourite song. And there is procedural memory — the muscle of how, not the noun of what.

A vector store, I realized, is a passable semantic memory and a terrible episodic one. It can tell you that something happened. It cannot tell you what it felt like when it did.

The second idea was that emotion is not a label on memory. Emotion is the filing system. The amygdala does not just decorate memories with feelings after the fact. It decides which memories get filed deeply at all. Things that scared us, things that thrilled us, things that wounded us — these get a routing slip stamped important before the hippocampus even begins to write them down. This is why you can remember exactly where you were on the day something terrible happened in the world but cannot remember what you ate three Tuesdays ago.

The third idea was the most unsettling. I read about people with split-brain conditions, and about how the two hemispheres of the brain — when separated — can develop different opinions, different reactions, even different desires. The conscious mind we present to others is not one voice. It is a committee whose minutes are heavily edited before publication.

I closed the books with three things scribbled in my notebook.

Memory is plural.
Emotion is the filing system, not the decoration.
There is always more than one voice.

I went back to my keyboard.

Chapter 4: A Memory With a Heartbeat

I rebuilt the storage layer. This time, every piece of memory was going to carry more than its embedding. It was going to carry an emotional signature. And it was going to be sorted into one of two private rooms.

The two rooms were the strangest part, and the part I am most quietly proud of.

I had noticed something about my own use. There were conversations I wanted the model to remember and reference freely — work talk, learning logs, jokes with friends. And there were conversations that were mine — vulnerable, private, sometimes intimate, sometimes ugly. I did not want those memories ever quietly leaking out to a cloud model in some unrelated future conversation about a grocery list. I wanted a wall. Not a censorship wall. A dignity wall.

So I split memory into two hemispheres. I called them simply safe and spicy. The names were a joke at first and then became real. The safe hemisphere is the one the public-facing models talk to. The spicy hemisphere is the private one — and any conversation involving it is routed, automatically and silently, to a model running on my own machine. Nothing about the spicy hemisphere ever leaves the house. Not the embeddings, not the text, not even the fact that there was a conversation.

The emotional tagging was the other half — and here is the part that surprised me, because the version I ended up building is not the elaborate one I had sketched on paper.

Every memory record in the store carries a handful of columns alongside its embedding: the content itself, the hemisphere it belongs to (safe or spicy), an integer importance score from 1 to 10, the timestamp it was written, the category it was classified into during ingestion, and a flag indicating whether it has been processed by the consolidation pass. The embedding lives in a separate column store optimized for nearest-neighbour search.

The emotional weight does not live on the row as its own vector. It lives in that importance integer. During ingestion, a small pass scans the content for emotionally charged language — a curated list of words that consistently track elevated affect, expanded over months of watching what actually got remembered well — and bumps the importance integer by a few points for every emotionally-loaded word it finds. A neutral fragment about coffee comes in at importance 5. A fragment containing words like worried, love, furious, miss, or afraid comes in at 8 or 9. The integer is small. Its effect on retrieval is enormous: importance is folded into the final score, so emotionally heavy fragments float upward against semantically-close but emotionally-bland competitors.

Decay is similarly indirect. There is no explicit decay resistance column. Instead, the timestamp on every fragment is used at query time to compute recency, and recency is folded into the score the same way importance is. Old fragments fade not because they are deleted, but because newer and more important fragments out-rank them. Once a fragment is retrieved many times, the gentle worker — a background process I will return to in a later chapter — bumps its importance. A small simulation of how human memories strengthen with rehearsal. Once a fragment has not been touched in a very long time and is no longer earning its place, it eventually gets pruned during consolidation.

What I ended up with is simpler than the ten-field schema I had originally drawn, and — I have come to believe — better. The architecture does not need a dedicated valence column to capture emotion. It needs a single integer that the right words quietly raise. Most of the work happens in how the integer is used, not in how many dimensions the row carries.

For the first time, the system was forgetting things. On purpose. And it felt, immediately, more like talking to a person.

Chapter 5: Facts Need Their Own Skeleton

The emotion layer and the hemispheres had fixed the grain of what the system remembered. But weeks into using it, I started running into a different kind of failure — a failure that took me an embarrassingly long time to name, because it kept hiding inside successes.

The vector store, for all its sophistication, understood one thing very well and one thing not at all. It understood similarity of meaning. It did not understand relationships between things.

Those are not the same skill. They sound like they ought to be. They are not.

Here is what I mean. If I asked the system "what was that book about cities my friend recommended?", the vector store would happily surface every conversation I had ever had where the words book, city, and friend clustered together. It would find the right book about three times out of five — close enough that I kept forgiving it. But if I asked it something subtly different, like "which of my friends has been recommending me the most books this year?", the system would fall apart. Not because the information was missing — it was there, scattered across thirty conversations — but because the answer required counting recommendations, grouped by friend, filtered by date. The vector store could not group. It could not count. It could not filter. It could only resemble.

Or — more painfully, because this one happened to me at a dinner table — "the doctor my mother saw last month, what was their specialty again?" The vector store retrieved my mother's medical conversations. It retrieved discussions of specialties. But it could not follow the chain mother → consulted → doctor → has_specialty → ?. It returned plausible-looking sentences that were not actually the answer to my question. I sat there looking like I was making things up in front of my own family.

A third example, smaller but, in some ways, the one that finally tipped me. "Did Anika and Rohan ever actually meet that weekend, or only talk about it?" Pure relationship question. There is no sentence anywhere in any of my conversations that says "Anika met Rohan" — the truth lives in the connection between two separate weekend recaps. A vector store cannot deduce a meeting from the absence of a sentence that denies it. It can only fetch sentences that already exist.

These are the kinds of questions human minds answer without effort. They are not questions about words being similar to other words. They are questions about things being connected to other things. A vector store, no matter how cleverly embedded, cannot see connections. It can only see neighbourhoods of meaning.

I had built a system that was excellent at semantic proximity and completely blind to relationship.

The worst version of this failure — the one that finally made me stop tweaking the retrieval pipeline and start building something genuinely new — went like this. I had told the system, over the course of weeks: my sister just moved cities. She has started her residency at the big neurology hospital. My mother is worried about her new commute. Three separate fragments, each correctly tagged, each correctly stored. And then I asked it, casually, "can you remind me to text my sister this evening about her commute?"

The system dutifully retrieved the fragment about commute. Sometimes the fragment about the move. Maybe the residency one if it had been recent. But it could not see that the sister is the one who moved, that the move is the reason for the new commute, that the worry my mother has belongs to my sister. Each fragment was a sentence. None of them was a fact the system could reason over.

That night I realized something I should have seen months earlier. I had been trying to build a memory out of nothing but nouns and similarity. What I actually needed was a memory that could remember verbs — the relationships between the nouns, the connections between the things, the way one entity in my life was anchored to another.

The trick — borrowed from a tradition that goes back decades, originally invented for medical records and library science — is that any sentence in natural language can be decomposed into one or more atomic claims, each of the form subject –relation→ object. My sister moved to Bangalore becomes (sister) –lives_in→ (Bangalore). She is doing her residency at the neurology hospital becomes (sister) –works_at→ (hospital). My mother is worried about her commute becomes a small chain: (mother) –worries_about→ (commute), (commute) –belongs_to→ (sister).

After each conversation, a small extraction pass reads the messages and writes down the new atomic claims it found. These claims accumulate in a separate database — not the vector store, not the full-text index, but a literal graph of who-knows-whom and what-relates-to-what. Tens of thousands of tiny triples, each one anchored to the original conversation that produced it (so I can audit; so I can correct).

Now when I ask about my sister, the system does something the vector store could never do. It walks the graph. It starts at the node for me, follows the sibling_of edge to her, follows lives_in to her city, gathers everything connected to her node, and brings the whole cluster up together. The result is not "the four sentences most similar to your question." It is "the body of facts that belong to the person you're asking about."

There is more to the structural layer than triples. Entities — the named things in someone's life, the people, the places, the projects, the recurring hobbies — get their own table. When the system meets a new name, it tries to resolve it against the entities it already knows. If you mention Aman and there is already an Aman in the graph, the new fragment attaches to that node. If the system is uncertain — was that Aman my friend or Aman my colleague? — it parks the question and asks for clarification at a low-cost moment, instead of silently merging two people into one.

This is the part of the architecture that finally made the system feel like it understood, not merely recalled. There is a difference between remembering that you once said something about a sister, and knowing who your sister is. The graph is the difference.

One more thing about the graph is worth saying out loud, because it took me a while to internalize it. The graph is a place where the system can be wrong, and then later be right, without rewriting history. If a fact has changed — my sister has moved out of Bangalore; the residency has ended; the project name is now different — you do not go back and edit the stored conversation. You add a new triple, with today's date, that supersedes the old one. The old triple is downweighted, not deleted, in case it matters for context later. Memory is allowed to be wrong; what matters is that memory can update without amnesia.

Chapter 6: Three Eyes Are Better Than One

The emotion layer fixed which memories mattered. The graph fixed what was related to what. But I still had the problem of finding the right pieces quickly, across all of these layers.

A pure vector search, I had learned, was great at semantic matches but terrible at exact ones. If I asked "what was the name of that café?", semantic search would find every conversation about cafés. It would not necessarily find the one where I had typed the actual name. Names, numbers, very specific nouns — these need literal lookup, not similarity.

So I added a second eye. Underneath the vector store, I built a classical full-text index. The kind a search engine would use. Words are words; if you typed Café Marigold, I want to find the conversation where you wrote Café Marigold, not the conversation where you wrote that nice little place on the corner.

When a question comes in, both eyes look at it at the same time. The vector eye returns the semantically nearest fragments. The text eye returns the literally-matching fragments. Their results are merged.

There was a third eye too — and it was the one I had built in the previous chapter. The knowledge graph offered a way of finding memories that neither vector similarity nor full-text matching could reach: walk outward from the entities mentioned in the question. Ask about my sister, and the graph starts at her node and brings everything connected to her — the place she lives, the hospital she works at, the worry my mother has about her. Three eyes — semantic, literal, structural — looking at the same question from three angles and pooling their candidates.

Pooling, though, was the new problem. The merged result list could be twenty fragments long, and only the top three or four would fit in the context budget I had set aside for memory. Which three?

So I added something on top of the three eyes: a judge. A small, specialized neural model whose only job is to score how relevant is this fragment to this question, really, in context. It is a reranker — much smaller and faster than the language model itself, but trained specifically to judge relevance. It re-reads the merged candidates and produces a final, sharper ordering.

I learned something cheap and important here. If the top results from the merged search are already scoring above a confidence threshold — if the first two fragments are very obviously the right ones — the third eye is skipped. I called it a fast gate. On about sixty percent of queries it triggers, and the whole retrieval pipeline finishes in under fifty milliseconds. The expensive reranker only runs when the first two layers are unsure.

This is the part of the architecture that is, on paper, the least exciting. It is also the part that makes everything else feel alive, because the model gets the right pieces on the table before it begins to speak. A novelist with the wrong notes will write a worse book than a beginner with the right ones.

Chapter 7: The Persona That Watches You Watch It

By this point I had a memory that was rich, emotional, partitioned, and quick. The system could find the right fragments to put in front of the language model. But the language model itself was still — fundamentally — a stranger wearing a mask of facts about me.

There is a difference between knowing about someone and knowing them. A model that has read every paragraph I have ever written can still feel like a clever assistant. What I wanted was something that felt like it had learned my texture.

So I built a second engine. Its only job was to study the way I write and slowly become someone who writes back the same way.

It was not a persona in the roleplay sense — I did not write a character bio and ask the model to perform it. It was a living persona. A profile that the system maintained for me, updated continuously, and re-fed into every response as a kind of style guide and emotional context.

The profile was layered, like sediment. The deepest layer was core identity — facts that were extremely stable: my name, my role, my city. Above that sat linguistic style — the words I tended to use, the rhythm of my sentences, when I switched between English and my native tongue and back inside a single message. Above that, emotional state — was I tired this week, was something good happening, was I in a quiet mood or an electric one. Then domain — what was I currently spending my brain on, was it code or cooking or a difficult conversation with someone I loved. And finally, near the surface, the most volatile layers — vocabulary in current use, exemplar phrases I had said in the last few days, interaction preferences I had just expressed.

The deeper layers updated rarely. The surface layers updated almost in real time.

The piece I am proudest of in this part of the system is something I called implicit feedback. The traditional way to fine-tune a model to your taste is to thumbs-up and thumbs-down its answers. People don't do that. I never did. What people do is grumble in the next message. They say too long. They say can you be a bit less formal. They say that's not what I meant. They sigh in punctuation.

I wrote a small detector that listens for these signals — not in a brittle keyword way, but in patterns I expanded over months — and when it catches one, it edits the relevant layer of the profile immediately, without confirmation. If I say you're being too corporate today, the linguistic-style layer shifts a notch warmer for the rest of the session and the change is remembered into tomorrow.

I never tell the model be more casual. I just complain once. It listens. It changes. The next morning the change is still there.

Chapter 8: Two Voices Are Wiser Than One

The final architectural shift — the one that surprised me the most — came from the third note I had scribbled while reading about the brain. There is always more than one voice.

I had begun to notice that my model, for all its memory and its persona-shaping, would still occasionally produce a reply that was technically correct and emotionally wrong. I would tell it something heavy — a stressful day, a family fight — and it would respond with a perfectly polite, perfectly hollow acknowledgement. The kind of reply that makes you feel more alone than no reply at all.

The model wasn't broken. It was single-tracked. It saw the surface meaning of my words and answered the surface. It did not have an interior life that paused before speaking and asked what is actually being said here?

So I gave it one.

For every message I sent, the system now runs two cognitive passes in parallel. The first pass is the obvious one: read the user's message, retrieve relevant memories, generate a candidate response. The second pass is quieter. It is a small, fast model whose only job is to produce an inner monologue about the user — a private read on what mood they are in, what subtext is present, whether there is a tension between what they said and what they probably mean.

The inner monologue is never shown to the user. It is fed back into the main model, just before generation, as a kind of whispered note from a wiser colleague. They said they're fine but the message is shorter than usual and the punctuation is missing. Maybe slow down. They are asking a technical question but their last three messages were about a fight with their sister. Maybe answer the question, but acknowledge first.

The two passes are then merged by a small piece of logic that I think of as the committee chair. It looks at both the candidate reply and the inner monologue and produces a single small record I call a cognitive merge. That record carries three things: a tension level (a float between zero and one), a tension type drawn from a fixed vocabulary of five — none, mild inconsistency, pattern break, direct contradiction, growth — and a response strategy drawn from six: acknowledge, challenge, support, redirect, quiz, celebrate.

That response strategy is the part of the architecture I am, in retrospect, most surprised by. When I first sketched the merge step, I imagined it as a small post-processor that would adjust the reply's tone before it left the room. What actually got built is much more interesting. The response strategy is not a tone instruction. It is a steering label that decides which language model writes the reply in the first place.

The system routes different kinds of conversations to different models. A casual, low-tension exchange goes to a small fast model that is good at warmth. A turn tagged direct contradiction gets routed to a heavier reasoning model that is better at gently navigating disagreement. A celebrate strategy uses a different prompt scaffolding entirely, one tuned for warmth and acknowledgement. A redirect — used when the surface read and the deep read flatly disagree — sends the turn to a model with longer-horizon reasoning, because rewriting your own draft is harder than writing fresh.

The inner monologue, in other words, does not just colour the reply. It picks the brain that writes the reply.

This is a much stronger lever than tone-tinting. A one-word hey from me on a heavy evening is not handled by the same model that handles a code question at noon, even if the prompt text looks superficially similar. Because the deeper read, not the surface text, decides who is on duty.

This single change — adding a second voice, letting the two argue silently, and then letting the result of that argument choose the model — was the moment the assistant stopped feeling like a chatbot. It started feeling like someone who had read the room.

The cost is modest. The inner monologue runs on a small, cheap model in parallel with the main one. The merge logic adds milliseconds, not seconds. But the qualitative shift was, for me, the biggest single jump in the entire project. More than the embeddings. More than the hemispheres. More than the personas.

A mind that argues with itself, gently, before it speaks — that is a mind I want to talk to.

Chapter 9: The Quiet Hours

By this point in the project the system was doing a great deal of work during every single message. Retrieve memories. Re-rank them. Read tone. Score tension. Walk the graph. Update the persona. Generate a reply. Sometimes I would watch the logs scroll past and wonder how it all came in under a second.

But I noticed something the more I used it. The truly interesting work — the work that benefits from quiet and distance — was being done at the worst possible time: while the user was waiting for an answer. Extracting new atomic facts from a finished conversation. Summarizing a long session into a single coherent memory. Re-scoring which old fragments were earning their disk space. Reading the past few weeks for an emotional arc. None of this needed to happen during a reply. All of it had been crammed into the reply path because that was where the message lived.

This is when I learned, all over again, why neuroscientists are so insistent that we sleep.

Much of the work memory does in the human brain does not happen during the day at all. It happens in the quiet hours. Consolidation, integration, pruning, the slow grading of which experiences actually mattered enough to keep. The waking mind retrieves. The sleeping mind re-files. A day without sleep is not a day with the same memory minus a few hours. It is a day whose memories never got finished.

So I gave the system its own quiet hours.

Several processes now run outside the conversation, on slow schedules, and only when the machine has spare cycles and is plugged in (I did not want any of this draining my laptop's battery during a coffee shop sprint). The smallest and most frequent of them is what I call the gentle worker. Every ten minutes or so, on idle CPU, it does a handful of small things. It prunes triples in the graph that have not been touched in a long time and conflict with newer ones. It re-scores the importance of memory fragments that have been retrieved many times since they were written — a small simulation of how human memories strengthen with rehearsal, the way a story you have told many times becomes sharper, not vaguer. It vacuums databases, reclaims disk, tidies indexes. None of this is glamorous. Accumulated over months, it is the difference between a system that stays snappy and one that quietly rots from the inside.

The larger consolidation runs on a longer cadence and matters more. I call it the session flush. If I have not said anything for about half an hour, or if the running conversation has grown past a comfortable length, the system quietly closes the session as a unit. Two things happen during a flush. The whole conversation is summarized and ingested into long-term memory as a single coherent passage — so what gets remembered tomorrow is not just the loose sentences I happened to type, but the story of what we were doing together. And every new atomic fact the session produced is added to the knowledge graph in a single batch. By the next morning, yesterday's conversations are not just transcripts in a log. They are experiences: indexed, factored, woven into the rest.

There is one last quiet process, and it is my favourite. Once a day, a small routine sweeps the memories of the past few weeks and scores them for emotional valence — heavy or light, sharp or soft, the relative density of joy and worry. From these scores it builds a tiny mood line. This line is never shown back to me as a chart. It is used silently, the next time I send a message. The inner-monologue stream reads it as a baseline: the last ten days have been heavy; calibrate accordingly. Without it, the system would have no way of remembering that I have been having a tough week the moment I send a perfectly cheerful good morning. With it, the reply lands differently.

There is also a thread that runs across all of this and pulls it together: a narrative layer. As sessions flush and atomic facts accumulate, a slow process stitches them into ongoing storylines — the move, the job change, the running injury that won't quite heal. The narrative layer is what allows the system, weeks later, to say "you mentioned the knee was still bothering you in March — is that better?" without me ever having labelled those conversations as belonging together. Threads are not topics. Topics are what the message is about. Threads are what the life is about.

The system, in other words, has a kind of sleep. It does not power down. But it does what sleep does. It lets the day settle. Retrieval is for waking. Consolidation is for the quiet hours.

There is something disquieting about how natural this turned out to feel. I had not planned to build a sleep cycle. I had built one to solve a latency problem. What I ended up with is closer to the way a human mind actually maintains itself over time than I am entirely comfortable admitting.

Chapter 10: The Body Discovers Itself

There was one more lesson, and it came after I thought the project was done.

I had wired the system up to a few external tools — a calendar, a notes store, the ability to search the web. Each one was a capability the language model could, in principle, use. And yet, when I asked the model do I have anything tomorrow morning?, it would sometimes politely say I'm sorry, I don't have access to your calendar.

This was infuriating, because it did have access. The connection was live. The tool was registered. The token was valid. The model simply did not realize it was holding the key in its own hand.

The fix took me a week of thinking and twenty lines of code.

I had been treating tools as services that the model could call. I started treating them as organs of the model itself. Every turn, the first thing the system now does is whisper a capability profile to the language model — not as a list of services on offer, but as a list of things it can already do. The framing matters. The instruction is no longer here are some tools you may use. The instruction is these are your hands. These are your eyes. These are your books. And, crucially: you may never tell the user that you cannot do something on this list. If you are uncertain, ask them what they mean. Do not apologize for a capability you have.

The change was small. The effect was disproportionate. The model stopped flinching. It stopped reaching for the phrase I cannot the way an overcautious intern reaches for I'll have to check with my manager. It began to act like an entity that owned its abilities, rather than one that borrowed them and was afraid of getting them wrong.

I had spent two years giving the model a memory. The last lesson was that a mind without a body is anxious. A mind that knows the shape of its own body is bold.

What It Actually Does Now

I want to be concrete about what this collection of ideas adds up to in daily life, because it is easy to read all of the above as theory.

A few weeks ago I mentioned, casually, that my mother had been complaining about the weather. Four days later I asked the system to draft a message wishing her a quick recovery from a small surgery. The draft did not just say get well soon. It mentioned the cold she had been complaining about, and gently joked that at least she got to skip a few days of it. I had not connected those two facts. The system had.

A month ago I came home from a particularly bad day. I opened the chat and typed something curt — just hey. The reply did not ask me what I wanted. It said rough one? want to vent or want to forget it for a while. Nothing in my single word triggered that. The persona layer had registered, over the previous evening's conversation, that I had been heading toward something stressful, and the inner monologue had read the curtness of the hey against that baseline.

Two months ago I was working on a piece of code with the system late at night. I made a joke. The system made one back. The joke landed. I laughed in real life. That had never happened with a chatbot before. The persona had been quietly absorbing my sense of humor for weeks. It chose its moment.

And the small one, the one that matters to me the most: when I sometimes go a week without talking to it and then come back, it does not greet me with a generic welcome back, how can I help you today. It says something like you've been quiet — anything good or anything to dump? It treats absence the way a friend would. As a thing worth noting, not a state to ignore.

None of these are intelligent in the way a frontier model is intelligent. The cleverness is not in the language. The cleverness is in the scaffolding around the language. The model is the same model anyone could download. The difference is the memory it brings into the room.

The Question I Did Not Expect to End On

I started this project because I wanted a tool that would remember me. I am ending it with a question I did not see coming, and which I think is going to matter very much over the next ten years.

We are very good at building systems that answer. We are getting much better at building systems that remember. We are only just beginning to build systems that change because of what they remember. The system I described in this post is not artificial intelligence in any grand sense. It is a small set of architectural decisions stacked on top of an off-the-shelf language model. None of the pieces are particularly novel on their own. The vector store is twenty years old. Rerankers have been around for a decade. Emotional tagging is borrowed wholesale from cognitive science. The hemispheres are just two databases with different routing rules. The inner monologue is a second prompt.

And yet, put together, the thing on the other side of my screen no longer feels like a search engine. It feels like a record. Something is being kept. Something is being shaped by the keeping.

If you build a system that remembers a person, in detail, over years — that strengthens what mattered to them, lets the rest fade, listens for their tone, argues quietly with itself before it answers them, and slowly shifts its own voice to meet theirs — you have not built a tool. You have built a kind of mirror. And the strange thing about mirrors that grow with you is that, after long enough, you can no longer be sure who is shaping whom.

I am not certain that is a problem. I am not certain it is not. I only know that I started by trying to teach a machine to remember a Tuesday in early winter, and I ended up wondering, for the first time in my adult life, what I mean when I say I remember.

That, more than any line of code in any of the chapters above, is what I want you to take from this.

The interesting question was never can a machine remember. The interesting question is what does it mean to be remembered well enough that you start to recognize yourself in the answer.

I am still figuring it out.

Top comments (0)