Apply to my task
arXiv:2610.21900 ★ 80 Oct 15, 2026

TEM (Temporal State Tracking Memory): agent memory that keeps old versions of facts tagged [historical]

Key result

Finding: keeping old values isn't enough. Give the model every version of a fact in a row and it will take the old address as the current one. The TEM method lets the model answer both “what is it now” and “what was it before” when facts about a client or project change. The old value isn't erased; it gets a [historical] tag, and the latest version stays clean. Versions go in order of appearance, giving you a ready-made timeline slice. Accuracy rises several-fold on every model tested.

01

TL;DR

TEM is a memory scheme for agents. When a fact about the user changes (they moved, switched jobs, changed plans), the old value isn't erased. It's kept alongside the new one, all versions are lined up in the order they appeared, and the outdated ones get a [historical] tag. The latest version stays untagged. The model receives a ready-made “timeline slice” with a hint about what's current and what's already in the past.

The core problem: keeping old values isn't enough. Hand the model every version in a row and it mixes up “now” and “before.” It treats the old address as the current one, answers about the wrong change, or grabs the wrong fact altogether. The authors compared three setups with identical facts and identical order. If you overwrite old with new, the model can barely answer questions about the past. If you keep everything without tags, it does better, but inconsistently. Add nothing but the [historical] tag, and accuracy jumps several-fold on every model. Relying on “the hint is somewhere in the text” doesn't help: you have to walk the model to the answer explicitly.

The method has three parts: store versions, order them by source, and tag the outdated ones. For you, the last part is what matters: an explicit status tag right next to the fact works as a data-presentation rule. You can use it by hand in a chat or in an agent's memory file, no code required.

Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.

02

Method Blueprint

WRITE:    new fact → add as a new version (do NOT erase the old one)
          each record = subject + relation + value + source (session/date)
          versions of one “subject+relation” = one group

STATUS:   in a group, the version with the latest source = current (no tag)
          all others = [historical]

PRESENT:  pick the relevant facts (up to 15)
          → sort by source order (oldest → newest)
          → put [historical] on the outdated ones
          → hand them to the model together with the question

ANSWER:   the model picks the right version from the wording of the question
          (“now” → untagged, “before the move” → the previous one)

In the original this is a software system: code extracts facts and searches over them. But the final “chunk of context” the model sees is just text, and you can assemble it by hand.

03

Example

Task: You keep notes in a ChatGPT project on a client who runs a home-goods store. Over the year they switched marketplaces, ad budgets and contractors. You ask: “Why did they leave Amazon, and what are they doing now?” Without markup, the model scrambles the order or treats the old value as current.

Prompt:

<Memory>
Facts about the client “Cozy Home Co.”, in order of appearance (oldest to newest).
Tag [historical] = value was replaced by a later one.
No tag = current value.

- Main sales channel | Amazon | source: call Feb 12 [historical]
- Main sales channel | Etsy | source: call Jun 20 [historical]
- Main sales channel | Walmart Marketplace + own Shopify store | source: call Oct 3
- Ad budget | $3,000/mo | source: call Feb 12 [historical]
- Ad budget | $8,000/mo | source: call Jun 20 [historical]
- Ad budget | $4,500/mo | source: call Oct 3
- Reason for leaving Amazon | rising fees and inbound-shipment penalties | source: call Jun 20
</Memory>

Answer only from <Memory>. If the question is about “now,” use the untagged values.
If it's about the past, pick the version that was in effect at that moment.
Never present a historical value as the current one.

Question: Where did the client sell before Etsy, why did they leave, and what is their ad budget now?

Result: The model should answer all three parts of the question: the previous channel (Amazon), the reason for leaving (from the untagged record about the reason), and the current budget (the untagged record, $4,500). It should not pass off the historical value ($8,000) as the current one.

04

Why it works

The model's weakness. When the context holds several values of the same fact, they all look “semantically similar” to the question. The model has to decide on its own which one is current and which isn't. Record order doesn't always help: versions can be shuffled, and words like “now” and “before the move” require matching the question against a chain of events. So it slips up, especially smaller models.

The model's strength. Models are good with explicit labels in the text. If [historical] sits next to a fact, the model doesn't have to work out the status. It just reads the tag and matches it to the question. Picking the right version for the question is something it does well on its own.

How the method exploits this. TEM splits two jobs: what to show (relevant facts) and how to present it (in order, with a status tag). Code computes the status with a simple rule: anything that isn't the latest in its group is historical. So even if the fresh version didn't make it into the retrieved set, the old one still carries its tag and doesn't pose as current.

Control knobs: - Tag → swap it for “outdated,” “replaced by X as of date,” or add a date. Same idea: the status is visible at a glance. - Order → oldest to newest, as in the original. You still need the tag: in the experiment the order was identical, and the difference came from the tag alone. - Fact limit → up to 15 in the original. A short slice is cheaper and doesn't overload the model. - Rule in the instructions (“use untagged for ‘now’”) → the original had no such rule; the model chose on its own. This is your add-on, so test it.

