SELECT 1
Entry 013Fri 2026.10.23
One launch a day. Picked, run, explained.

Fri 2026.10.23

TenseMem: updating an agent’s memory with rules

Today's pick: TenseMem

TenseMem is a product that stores an AI agent’s memory in an SQLite file and keeps a single current value for each item.

It is today’s pick because rules, not the model, decide which value is current.

exit 0Ran itIt works. Even with a real model, the current value and the history were stored separately.
Found on
Show HN
Built with
Python, SQLite, Cursor

The problem

The facts an AI agent remembers about a user change over time. If a user lived in Delhi and then moved to Bangalore, the agent has to use the city where the user lives now. According to Anthropic’s Claude help center, Claude finds related past chats with RAGRetrieval-augmented generation. The system first searches for documents related to a question and passes them to the LLM with the question.. Claude itself saves its memory by topic as the user chats. The maker of TenseMem says in the README that similarity searchA search that turns text into numeric vectors and returns the records closest to the vector of the question. It also returns older records when their meaning is similar. returns both "I live in Delhi" and "I moved to Bangalore". Then the model has to guess which one is right.

How it solves it

Shubham Singh posted TenseMem as a Show HNA post on Hacker News, a developer community, in which someone presents what they made. Its title starts with "Show HN:". on Hacker News on October 22, 2026. TenseMem stores one current value for each item, such as lives_in. The LLMA large language model. It is an AI model trained on large amounts of text to understand and generate text. only finds facts in the user’s words and proposes them as operations in a fixed format: subject, item, value and the source sentence. deterministicAlways giving the same result for the same input. LLM output, in contrast, can differ from run to run. rules decide whether to apply them. When a new city comes in, the old one moves to the history. The agent can use this history to answer "where did I live before?".

Every read returns freshness information as well. If a message has not been processed yet, is_current is False. TenseMem wraps the memory it hands to the agent in a <tensemem-context> tag. If the agent passes a conversation that contains this memory back to add(), TenseMem removes the tagged part before it looks for information. This keeps it from storing its own memory again as new information.

What is different

The first difference is who decides the current value. Claude saves and updates its memory by itself during the chat. In TenseMem the model proposes operations, and rules decide whether to apply them. So the same operations always give the same state. The tradeoff is scope. Only items registered first with register_predicate are stored.

The second difference is how memory is read back. Similarity search also returns older values when they resemble the question. TenseMem’s context() returns only the current value for each item, and older values come from history(). TenseBench is the maker’s own benchmark of 101 conversations. With the rule-based extractor, TenseMem scored 1.000 on current-state accuracy. The two baselines scored 0.368. One joins the full user transcript, and the other picks the turns that share the most words with the question. The tradeoff is tokens. The memory text passed to the model averaged 48.1 tokens with TenseMem and 20.2 and 19.6 tokens with the two baselines.

The third difference is where memory is managed. Claude’s memory is managed inside Anthropic’s service. TenseMem keeps memory in an SQLite file inside the application, with no separate server. The tradeoff is fewer storage options. According to the README, SQLite is the only store for now.

What it makes easier

  • Developers building agents that remember users for a long time. They do not need to write their own rules for facts that change, like a move or a new job. Today I used a real model and added a sentence about a move. The current value changed, and the old one went to the history.
  • Services where users may paste secrets into messages. The maker says in SECURITY.md that add() masks common secret formats before it stores text or sends it to a model. Today I added a fake AWS access key, and it appeared in neither the requests nor the database.

How it was built

  • The 57 commits were written over five days from October 17, 2026, in the author’s time zone. 49 of their messages end with a Co-authored-by line for the Cursor agent.
  • The Python code in src is 12,969 lines. There are four runtime dependencies.
  • According to the README, the default tests run without API keys and never call a hosted model.

Running it

