Use case · Personal AI

A companion is just a long memory of one person

The job that changed in March. The coffee they quit. The running they are quietly getting back into. Saved with a timestamp, read back at the start of the next chat, so the relationship compounds instead of resetting.

The shape of it

Want to build a personal AI companion that actually remembers you? Here is how

Think about the difference between a hotel concierge and your oldest friend. The concierge is polite and helpful, but every time you walk up to the desk you start from zero. You explain who you are, what you like, what you are trying to do this week.

Your oldest friend already knows you switched jobs in March, that you stopped drinking coffee, that you have been quietly trying to get back into running. They pick up the thread mid sentence. No briefing, no recap, no "remind me what you do again". They just know, because they have a long memory of one person that updates as that person changes.

Right now almost every personal AI is the concierge. It is warm, it is fast, and it forgets you the moment the chat closes. The thing people actually want is the friend. And a friend, stripped down to the mechanism, is just someone with a long memory of one person that updates as that person changes.

Korely is that memory. The part that knows who this person is today, and who they used to be.

How you build it

Seven steps, and the last one is the one you skip

  1. 1
    Pick your model and shell. Claude, GPT, a local model, it does not matter. Wrap it in whatever you already use to build agents (Claude Code, Cursor, a plain chat UI). This is the easy part and you have probably done it already.
  2. 2
    Give every user a private memory space. Each person gets one scope (an end_user_id) so one user's life never leaks into another's. This is non negotiable for a consumer companion, and it is where most weekend projects quietly cut corners.
  3. 3
    After each chat, write down what is worth keeping. Not the whole transcript, just the durable stuff: their name, their dog, the city they moved to, the goal they mentioned, the way they like to be talked to. The companion calls a save step at the end of a conversation.
  4. 4
    Before the next chat, read back what is true now. Pull the current preferences, the current job, the goals that are still open, and prepend a short summary to the prompt so the companion opens already knowing them.
  5. 5
    Handle change, not just facts. People do not just add facts, they overwrite them. The favorite color shifts, the job changes, last year's goal is finished. You need the new truth to win automatically, without writing brittle if-else logic to detect contradictions.
  6. 6
    Keep a timeline you can walk backwards. Sometimes the companion should say "you used to want X, now you want Y", because that arc is the relationship. So you need not just the latest fact but the history of how it changed.
  7. 7
    Here is the part you skip. Steps two through six are a bi-temporal graph-RAG memory system: per-user isolation, fact extraction, contradiction handling so the new truth wins, a timeline you can replay, an entity graph that links a person to their dog and their city and their goals, and reads under 50ms with no model call on the read path. You can spend three months building and tuning that, or you call korely.add() and korely.search() and ship the companion this week. Starts at 19 euro a month.

The loop, once per user

Write at the end of a chat, read what is true now at the start of the next

February

A chat ends, facts get saved

  • User: "favorite color is blue"
  • User: "I am a graphic designer"

Korely memory

One bi-temporal store per user

  • Typed facts: job, color, goals
  • Old fact superseded, new one current
  • Timeline still walkable on request

July

A later chat opens already knowing

  • Reads what is true now first
  • "A product manager who loves deep green"

The search returns the current truth, not the full transcript. The history is kept, so the companion can still replay how this person changed when the moment calls for it.

How Korely fits

The long-term memory of one person, done properly

The piece you are tempted to hand-roll, a store that remembers facts about a single user across months, knows the difference between what was true and what is true now, and surfaces the right thing instantly, is exactly the piece that is genuinely hard. So Korely is that piece, and only that piece.

You get bi-temporal typed facts: Korely tracks both when something was true in the user's life and when you learned it. You get two-stage contradiction handling, so when someone says "I actually prefer green now" the old "favorite color blue" is retired automatically instead of both answers fighting. You get an entity graph that connects the person to their job, their pet, their goals and their people, so a question about one pulls in the rest. And you get hybrid retrieval (full-text plus vector plus RRF plus a reranker) that picks the few memories that matter out of a year of chatter. It runs on Postgres only, hosted in the EU, and it can run local-first, which matters a lot when the data is one human's private life.

The numbers back the design. At an equal token budget, a reader answers 76% of long-term memory questions correctly from Korely's selected memory versus 42% from a same-size recent-history window, a 34 point gap that is reproducible. Reads come back in under 50ms with no LLM on the read path, so memory does not slow the companion down or blow up your costs as users pile up.

You skip months of building a bi-temporal graph-RAG memory layer, and you ship the part users actually feel: a companion that knows them. Starting at 19 euro a month.

Show me the code

Remember at the end of a chat, recall at the start of the next