05

Prompt template

<Memory>
Facts about {subject}, in order of appearance (oldest to newest).
Tag [historical] = value was replaced by a later one.
No tag = current value.

- {parameter_1} | {value_v1} | source: {date/session_1} [historical]
- {parameter_1} | {value_v2} | source: {date/session_2} [historical]
- {parameter_1} | {value_v3} | source: {date/session_3}
- {parameter_2} | {value} | source: {date/session}
</Memory>

Answer only from <Memory>.
If the question is about “now,” use the untagged values.
If the question is about the past, pick the version that was in effect at that moment.
Never present [historical] as current.

Question: {question}

Fill in: - {subject} — a client, project, employee; - {parameter} — whatever changes (address, plan, tech stack, job title); - versions and dates — from your notes.

Rule: in each group (one subject + one parameter) every version except the latest gets the tag. The latest one stays untagged.

🚀 Quick start — paste into your chat:

Here is a timeline-memory template with [historical] tags. Adapt it to my task: [your task]. 
Ask me questions to fill in the fields.

[paste the template above]

The LLM will ask what changes over time in your case, which versions and dates you have, and what questions you plan to ask. It needs that to build the version groups correctly and place the tags. Then it assembles the <Memory> block from your notes.

06

Limitations

⚠️ Unambiguous updates only: the method assumes the new value replaces the old one (address, job). If preferences hold at the same time (likes coffee and likes tea), the [historical] tag becomes a lie.

⚠️ Order = order of recording, not of events: status depends on when the fact entered memory. If someone mentions a move after talking about a more recent event, the order breaks. The authors acknowledge this.

⚠️ Contradictions within a single record aren't resolved: if one session contains two different values, the method won't sort them out.

⚠️ Tags barely helped on open-ended conversational questions: on a public benchmark with questions about event details and links between facts, results with and without tags were practically the same. The tag helps specifically with “which version of the fact is current.”

⚠️ Weak models and synthetic data: tested on small open models (4–20B parameters) and on generated dialogues. With strong models the gap may be smaller.

⚠️ The full system needs code: automatic fact extraction and search are software. By hand you can only replicate the presentation.

⚠️ Comparison with other memory systems isn't apples to apples: the authors themselves note that the generators and metrics behind the scores differ.

07

How they tested it

The authors generated 60 fictional personas and 600 dialogues in which people changed city, job and favorite drink. Then they wrote 420 questions of three kinds: “where do they live now,” “where did they live before,” and “where did they live before the last move.” They tested four open models and six memory-storage approaches, about 10 thousand answers in total.

The key design is an ablation (researchers remove one detail and see what changes). They took the same facts in the same order and compared two variants: with the [historical] tag and without. That ruled out the effect of retrieval and ordering: only the tag changed. Result: on questions about the past, accuracy rose to 97–100%. Without tags, with the same content, it was 42–82%. Simply overwriting old with new gave 0–8%.

Interestingly, the tags lifted “ordinary” questions too: “where do they live now” also improved. Without labels, models aren't sure even about the current value when old ones sit next to it. Another plus: the presented context averaged 94–118 tokens, roughly half of what RAG uses when it stuffs chunks of the original dialogues into context.

To be fair, the authors also tested the method on the public LoCoMo set (1,540 questions). Hybrid memory beat plain RAG on the same budget, but the tags made almost no difference there. Takeaway: the tag solves version selection, and the rest of the gain there came from how the context was organized.

08

Adaptations and extrapolations

🔧 Technique: add the event date → remove the method's main limitation

This is my adaptation; it's not in the paper. The authors admit that recording order isn't event order. Add two dates in your notes: source: call Oct 3 | effective since: Sep 1. Then delayed reports won't confuse the model. Test it on your own data.

Extrapolation: a rule for an agent's memory file (not from the paper, but it follows from its finding). In CLAUDE.md/AGENTS.md or project memory:

## Project memory rules
- Do NOT delete decisions and parameters that have changed.
- Tag the old record [historical] and add: “replaced by: {what} as of {date}”.
- The current record has no tag and sits at the bottom of its group.
- When answering about “now,” use only untagged records.
- When answering “why did we previously…,” look for [historical] records.

This way the agent keeps the decision history (why you dropped database X) and doesn't mistake a reversed decision for an active one.

09

Resources

  • TEM: Temporal State Tracking Memory for Large Language Model Agents — Pengfeng Song, Yunkai Zhuang, Liye Shi (Zhejiang Wanli University, Ningbo, China).
  • Code: https://github.com/sungkites/TEM
  • Benchmarks used: LoCoMo, LongMemEval, LongBench.
  • Memory systems compared: MemGPT, MemoryBank, A-MEM, Mem0, MemoryOS, Zep.