I installed it from PyPI in an isolated environment and tested it in this order.

  1. Install. pip install "tensemem[openai]" finished in 7 seconds.
  2. README example. I ran it with FakeExtractor, which extracts by rules with no model. I added Delhi and then changed it to Bangalore. The history stored Delhi as SUPERSEDED and Bangalore as ACTIVE. When I marked Bangalore as wrong with correct(), the current value went back to the previous value, Delhi.
  3. Rebuild. rebuild() recomputes the state from scratch using the stored message log. Right after I called it, the state was empty. The freshness information showed is_current False and pending 1. rebuild() runs asynchronously by default. After it finished, the state still held the corrected value, Delhi.
  4. TenseBench. tensemem bench scored 101 conversations in 23 seconds. The results matched the table in the README.
  5. Real model. I connected Claude Haiku 5.5 through OpenRouter as the extraction model. From "I live in Delhi and I work at Infosys." it extracted lives_in and works_at. When I added "Last month I moved to Bangalore.", the current value of lives_in changed to Bangalore.
  6. Feedback loop. I took the memory block that context() returned and changed only Bangalore to Chennai. Then I added it back with add(). If the contents of the block were stored, the current value would become Chennai. No model request was made, and the state did not change.
  7. Another person. I added "My friend Ravi lives in Mumbai and works at TCS." TenseMem stored its facts with user.friend as the subject. The user’s current values for lives_in and works_at did not change.
  8. Secrets. I added a sentence with a fake AWS access key. The key was in neither the requests sent to the model nor the database. [REDACTED] appeared in its place.
  9. Cost. Five messages used 4 requests and 12,067 tokens, and cost $0.001815.

The three README claims I checked all held up when I ran it. They were one current value per item, no re-storing of the memory it returns, and corrections that survive rebuild().

1 add: state={'lives_in': 'Delhi', 'works_at': 'Infosys'} fresh=True failed=0
2 move: state={'lives_in': 'Bangalore', 'works_at': 'Infosys'} fresh=True failed=0
history lives_in: [('Delhi', 'SUPERSEDED'), ('Bangalore', 'ACTIVE')]
3 echo: state={'lives_in': 'Bangalore', 'works_at': 'Infosys'} fresh=True failed=0
4 other person: state={'lives_in': 'Bangalore', 'works_at': 'Infosys'} fresh=True failed=0

Not checked

  • TenseBench scored with a real model. Score the TenseBench conversations with a real model and compare with the README table.
  • Studio and the MCPModel Context Protocol: a standard for how AI models connect to outside tools and data. server. Studio is a local web UI that connects to the REST server of tensemem serve. Run both to see the memory in Studio. Then test tensemem mcp.

Verdict

It works. Even with a real model, the current value and the history were stored separately. But the developer has to register the items to remember in advance. It is still a 0.1.0 alpha. It is worth trying if you build an agent whose user facts change often and you need to know their current values for sure. If you want an agent to remember the broad context of a chat without splitting it into items, this product is not the right choice.

What to take away

  • Let rules, not the model, decide which value is current. Today, even with a real model, the rules moved Delhi to the history and made Bangalore the current value.
  • Mark the memory you hand to an agent so it is not stored again. TenseMem wraps the memory block in a tag to stop that feedback loop.

Getting started

  1. pip install "tensemem[openai]"
  2. python -c "from tensemem import FakeExtractor, Memory; m = Memory(llm=FakeExtractor()); m.register_predicate(\"lives_in\"); m.add(\"u1\", \"I live in Delhi\")"
You need
Python 3.11 or newer · For extraction with a real model, one of OpenAI, Anthropic, Gemini, Ollama or LiteLLM. FakeExtractor extracts by rules with no key
Cost
Free under Apache-2.0. Extraction with a hosted model is billed separately by the provider.

Register each item to remember with register_predicate first. Items that are not registered are not stored.

Steps select 1 ran.

Progress

  1. Day 3Some commits
  2. Day 7Upcoming
  3. Day 15Upcoming
  4. Day 30Upcoming
  5. Day 90Upcoming
  6. Day 180Upcoming
  7. Day 365Upcoming

Latest check Day 3, Sun 2026.10.25

Commits since launch
0 → 1
Stars
3 → 5
Last commit
2026.10.23

1 commit, but nothing worth summarizing.

Full history →