How to Design a Persistent Memory and Personalized Agentic AI System with Decay and Self-Evaluation?

How to Design a Persistent Memory and Personalized Agentic AI System with Decay and Self-Evaluation?

In this tutorial, we explore how to build an intelligent agent that remembers, learns, and adapts to us over time. We implement a Persistent Memory & Personalisation system using simple, rule-based logic to simulate how modern Agentic AI frameworks store and recall contextual information. As we progress, we see how the agent’s responses evolve with experience, how memory decay helps prevent overload, and how personalisation improves performance. We aim to understand, step by step, how persistence transforms a static chatbot into a context-aware, evolving digital companion. Check out the FULL CODES here.

import math, time, random
from typing import List


class MemoryItem:
   def __init__(self, kind:str, content:str, score:float=1.0):
       self.kind = kind
       self.content = content
       self.score = score
       self.t = time.time()


class MemoryStore:
   def __init__(self, decay_half_life=1800):
       self.items: List[MemoryItem] = []
       self.decay_half_life = decay_half_life


   def _decay_factor(self, item:MemoryItem):
       dt = time.time() - item.t
       return 0.5 ** (dt / self.decay_half_life)

We established the foundation for our agent’s long-term memory. We define the MemoryItem class to hold each piece of information and build a MemoryStore with an exponential decay mechanism. We begin laying the foundation for storing and aging information just like a human’s memory. Check out the FULL CODES here.

 def add(self, kind:str, content:str, score:float=1.0):
       self.items.append(MemoryItem(kind, content, score))


   def search(self, query:str, topk=3):
       scored = []
       for it in self.items:
           decay = self._decay_factor(it)
           sim = len(set(query.lower().split()) & set(it.content.lower().split()))
           final = (it.score * decay) + sim
           scored.append((final, it))
       scored.sort(key=lambda x: x[0], reverse=True)
       return [it for _, it in scored[:topk] if _ > 0]


   def cleanup(self, min_score=0.1):
       new = []
       for it in self.items:
           if it.score * self._decay_factor(it) > min_score:
               new.append(it)
       self.items = new

We expand the memory system by adding methods to insert, search, and clean old memories. We implement a simple similarity function and a decay-based cleanup routine, enabling the agent to remember relevant facts while automatically forgetting weak or outdated ones. Check out the FULL CODES here.

class Agent:
   def __init__(self, memory:MemoryStore, name="PersonalAgent"):
       self.memory = memory
       self.name = name


   def _llm_sim(self, prompt:str, context:List[str]):
       base = "OK. "
       if any("prefers short" in c for c in context):
           base = ""
       reply = base + f"I considered {len(context)} past notes. "
       if "summarize" in prompt.lower():
           return reply + "Summary: " + " | ".join(context[:2])
       if "recommend" in prompt.lower():
           if any("cybersecurity" in c for c in context):
               return reply + "Recommended: write more cybersecurity articles."
           if any("rag" in c for c in context):
               return reply + "Recommended: build an agentic RAG demo next."
           return reply + "Recommended: continue with your last topic."
       return reply + "Here's my response to: " + prompt


   def perceive(self, user_input:str):
       ui = user_input.lower()
       if "i like" in ui or "i prefer" in ui:
           self.memory.add("preference", user_input, 1.5)
       if "topic:" in ui:
           self.memory.add("topic", user_input, 1.2)
       if "project" in ui:
           self.memory.add("project", user_input, 1.0)
   def act(self, user_input:str):
       mems = self.memory.search(user_input, topk=4)
       ctx = [m.content for m in mems]
       answer = self._llm_sim(user_input, ctx)
       self.memory.add("dialog", f"user said: {user_input}", 0.6)
       self.memory.cleanup()
       return answer, ctx

We design an intelligent agent that utilizes memory to inform its responses. We create a mock language model simulator that adapts replies based on stored preferences and topics. At the same time, the perception function enables the agent to dynamically capture new insights about the user. Check out the FULL CODES here.

def evaluate_personalisation(agent:Agent):
   agent.memory.add("preference", "User likes cybersecurity articles", 1.6)
   q = "Recommend what to write next"
   ans_personal, _ = agent.act(q)
   empty_mem = MemoryStore()
   cold_agent = Agent(empty_mem)
   ans_cold, _ = cold_agent.act(q)
   gain = len(ans_personal) - len(ans_cold)
   return ans_personal, ans_cold, gain

Now we give our agent the ability to act and evaluate itself. We allow it to recall memories to shape contextual answers and add a small evaluation loop to compare personalised responses versus a memory-less baseline, quantifying how much the memory helps. Check out the FULL CODES here.

mem = MemoryStore(decay_half_life=60)
agent = Agent(mem)


print("=== Demo: teaching the agent about yourself ===")
inputs = [
   "I prefer short answers.",
   "I like writing about RAG and agentic AI.",
   "Topic: cybersecurity, phishing, APTs.",
   "My current project is to build an agentic RAG Q&A system."
]
for inp in inputs:
   agent.perceive(inp)


print("n=== Now ask the agent something ===")
user_q = "Recommend what to write next in my blog"
ans, ctx = agent.act(user_q)
print("USER:", user_q)
print("AGENT:", ans)
print("USED MEMORY:", ctx)


print("n=== Evaluate personalisation benefit ===")
p, c, g = evaluate_personalisation(agent)
print("With memory :", p)
print("Cold start  :", c)
print("Personalisation gain (chars):", g)


print("n=== Current memory snapshot ===")
for it in agent.memory.items:
   print(f"- {it.kind} | {it.content[:60]}... | score~{round(it.score,2)}")

Finally, we run the full demo to see our agent in action. We feed it user inputs, observe how it recommends personalised actions, and check its memory snapshot. We witness the emergence of adaptive behaviour, proof that persistent memory transforms a static script into a learning companion.

In conclusion, we demonstrate how adding memory and personalisation makes our agent more human-like, capable of remembering preferences, adapting plans, and forgetting outdated details naturally. We observe that even simple mechanisms such as decay and retrieval significantly improve the agent’s relevance and response quality. By the end, we realize that persistent memory is the foundation of next-generation Agentic AI, one that learns continuously, tailors experiences intelligently, and maintains context dynamically in a fully local, offline setup.


Check out the FULL CODES here. Feel free to check out our GitHub Page for Tutorials, Codes and Notebooks. Also, feel free to follow us on Twitter and don’t forget to join our 100k+ ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.

The post How to Design a Persistent Memory and Personalized Agentic AI System with Decay and Self-Evaluation? appeared first on MarkTechPost.