Research digest

Key result

Finding: keeping old values isn't enough. Give the model every version of a fact in a row and it will take the old address as the current one. The TEM method lets the model answer both “what is it now” and “what was it before” when facts about a client or project change. The old value isn't erased; it gets a [historical] tag, and the latest version stays clean. Versions go in order of appearance, giving you a ready-made timeline slice. Accuracy rises several-fold on every model tested.

Principle

All versions of one fact (say, “client + plan”) are collected into a group. The latest version goes untagged, the rest get [historical]. Then everything is fed to the model oldest to newest. The fact's status sits right next to it, nothing to compute. It's like a receipt with “refunded” stamped on the old lines: the bookkeeper doesn't have to guess which line counts. You can phrase the tag differently too: “outdated” or “replaced by X as of date.” Same idea.

Why it works

When the context holds three of a client's plans, all three look “semantically similar” to the question. The model has to decide on its own which one is current. Record order doesn't always help, especially for small models. The authors compared three setups with identical facts and order. Overwriting old with new: the model can barely answer about the past. All versions without tags: better, but results jump around. With the [historical] tag: accuracy rises several-fold. The order was the same in every setup; the tag alone made the difference. A hint like “the answer is somewhere in the text” didn't help. You have to lead the model to the answer explicitly. Another plus: a simple rule computes the status, not the model. Even if the fresh version didn't make it into the retrieved set, the old one still carries its tag and doesn't pretend to be current.

When to apply

Assistants with memory and notes on clients or projects → questions like “what was it before the move” and “what plan are they on now,” especially when values change many times a year (address, plan, job title, tech stack). Works by hand: assemble the block from your notes and paste it into the chat. NOT a fit when preferences coexist (likes both coffee and tea): the [historical] tag would be a lie. For open-ended questions about event details, tags added almost nothing.

Mini recipe

1. Find what changes: list what gets replaced over time (plan, sales channel, contractor). 2. Don't erase the old: each version is its own line: parameter | value | source (date or call). 3. Build groups: one subject and one parameter = one group of versions. 4. Place the tags: in each group, every version except the latest gets [historical]. 5. Sort: oldest to newest. Use only relevant facts, no more than 15 in the original. 6. Explain the rules to the model: “[historical] = replaced later, no tag = current.” Add: “Never present [historical] as current.” The original had no such line; it's your add-on, so test it on your own data. 7. Ask the question: for “now” the model uses untagged lines; for the past it picks the right version itself. 8. Too lazy to do it by hand: ask the model to build the template: `Here are my client notes. Ask me questions, find the versions of each fact and build a block with [historical] tags`.

Examples

[BAD]: `Here are my client notes: Amazon, then Etsy, then Walmart Marketplace. Budget 3k, 8k, 4.5k. What's the budget now?` [GOOD]: ` Facts in order of appearance, oldest to newest. [historical] = replaced later. No tag = current. - Ad budget | $3,000 | call Feb 12 [historical] - Ad budget | $8,000 | call Jun 20 [historical] - Ad budget | $4,500 | call Oct 3 Answer only from . Never present [historical] as current. Question: what is the ad budget now and what was it over the summer?` The model answers: $4,500 now, $8,000 over the summer. Without tags it would be more likely to name any of the three numbers.

In plain words

Models have zero sense of time — they match by meaning, not by calendar. Feed a model a history where a client first lived in Denver and then moved to Dubai, and both facts look equally relevant to it. The agent starts mixing up past and present and serving up hallucinations out of nowhere.

It's like keeping an address book: you write in your friends' new addresses but never cross out the old ones. Then you ask an intern to ship a package, and they send it to an address from ten years ago just because it was the first one they spotted. A total fail, even though technically you wrote everything down.

The fix is called TEM — tracking state over time. The mechanics are almost embarrassingly simple: old data isn't deleted; it's lined up in a chronological chain and stamped with an explicit [historical] label. The fresh fact stays clean. The model no longer has to guess from circumstantial clues what's true right now — someone literally pointed at the right line.

It was tested on agents, but the principle is universal. It's critical for any AI assistants, project knowledge bases and smart CRMs, where a client switches plans, contractors or marketplaces three times a year. Without this markup even advanced models regularly drop the ball, and small cheap ones turn into useless junk.

The moral is simple: don't count on an LLM to untangle someone else's timeline. Want sane memory from your bot? Force-tag stale data as historical instead of hoping for context magic. Otherwise your agent will keep sending reports about a dead tech stack and trying to fix something the client threw out two years ago.

AI lab assistant

Apply this study to your task

Describe what you're working on. AI takes the method and the measured results from this paper and adapts them to your case, or writes a ready prompt built on them.

Based on TEM (Temporal State Tracking Memory): agent memory that keeps old versions of facts tagged [historical] arXiv:2610.21900

Sign in to apply this study New accounts get 50 free credits.