Zašto vaš AI agent sve zaboravlja — i kako to popraviti
Zamislite ovakvu situaciju: razgovarate s AI asistentom, kažete mu da ste vegeterijanac, da ste alergični na orašaste plodove i da obožavate mediteransku kuhinju. Agent vam preporuči savršen restoran. Sutradan otvorite novi razgovor — i agent pojma nema tko ste. Predlaže vam steak house.
Frustrirajuće, zar ne?
Problem je zapravo prilično fundamentalan: veliki jezični modeli (LLM-ovi) su bez stanja (stateless). Svaki poziv API-ju je čist list papira. Model ne pamti prošle razgovore, korisničke preferencije ni rezultate prethodnih zadataka. Sve što zna dolazi iz treninga (parametarsko znanje) i onoga što mu stavite u trenutni prompt — kontekstni prozor.
Ali evo zašto je ovo važno upravo sada. U 2026., memorija za AI agente postala je ključna infrastrukturna komponenta — jednako važna kao i sam LLM. Istraživanja pokazuju da agenti s memorijom postižu 26% veću točnost odgovora, 91% brže vrijeme odaziva i do 90% manju potrošnju tokena u usporedbi s pristupima koji guraju cijelu povijest razgovora u kontekst. To nisu zanemarivi brojevi.
U ovom vodiču provest ću vas kroz to kako funkcionira memorija AI agenata, koji tipovi memorije postoje, kako odabrati pravi okvir za svoj projekt i — najvažnije — kako zapravo implementirati dugoročno pamćenje u Pythonu koristeći Mem0, trenutno vodeći open-source okvir za memoriju agenata. Idemo.
Tipovi memorije AI agenata: Od RAM-a do tvrdog diska
Memoriju AI agenata najlakše je razumjeti kroz analogiju s ljudskim pamćenjem — ili, ako ste programer, kroz analogiju s računalnim sustavom. Postoje dva temeljna tipa, svaki s nekoliko podkategorija.
Kratkoročna memorija (Short-Term Memory)
Kratkoročna memorija funkcionira poput RAM-a — brza je, aktivna i neophodna za trenutni rad, ali nestaje čim se proces završi. U kontekstu AI agenata, to je kontekstni prozor LLM-a: posljednje poruke u razgovoru, sistemski prompt, rezultati poziva alata i koraci razmišljanja.
Implementacija je zapravo jednostavna — obično je to lista poruka (message buffer) koja se šalje uz svaki poziv modelu. Problem? Kad razgovor postane predug. Kontekstni prozor ima fiksnu veličinu (recimo 128K ili 200K tokena), pa duži razgovori dovode do gubitka konteksta ili eksplozije troškova. Jedno ili drugo, nikad dobro.
Dugoročna memorija (Long-Term Memory)
E sad, tu stvari postaju zanimljive.
Dugoročna memorija je tvrdi disk vašeg agenta — informacije koje preživljavaju između sesija i omogućuju agentu da uči, pamti i prilagođava se tijekom vremena. Dijeli se na tri podvrste:
- Epizodička memorija — pamti specifične prošle događaje i iskustva. Agent se sjeća što se dogodilo, kada i kakav je bio ishod. Recimo, agent pamti da je korisnik prošli tjedan tražio letove za Split i da preferira izravne letove. Ovo mu omogućuje učenje iz vlastitog iskustva.
- Semantička memorija — pohranjuje strukturirano činjenično znanje. Za razliku od epizodičke koja se bavi specifičnim događajima, semantička sadrži generalizirane informacije: činjenice, definicije, pravila. Primjer: agent zna da korisnik radi kao softverski inženjer i programira u Pythonu.
- Proceduralna memorija — pohranjuje naučene vještine i operativno znanje. Agent pamti kako nešto napraviti, ne samo što zna. Na primjer, agent je naučio da za ovog korisnika uvijek treba pokrenuti testove prije predlaganja commita.
Kako memorija tehnički funkcionira
Standardna implementacija dugoročne memorije koristi sljedeći tok:
- Ekstrakcija — iz razgovora se identificiraju relevantne informacije (činjenice, preferencije, događaji)
- Vektorizacija — ekstrahirane informacije pretvaraju se u vektorske reprezentacije (embeddings)
- Pohrana — vektori se spremaju u vektorsku bazu podataka (Pinecone, Weaviate, ChromaDB, Qdrant) s pripadajućim metapodacima
- Dohvat — pri novom upitu, sustav izvodi semantičko pretraživanje (similarity search) i dohvaća top-k najrelevantnijih sjećanja
- Injektiranje — dohvaćena sjećanja ubacuju se u kontekstni prozor LLM-a kao dodatni kontekst
Ako vam ovo zvuči kao RAG — u pravu ste, proces je sličan. Ali postoji ključna razlika: dok RAG dohvaća informacije iz eksternih dokumenata, memorijski sustav dohvaća iz prošlih interakcija samog agenta. Različit izvor, isti mehanizam.
Pregled vodećih okvira za memoriju u 2026.
Ekosustav okvira za memoriju AI agenata značajno je sazrio u posljednje vrijeme. Evo tri vodeća rješenja — i, što je možda još važnije, kada koristiti koje.
Mem0 — za personalizaciju i upravljivu memoriju
Mem0 je trenutno vodeći open-source okvir za memoriju agenata, i iskreno, ne bez razloga. Pruža trorazinski sustav memorije: korisničku, sesijsku i agentsku, koristeći hibridnu arhitekturu koja kombinira vektorsku pohranu, graf relacija i key-value pohranu.
Što ga čini posebnim:
- Automatska ekstrakcija relevantnih činjenica iz razgovora
- Inteligentna deduplikacija i konsolidacija sjećanja
- Podrška za više LLM backendova (OpenAI, Anthropic, Gemini, Groq)
- MCP server integracija za pristup iz Claude Code i sličnih okruženja
- Dostupan kao open-source (self-hosted) ili kao upravljana platforma
Najbolji za: chatbotove za korisničku podršku, personalizirane asistente, B2B copilote.
Zep / Graphiti — za temporalno zaključivanje
Zep radi stvari malo drugačije — modelira memoriju kao temporalni graf znanja. Ne prati samo što se dogodilo, nego i kada se dogodilo i kako se entiteti međusobno odnose kroz vrijeme. Svaka činjenica pohranjuje se kao čvor grafa s vremenskim prozorom valjanosti.
I brojke ne lažu. Na LongMemEval benchmarku s GPT-4o, Zep postiže 63,8% nasuprot Mem0-ovih 49,0% — razlika od punih 15 postotnih bodova, zahvaljujući upravo temporalnom modeliranju.
Najbolji za: aplikacije koje trebaju praćenje entiteta kroz vrijeme, financijske savjetnike, pravne AI sustave.
Letta (bivši MemGPT) — za dugotrajne agente s punim stanjem
Letta koristi pristup inspiriran operacijskim sustavima za upravljanje kontekstom LLM-a. Memorija ovdje nije dodatak — ona je prvorazredna, eksplicitna komponenta agentovog stanja. Označeni memorijski blokovi (core memory blocks) uvijek se injektiraju u prompt, dok se arhivska memorija dohvaća po potrebi.
Agenti mogu eksplicitno pisati, ažurirati ili brisati memorijske blokove putem alata i API-ja. I ključno — memorija preživljava restartove i sesije bez ikakvih problema.
Najbolji za: dugotrajne agente koji trebaju održavati identitet i stanje kroz tjedne ili mjesece.
Usporedba u tablici
| Okvir | Arhitektura | Najbolji za | Licenca |
|---|---|---|---|
| Mem0 | Vektor + Graf + KV hibrid | Personalizacija, chatbotovi | Apache 2.0 |
| Zep | Temporalni graf znanja | Temporalno zaključivanje | Apache 2.0 |
| Letta | OS-inspirirana, LLM-upravljana | Dugotrajni stateful agenti | Apache 2.0 |
Praktična implementacija: Dugoročna memorija s Mem0 u Pythonu
Dosta teorije — ajmo kodirati. Izgradit ćemo kompletnog AI asistenta s dugoročnom memorijom koji pamti korisničke preferencije između sesija. Koristit ćemo Mem0 u self-hosted načinu rada, što znači besplatno i bez potrebe za API ključem platforme.
Preduvjeti i instalacija
Trebat će vam Python 3.10+ i OpenAI API ključ (ili drugi podržani LLM provider). Instalacija je trivijalna:
pip install mem0ai openai python-dotenv
Kreirajte .env datoteku s vašim API ključem:
OPENAI_API_KEY=sk-vaš-ključ-ovdje
Korak 1: Osnovni chatbot s memorijom
Kreirajte datoteku memory_chatbot.py. Ovo je minimalni pristup — chatbot koji automatski sprema i dohvaća sjećanja:
import os
from dotenv import load_dotenv
from openai import OpenAI
from mem0 import Memory
load_dotenv()
# Inicijalizacija OpenAI klijenta i Mem0 memorije
openai_client = OpenAI()
memory = Memory()
def chat_with_memory(message: str, user_id: str = "korisnik_1") -> str:
"""Šalje poruku LLM-u s kontekstom iz memorije."""
# 1. Dohvati relevantna sjećanja za ovog korisnika
relevant_memories = memory.search(
query=message,
user_id=user_id,
limit=5,
)
# 2. Formatiraj sjećanja u tekst za kontekst
memories_text = ""
if relevant_memories and relevant_memories.get("results"):
memories_list = [
f"- {entry['memory']}"
for entry in relevant_memories["results"]
]
memories_text = "\n".join(memories_list)
# 3. Konstruiraj sistemski prompt s memorijom
system_prompt = (
"Ti si pomoćni AI asistent koji pamti korisnikove preferencije "
"i prošle razgovore.\n"
)
if memories_text:
system_prompt += (
f"\nEvo što znaš o ovom korisniku iz prošlih razgovora:\n"
f"{memories_text}\n\n"
"Koristi ove informacije za personalizirane odgovore."
)
# 4. Pozovi LLM
response = openai_client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": message},
],
temperature=0.7,
)
assistant_message = response.choices[0].message.content
# 5. Spremi razgovor u memoriju za buduće dohvate
memory.add(
messages=[
{"role": "user", "content": message},
{"role": "assistant", "content": assistant_message},
],
user_id=user_id,
)
return assistant_message
# Primjer korištenja
if __name__ == "__main__":
# Sesija 1: Korisnik dijeli preferencije
print("=== Sesija 1 ===")
print(chat_with_memory("Ja sam vegeterijanac i alergičan sam na orašaste plodove."))
print(chat_with_memory("Preferiram mediteransku kuhinju, posebno grčku."))
# Sesija 2: Agent se sjeća
print("\n=== Sesija 2 (novi razgovor) ===")
print(chat_with_memory("Možeš li mi preporučiti restoran za večeras?"))
Pokrenite skriptu i primijetit ćete nešto cool: u drugoj „sesiji", kad korisnik traži preporuku restorana, agent automatski dohvaća prethodno pohranjene preferencije — vegeterijanstvo, alergiju na orašaste plodove, mediteransku kuhinju — i daje personaliziran odgovor. Korisnik nije ponovio ni jednu informaciju. To je cijela poanta memorije.
Korak 2: Napredna konfiguracija s vektorskom bazom
Za produkcijsku primjenu, želite konfigurirati specifičnu vektorsku bazu i model za embeddings. Mem0 podržava ChromaDB, Qdrant, Pinecone, Weaviate i mnoge druge. Evo primjera s Qdrantom:
from mem0 import Memory
config = {
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o",
"temperature": 0.1,
},
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536,
},
},
"vector_store": {
"provider": "qdrant",
"config": {
"host": "localhost",
"port": 6333,
"collection_name": "agent_memories",
},
},
"version": "v1.1",
}
memory = Memory.from_config(config)
# Dodavanje sjećanja s različitim opsezima
memory.add(
"Korisnik preferira Python za backend razvoj.",
user_id="dev_42",
metadata={"category": "tech_preferences"},
)
memory.add(
"Dogovorili smo se da koristimo FastAPI za novi projekt.",
user_id="dev_42",
agent_id="coding_assistant",
metadata={"category": "project_decisions"},
)
# Pretraživanje s filterima
results = memory.search(
"Koje tehnologije korisnik preferira?",
user_id="dev_42",
limit=3,
)
for result in results["results"]:
print(f"Sjećanje: {result['memory']}")
print(f"Relevantnost: {result['score']:.3f}")
print("---")
Korak 3: Upravljanje životnim ciklusom sjećanja
U produkciji, memorija nije samo „dodaj i dohvati". Trebate upravljati cijelim životnim ciklusom — ažuriranjem, brisanjem zastarjelih informacija i pregledom pohranjenih sjećanja. Evo kako to izgleda u praksi:
# Dohvati sva sjećanja za korisnika
all_memories = memory.get_all(user_id="dev_42")
print(f"Ukupno sjećanja: {len(all_memories['results'])}")
# Ažuriraj specifično sjećanje
memory.update(
memory_id="abc-123-def",
data="Korisnik je prešao s Pythona na Rust za backend razvoj.",
)
# Obriši zastarjelo sjećanje
memory.delete(memory_id="xyz-789-uvw")
# Obriši sva sjećanja za korisnika (npr. GDPR zahtjev)
memory.delete_all(user_id="dev_42")
# Dohvati povijest promjena sjećanja
history = memory.history(memory_id="abc-123-def")
for entry in history:
print(f"{entry['event']} | {entry['timestamp']} | {entry['old_memory']} → {entry['new_memory']}")
Funkcija history() je ovdje posebno korisna za reviziju (audit trail). Možete pratiti kako se sjećanja mijenjaju tijekom vremena, što je kritično za sukladnost s GDPR-om i sličnim regulativama. Vjerujte mi, kad vam klijent postavi pitanje o tome što agent „zna" o njemu — bit ćete zahvalni što ste ovo implementirali.
Graf memorija: Kada vektorsko pretraživanje nije dovoljno
Vektorsko pretraživanje izvrsno funkcionira za pronalaženje semantički sličnih sjećanja, ali ima jedno ozbiljno ograničenje: ne razumije odnose između entiteta.
Evo konkretnog primjera. Ako agent zna da „Marko radi u Acme Corp" i „Acme Corp koristi AWS", vektorsko pretraživanje neće nužno povezati ta dva sjećanja kad korisnik pita „Koji cloud koristi Markova tvrtka?". Semantički, ta dva fragmenta jednostavno nisu dovoljno slična.
Tu na scenu stupa graf memorija — memorija strukturirana kao graf znanja gdje su čvorovi entiteti, a bridovi odnosi između njih. Mem0 od verzije 1.0 nativno podržava ovaj pristup:
from mem0 import Memory
config = {
"graph_store": {
"provider": "neo4j",
"config": {
"url": "bolt://localhost:7687",
"username": "neo4j",
"password": "vaša-lozinka",
},
},
"version": "v1.1",
}
memory = Memory.from_config(config)
# Mem0 automatski ekstrahira entitete i relacije
memory.add(
"Marko je senior developer u Acme Corp. "
"Acme Corp koristi AWS za infrastrukturu i PostgreSQL za baze podataka.",
user_id="team_lead",
)
# Sada agent može zaključivati preko relacija
results = memory.search(
"Koji cloud provider koristi Markova tvrtka?",
user_id="team_lead",
)
# Rezultat: "Acme Corp koristi AWS" — povezano preko grafa
Graf memorija je posebno moćna kad imate agente koji rade s više korisnika, projekata ili organizacija — svugdje gdje se entiteti međusobno isprepliću i gdje jednostavno vektorsko pretraživanje ne može uhvatiti te veze.
Arhitekturni obrasci za memoriju u produkciji
Implementacija memorije u produkcijskom okruženju zahtijeva promišljenu arhitekturu. Evo tri provjerena obrasca koja sam vidio da dobro funkcioniraju u praksi.
Obrazac 1: Hijerarhijska memorija
Kombinirajte kratkoročnu i dugoročnu memoriju u hijerarhijski sustav. Kratkoročna memorija drži posljednje poruke u kontekstnom prozoru, dok se dugoročna koristi za dohvat relevantnog konteksta iz prošlosti. Zvuči jednostavno, ali pravilna implementacija čini veliku razliku:
class HierarchicalMemoryAgent:
def __init__(self, user_id: str):
self.user_id = user_id
self.short_term: list[dict] = [] # Posljednje poruke
self.max_short_term = 20 # Drži 20 poruka u STM-u
self.long_term = Memory() # Mem0 za LTM
def process_message(self, message: str) -> str:
# Dohvati dugoročni kontekst
ltm_context = self.long_term.search(
query=message, user_id=self.user_id, limit=5
)
# Kombiniraj STM + LTM u prompt
messages = self._build_prompt(message, ltm_context)
# Pozovi LLM
response = self._call_llm(messages)
# Ažuriraj kratkoročnu memoriju
self.short_term.append({"role": "user", "content": message})
self.short_term.append({"role": "assistant", "content": response})
# Obreži STM ako je predug
if len(self.short_term) > self.max_short_term:
# Konsolidiraj stare poruke u LTM prije brisanja
self.long_term.add(
self.short_term[:4], # Spremi najstarije poruke
user_id=self.user_id,
)
self.short_term = self.short_term[4:]
return response
Obrazac 2: Memorija po opsezima
Razdvojite memoriju na korisničku, sesijsku i agentsku razinu. Korisničke memorije traju „zauvijek" (preferencije, profil), sesijske traju koliko i razgovor, a agentske se dijele između svih korisnika kao naučeno ponašanje agenta.
# Korisnička memorija — traje preko svih sesija
memory.add(
"Korisnik preferira formalan ton komunikacije.",
user_id="korisnik_1",
)
# Sesijska memorija — traje samo za ovu sesiju
memory.add(
"Trenutno radimo na migraciji baze podataka s MySQL na PostgreSQL.",
user_id="korisnik_1",
run_id="sesija_2024_04_10",
)
# Agentska memorija — dijeli se između korisnika
memory.add(
"Kad korisnik traži pomoć s migracijom, uvijek provjeri verziju izvorišne baze.",
agent_id="db_migration_assistant",
)
Obrazac 3: Programatska vs. agentička memorija
Ovo je distinkcija koja se često previđa, a zapravo je dosta bitna. Razlikujte dva pristupa spremanju sjećanja:
- Programatska memorija — vi kao razvojni programer eksplicitno definirate što se sprema i kada. Pouzdanije, ali nefleksibilno.
- Agentička memorija — agent sam odlučuje što vrijedi zapamtiti na temelju konteksta razgovora. Fleksibilnije, ali zahtijeva pažljivu evaluaciju.
Mem0 zapravo koristi hibrid oba pristupa — vi pozivate memory.add(), ali okvir automatski ekstrahira činjenice iz razgovora. Za kritične aplikacije (zdravstvo, financije), preporučujem programatski pristup s eksplicitnim pravilima što spremati. Bolje biti siguran nego fleksibilan.
Izazovi i zamke u produkciji
Prije nego što ubacite memoriju u produkciju, morate biti svjesni nekoliko izazova. Naučio sam ovo na teži način, pa ne morate vi.
Zagađenje konteksta
Ako dohvaćate previše sjećanja ili su sjećanja nerelevantna, LLM-ov odgovor može biti lošiji nego bez memorije. Da, dobro ste pročitali — više memorije ne znači automatski bolje rezultate. Ključno je fino podešavanje parametra limit i korištenje pragova relevantnosti (score threshold). Počnite s 3-5 sjećanja i testirajte odatle.
Skalabilnost dohvata
Naivan pristup — spremanje svakog razgovora u vektorsku bazu — dovodi do katastrofalnog šuma pri dohvatu nakon tjedana ili mjeseci korištenja. Rješenje? Inteligentna konsolidacija (spajanje povezanih sjećanja), brisanje zastarjelih informacija i tiered storage. Nemojte samo trpati podatke unutra i nadati se najboljem.
Privatnost i sukladnost
Ovo je tema o kojoj se premalo priča. Memorija agenta pohranjuje osobne podatke korisnika, pa morate implementirati:
- Mehanizme za pregled, uređivanje i brisanje sjećanja (GDPR pravo na zaborav)
- Politike retencije podataka — koliko dugo čuvati sjećanja
- Revizijski trag (tko je pristupio kojim sjećanjima i kada)
Evaluacija kvalitete memorije
LOCOMO benchmark koristan je za opću evaluaciju, ali ne hvata aplikacijski specifičnu kvalitetu. Sustav koji postiže 66% na LOCOMO-u može odlično raditi za asistenta za kodiranje i katastrofalno za zdravstvenu aplikaciju. Moj savjet: razvijte vlastite evaluacijske testove specifične za vaš slučaj upotrebe. Generički benchmarkovi vam daju smjer, ali ne i odgovor.
Često postavljana pitanja
Koja je razlika između memorije AI agenta i RAG sustava?
RAG (Retrieval-Augmented Generation) dohvaća informacije iz eksternih dokumenata — baza znanja, dokumentacija, članci. Memorija AI agenta dohvaća informacije iz prošlih interakcija samog agenta — korisničke preferencije, prethodne razgovore, naučene obrasce ponašanja. U praksi, ova dva sustava se često kombiniraju: agent koristi RAG za pristup znanju i memoriju za personalizaciju.
Trebam li memoriju za sve AI agente?
Ne, definitivno ne. Jednostavni agenti koji obrađuju izolirane zahtjeve (prevođenje teksta, generiranje slike) ne trebaju memoriju. Memorija postaje kritična tek kad agent treba održavati kontekst kroz više sesija, personalizirati odgovore ili učiti iz prethodnih interakcija — dakle korisnička podrška, osobni asistenti, agenti za upravljanje projektima i slično.
Koliko memorija AI agenta košta u produkciji?
Trošak ovisi o tri komponente: LLM pozivi za ekstrakciju sjećanja (svaki add() poziv koristi LLM za identifikaciju relevantnih činjenica), vektorska pohrana (ChromaDB je besplatan za self-hosting, upravljane usluge poput Pinecone kreću od ~25$/mjesečno) i embedding model (text-embedding-3-small košta ~0,02$/1M tokena). Za tipičnog agenta s tisuću korisnika, mjesečni trošak memorije kreće se od 10 do 50 dolara. Iznenađujuće pristupačno, zapravo.
Kako spriječiti da agent zapamti netočne informacije?
Tri pristupa koji se u praksi pokazuju kao najdjelotvorniji: (1) validacija pri unosu — koristite LLM za provjeru konzistentnosti novih sjećanja s postojećima, (2) korisnička kontrola — omogućite korisnicima pregled i brisanje pohranjenih sjećanja, i (3) vremenski prozori — automatski označavajte stara sjećanja kao potencijalno zastarjela i tražite potvrdu prije korištenja.
Mogu li koristiti Mem0 s Claudeom umjesto OpenAI-ja?
Da, bez problema. Mem0 podržava više LLM providera, uključujući Anthropic Claude. Jednostavno promijenite konfiguraciju LLM providera u config objektu na "provider": "anthropic" i postavite ANTHROPIC_API_KEY kao varijablu okruženja. Svi ostali dijelovi — vektorska pohrana, pretraživanje, životni ciklus sjećanja — funkcioniraju identično.