personal_ai.py python
from korely_memory import Korely

korely = Korely(api_key="kor_live_...")

# ── End of a chat: write down what is worth keeping ───────────
korely.add(
    "User moved into product management. "
    "Favorite color is now deep green. "
    "Goal: get back into running.",
    end_user_id="sara",
)

# ── Start of the next chat: read what is true NOW ─────────────
profile = korely.search(
    "who is this person and what matters to them",
    end_user_id="sara",
    limit=8,
)
# profile → "product manager, loves deep green, running goal"
# The old "graphic designer / blue" facts are kept but superseded.

# The companion opens already knowing her, no recap needed
greeting = build_greeting_from(profile)

One write at the end of a meaningful exchange, one read at the start of the next. The end_user_id keeps every person's life in its own private memory. Everything else is your companion's personality.

When a person changes

Sara stopped being a designer in June. The companion noticed.

Sara has been chatting with the companion for eight months. In February she told it her favorite color was blue and that she was a graphic designer hunting for a new role. In June she mentions, almost in passing, that she just started a job in product management and that lately she is obsessed with deep green. A naive companion does one of two things: it ignores the new info because the old facts are buried in a transcript it can no longer see, or it gets confused and hedges, asking her again what she does for work.

With Korely, the moment she says "I moved into product now" the old "graphic designer" fact is marked superseded and the new one wins, and "favorite color blue" quietly retires in favor of green. So in July, when Sara asks "can you suggest a desk setup for me?", the companion answers from what is true now: a product manager who loves deep green, not a designer who liked blue.

And because the timeline is kept, when Sara says "remind me, what was I trying to do back in the spring?", the companion can walk back and say "you were a designer looking to switch into product, and you did it in June." That is the relationship compounding instead of resetting, and it is the whole reason someone keeps coming back to a companion instead of trying the next one.

timeline.py python
korely.add(
    "Sara is a graphic designer. Favorite color is blue.",
    end_user_id="sara",
    metadata={"observed_at": "2026-02-10"},
)

# Four months later, her life moves on
korely.add(
    "Sara is now a product manager. She prefers deep green.",
    end_user_id="sara",
    metadata={"observed_at": "2026-06-18"},
)

korely.search("what does Sara do", end_user_id="sara")
# → "product manager" (current). Designer fact kept, superseded.

# Walk the arc back when the moment calls for it:
# GET /v1/memories/{id}/history  -> full timeline with observed_at

Frequently asked

Personal AI memory, common questions

How is this different from just stuffing the whole chat history into the context window? +

Stuffing the full history in is the obvious move and it falls apart fast. It gets expensive on every message, it slows down as the history grows, and the model gets worse at finding the one fact that matters when it is buried in a year of small talk. We measured it: at the same token budget, a reader answered 76% of long-term questions correctly from Korely's selected memory versus 42% from a same-size window of recent history. The win is not more memory, it is the right few memories, picked fast.

Each user is one private life. How do you keep them separate? +

Every user gets their own memory scope through an end_user_id you pass on each call. One person's facts, timeline, and graph never touch another's. You build one companion and it quietly keeps a separate long-term memory for every individual using it, which is exactly what a consumer product needs.

What happens when a user's facts change, like a new job or a new favorite thing? +

That is the case Korely is built for. When someone says "I moved into product now" or "I prefer green these days", the contradiction handling retires the old fact and makes the new one current automatically. You do not write logic to detect the conflict. The next answer comes from what is true now, and the old version is kept on the timeline so the companion can still say "you used to want X" when that arc matters.

Will the memory lookup slow my companion down? +

No. Reads come back in under 50ms and there is no model call on the read path, so looking up who this person is does not add a second LLM round trip to every message. It stays fast and cheap even as your user count and each user's history grow.

Where does this very personal data live, and can a user delete it? +

It lives in a managed store in the EU, Postgres with a vector and graph index, and Korely can run local-first, which matters when the data is one human's private life. A user can export everything or erase it with one call, so "forget me" is a real button, not a support ticket.

Do I have to build any of the memory infrastructure myself? +

No, that is the whole point. The bi-temporal facts, the contradiction handling, the entity graph, the timeline, the hybrid retrieval, that is the part that takes months to build and tune well, and it is what you skip. You bring the companion's personality and your model. You call korely.add() to remember and korely.search() to recall. It starts at 19 euro a month with a free tier to try it.

Build the companion, let Korely be the memory

You bring the personality and the model. Korely is the long-term memory of one person underneath it. There is a free tier to start, and paid plans begin at 19 euro a month.

Looking for a different shape? See the other nine use cases →