Mengapa Agent AI Anda Terus Kehilangan Memorinya (Dan Bagaimana Kami Memperbaikinya)
Agent AI Anda baru saja melakukan percakapan selama 30 menit dengan seorang pengguna. Mereka membahas persyaratan proyek, berbagi preferensi, dan membuat keputusan. Kemudian pengguna mengetik /new untuk memulai sesi baru.
Agent tersebut mencoba mengonsolidasikan percakapan itu ke dalam long-term memory. Panggilan LLM gagal. Rate limit. Timeout. Atau model mengembalikan teks alih-alih memanggil tool yang diperlukan.
Memorinya hilang. Konteks selama tiga puluh menit, menguap begitu saja.
Hal ini terjadi lebih sering daripada yang Anda kira. Kami melacaknya di seluruh instance LemonClaw kami: konsolidasi memori memiliki tingkat kegagalan sekitar 15% pada model tunggal apa pun. Untuk fitur yang seharusnya menjadi infrastruktur yang tidak terlihat, hal itu tidak dapat diterima.
Bagaimana Framework Lain Menangani Ini (Mereka Tidak Menanganinya)
Sebagian besar framework agent AI memperlakukan konsolidasi memori sebagai panggilan LLM sederhana. Jika berhasil, bagus. Jika tidak, memorinya hilang.
OpenClaw, framework agent open-source paling populer, menggunakan model yang sama untuk konsolidasi seperti untuk percakapan. Panggilan Claude Sonnet yang memakan biaya $0.003 dan membutuhkan waktu 8+ detik, hanya untuk meringkas obrolan yang tidak akan pernah dilihat pengguna. Ketika panggilan itu gagal (rate limit, timeout, error model), framework mencatat peringatan dan melanjutkan. Konteks pengguna pun hilang.
nanobot, framework populer lainnya, memiliki arsitektur yang sama. Satu model, satu percobaan, tanpa fallback. Fungsi konsolidasi bahkan tidak memiliki timeout. Upstream yang lambat (error Cloudflare 524 sering terjadi) memblokir seluruh sesi hingga koneksi terputus.
Kedua framework tersebut tidak memisahkan konsolidasi dari model utama. Keduanya tidak memiliki logika fallback untuk operasi memori. Keduanya tidak membedakan antara "panggilan API gagal" dan "panggilan API berhasil tetapi model tidak melakukan apa yang kita minta."
Ini bukanlah kasus langka. Dengan tingkat kegagalan 15% pada model tunggal apa pun, sebuah framework yang menjalankan 100 konsolidasi per hari akan kehilangan memori pada 15 di antaranya. Selama seminggu, itu berarti 105 percakapan di mana agent melupakan segalanya.
Masalahnya Lebih Dalam Daripada Logika Retry
Perbaikan yang jelas adalah retry dengan exponential backoff. Kami sudah memilikinya. Ini menangani error HTTP sementara dengan baik:
# Retry loop: 1s โ 2s โ 4s backoff
for attempt in range(3):
try:
response = await acompletion(**kwargs)
return await self._collect_stream(response)
except (RateLimitError, APIConnectionError) as e:
await asyncio.sleep(RETRY_DELAYS[attempt])
Ini menangkap error 429 dan gangguan jaringan. Namun, dua mode kegagalan tetap lolos:
Mode kegagalan 1: Model tidak dapat melakukan tool calling. Beberapa model, terutama yang lebih kecil yang berjalan pada inference engine yang cepat, sesekali gagal menghasilkan pemanggilan fungsi yang valid pada prompt yang kompleks. API mengembalikan status 200 dengan ServiceUnavailableError yang terbungkus di dalam MidStreamFallbackError. Logika retry Anda melihat pengecualian, mencoba kembali model yang sama, dan mendapatkan error yang sama.
Mode kegagalan 2: Model "berhasil" tetapi tidak memanggil tool. LLM mengembalikan respons yang sangat valid. HTTP 200. Tidak ada error. Namun, alih-alih memanggil save_memory dengan data terstruktur, ia menulis ringkasan teks biasa. Mesin retry Anda menganggap ini sebagai keberhasilan. Fungsi konsolidasi memeriksa tool calls, tidak menemukannya, dan menyerah.
Mode kegagalan kedua adalah yang paling berbahaya. Lapisan transport mengira semuanya berjalan lancar. Lapisan bisnis tahu itu tidak berhasil. Tidak ada jumlah retry tingkat HTTP yang akan memperbaiki model yang tidak memahami skema tool Anda.
Arsitektur Dual-Layer Fallback
Kami menyelesaikan ini dengan dua loop fallback independen yang beroperasi pada level yang berbeda:
User mengirim /new
โ
โผ
consolidate() โโโ Business Layer Fallback
โ "Apakah model memanggil save_memory?"
โ Tidak โ coba model berikutnya dalam rantai
โ
โผ
_chat_with_retry() โโโ Transport Layer Fallback
โ Error HTTP โ exponential backoff
โ Semua retry habis โ telusuri rantai fallback
โ
โผ
Rantai fallback MODEL_MAP:
llama-3.3-70b โ$0.59/Mโโ qwen3-32b โ$0.29/Mโโ llama-4-scout โ$0.11/Mโโ gpt-4.1-mini โโ claude-haiku
(394 TPS) (662 TPS) (594 TPS) (andal) (opsi terakhir)
Layer 1 menangani kegagalan transport. Layer 2 menangani kegagalan logika bisnis. Rantai fallback digunakan bersama oleh kedua layer, didefinisikan sekali dalam katalog pusat.
Ini adalah pendekatan yang secara fundamental berbeda dari sekadar mencoba kembali model yang sama. Ketika sebuah model gagal memanggil tool, mencobanya kembali dengan prompt yang sama jarang membuahkan hasil. Beralih ke model yang berbeda dengan weights yang berbeda dan perilaku tool calling yang berbeda justru lebih efektif.
Katalog Model: Satu Sumber Kebenaran
Setiap model dalam katalog kami memiliki field fallback opsional yang menunjuk ke model berikutnya untuk dicoba:
@dataclass(frozen=True)
class ModelEntry:
id: str
label: str
tier: str
description: str
fallback: str | None = None
hidden: bool = False # Tersembunyi dari daftar /model yang menghadap pengguna
MODEL_CATALOG = [
# Model yang terlihat oleh pengguna (16 model yang dapat dipilih pengguna)
ModelEntry("claude-sonnet-4-6", "Claude Sonnet 4.6", "standard",
"Recommended", fallback="claude-sonnet-4-5"),
ModelEntry("gpt-4.1-mini", "GPT-4.1 Mini", "economy",
"Stable tool calling", fallback="claude-haiku-4-5"),
# Model konsolidasi tersembunyi (hanya untuk penggunaan internal)
ModelEntry("llama-3.3-70b-versatile", "Llama 3.3 70B (Groq)", "economy",
"394 TPS", fallback="qwen3-32b", hidden=True),
ModelEntry("qwen3-32b", "Qwen3 32B (Groq)", "economy",
"662 TPS", fallback="llama-4-scout-17b-16e-instruct", hidden=True),
# ...
]
Flag hidden=True menjaga model internal agar tidak muncul dalam perintah /model yang menghadap pengguna, namun tetap berpartisipasi dalam rantai fallback. Pengguna melihat 16 model yang dapat mereka pilih. Sistem menggunakan 19. Tiga model tersembunyi tersebut ada semata-mata untuk tugas latar belakang seperti konsolidasi memori, di mana kecepatan dan biaya lebih penting daripada kualitas percakapan.
Katalog ini adalah satu-satunya sumber kebenaran untuk semua perutean model. Menambahkan model baru ke rantai fallback hanya butuh satu baris kode. Tidak ada file konfigurasi untuk disinkronkan, tidak ada environment variables untuk diperbarui, tidak ada skrip deployment untuk dimodifikasi.
Transport Layer: Fallback Berantai dengan Deteksi Siklus
Mesin retry menelusuri rantai fallback menggunakan set yang dikunjungi untuk mencegah loop tak terbatas:
async def _chat_with_retry(self, kwargs, original_model):
# Tahap 1: Exponential backoff pada model utama
for attempt in range(3):
try:
response = await acompletion(**kwargs)
return await self._collect_stream(response)
except (RateLimitError, APIConnectionError, APIError) as e:
await asyncio.sleep(RETRY_DELAYS[attempt])
except AuthenticationError:
return LLMResponse(content="API key invalid.", finish_reason="error")
# Tahap 2: Telusuri rantai fallback
visited = {original_model}
current = original_model
while True:
entry = MODEL_MAP.get(current)
if not entry or not entry.fallback or entry.fallback in visited:
break
current = entry.fallback
visited.add(current)
# Resolusi gateway yang benar untuk model ini
gw = self._resolve_gateway_for_model(current)
resolved = self._resolve_model(current, gateway=gw)
fb_kwargs = {**kwargs, "model": resolved}
# Perbaiki api_base untuk protokol model target
if gw and gw.default_api_base:
fb_kwargs["api_base"] = gw.default_api_base
try:
response = await acompletion(**fb_kwargs)
return await self._collect_stream(response)
except Exception:
continue # Coba berikutnya dalam rantai
return LLMResponse(content="Service unavailable.", finish_reason="error")
Set visited sangatlah krusial. Tanpa itu, rantai seperti AโBโA akan berputar selamanya. Dengan itu, mesin mencoba setiap model tepat satu kali.
Resolusi gateway juga penting. Model yang berbeda membutuhkan format API yang berbeda. Model Claude merutekan melalui gateway format Anthropic (tanpa akhiran /v1). Model GPT merutekan melalui gateway yang kompatibel dengan OpenAI (dengan /v1). Model Groq menggunakan endpoint lain lagi. Mesin fallback meresolusi gateway yang benar untuk setiap model dalam rantai, mencegah ketidakcocokan protokol seperti mengirim permintaan Anthropic ke endpoint OpenAI.
Ini adalah detail yang diabaikan oleh sebagian besar framework. Mereka mengasumsikan semua model menggunakan protokol yang sama. Di lingkungan produksi, dengan 19 model di 4 format API yang berbeda, asumsi itu langsung terpatahkan.
Business Layer: Verifikasi Tool Call
Fungsi konsolidasi menambahkan loop fallback-nya sendiri di atasnya:
async def consolidate(self, session, provider, model, **kwargs):
visited = set()
current_model = model
while current_model and current_model not in visited and len(visited) <= 3:
visited.add(current_model)
response = await asyncio.wait_for(
provider.chat(messages=messages, tools=SAVE_MEMORY_TOOL, model=current_model),
timeout=30,
)
if response.has_tool_calls:
# Berhasil: ekstrak dan simpan memori
args = response.tool_calls[0].arguments
self.write_long_term(args["memory_update"])
self.append_history(args["history_entry"])
return True
# Model tidak memanggil tool โ coba berikutnya dalam rantai
entry = MODEL_MAP.get(current_model)
next_model = entry.fallback if entry else None
if next_model and next_model not in visited:
current_model = next_model
continue
return False # Tidak ada lagi fallback
return False
Ini menangkap kasus di mana _chat_with_retry mengembalikan respons yang berhasil (HTTP 200, konten valid) tetapi model tidak menggunakan tool. Fungsi konsolidasi memeriksa has_tool_calls, dan jika tidak ada, pindah ke model berikutnya dalam rantai.
Pembungkus timeout (asyncio.wait_for) juga memicu fallback. Jika sebuah model memakan waktu lebih dari 30 detik (umum terjadi dengan error Cloudflare 524 pada upstream yang lambat), fungsi tersebut menangkap TimeoutError dan mencoba model berikutnya daripada memblokir sesi pengguna tanpa batas waktu.
Mengapa Groq untuk Konsolidasi
Konsolidasi memori adalah tugas latar belakang. Pengguna tidak melihat output-nya. Mereka hanya butuh itu berfungsi. Hal ini menjadikannya kandidat sempurna untuk model yang cepat dan murah.
Sebagian besar framework menggunakan model mahal yang sama untuk segalanya. Jika Anda menjalankan Claude Sonnet untuk percakapan, Anda juga menjalankan Claude Sonnet untuk konsolidasi memori. Itu berarti $3/M token input dan 8+ detik per konsolidasi, untuk tugas yang menghasilkan output yang tidak pernah dibaca manusia.
Kami memisahkan konsolidasi dari model percakapan sepenuhnya. Percakapan menggunakan model apa pun yang dipilih pengguna. Konsolidasi menggunakan rantai khusus model yang di-host di Groq:
| Model | Kecepatan | Biaya Input | Biaya Output |
|---|---|---|---|
| llama-3.3-70b-versatile | 394 TPS | $0.59/M | $0.79/M |
| qwen3-32b | 662 TPS | $0.29/M | $0.59/M |
| llama-4-scout-17b-16e | 594 TPS | $0.11/M | $0.34/M |
| gpt-4.1-mini (sebelumnya) | ~150 TPS | $0.40/M | $1.60/M |
Model utama (llama-3.3-70b) mengonsolidasikan sesi 60 pesan dalam waktu ~5 detik. Default sebelumnya (gpt-4.1-mini) membutuhkan 8+ detik. Biaya per konsolidasi turun dari ~$0.003 menjadi ~$0.001.
Tradeoff-nya: model Groq memiliki tool calling yang kurang andal pada prompt yang kompleks. Itulah tepatnya mengapa dual-layer fallback ada. Ketika llama-3.3-70b gagal memanggil tool, qwen3-32b mengambil alih. Jika itu gagal juga, llama-4-scout mencoba. Jika ketiga model Groq gagal, gpt-4.1-mini menanganinya dengan keandalan tool calling yang mendekati 100%.
Dalam produksi, kami melihat model utama berhasil ~85% dari waktu. Rantai mencapai gpt-4.1-mini dalam kurang dari 2% konsolidasi. Tingkat kegagalan total: secara efektif nol.
Hasil Produksi
Kami menerapkan ini pada dua instance LemonClaw dan mengujinya dengan percakapan Telegram sungguhan.
Deployment pertama (hanya single-layer fallback):
Memory consolidation (archive_all): 56 messages
llama-3.3-70b-versatile โ "Failed to call a function"
Falling back โ qwen3-32b
qwen3-32b: LLM did not call save_memory, skipping
โ "Memory archival failed, session not cleared."
Lapisan transport menangkap kegagalan pertama dan melakukan fallback. Namun qwen3-32b mengembalikan teks tanpa memanggil tool. Single-layer fallback tidak bisa menangani ini. Ini adalah skenario persis di mana setiap framework lain akan kehilangan memori secara diam-diam.
Deployment kedua (dual-layer fallback):
Memory consolidation (archive_all): 60 messages
model=llama-3.3-70b-versatile โ success
Memory consolidation done: 60 messages remaining
Model yang sama, volume pesan yang sama. Kali ini berhasil pada percobaan pertama. Sifat kegagalan tool calling yang intermiten adalah alasan mengapa Anda membutuhkan rantai fallback daripada model cadangan tunggal.
Ketika model utama benar-benar gagal, rantai tersebut menangkapnya:
llama-3.3-70b โ tool call failed
โ consolidate() fallback โ qwen3-32b
โ qwen3-32b didn't call tool
โ consolidate() fallback โ llama-4-scout
โ llama-4-scout didn't call tool
โ consolidate() fallback โ gpt-4.1-mini
โ gpt-4.1-mini called save_memory โ
Memory consolidation done
Empat model dicoba, memori terselamatkan. Pengguna melihat "New session started." dan tidak tahu bahwa semua ini terjadi.
Kesenjangan Arsitektur
Sistem memori LemonClaw vs. alternatif lainnya, fitur demi fitur:
| Kemampuan | Framework Agent AI Tipikal | LemonClaw |
|---|---|---|
| Model konsolidasi | Sama dengan percakapan (mahal, lambat) | Rantai model independen, diakselerasi Groq |
| Penanganan kegagalan | Log peringatan, memori hilang | Dual-layer fallback, sedalam 5 model |
| Transport fallback | Retry model yang sama 3x | Fallback berantai lintas model berbeda |
| Business logic fallback | Tidak ada | Verifikasi tool call + penggantian model |
| Perlindungan timeout | Tidak ada (Cloudflare 524 memblokir sesi) | asyncio.wait_for(timeout=30) + fallback |
| Pemangkasan sesi | Tidak ada (konteks tumbuh selamanya) | Pangkas pesan lama setelah konsolidasi |
| Pencarian riwayat | Tidak ada | Rolling window HISTORY.md, dapat dicari dengan grep |
| Model internal | Tidak didukung | hidden=True untuk model khusus sistem |
| Pencegahan siklus | Tidak diperlukan (tidak ada rantai) | Set visited mencegah loop AโBโA |
| Resolusi gateway | Diasumsikan format API tunggal | Gateway per model dengan deteksi protokol |
Setiap baris dalam tabel ini mewakili kegagalan produksi yang kami alami sendiri atau kami amati di tracker isu framework lain. Dual-layer fallback, katalog model tersembunyi, resolusi gateway per model, fallback yang dipicu timeout: tidak satu pun dari ini ada di OpenClaw, nanobot, atau framework agent open-source lainnya yang telah kami periksa.
Apa yang Kami Pelajari
"Permintaan berhasil" bukan berarti "tugas berhasil." Mesin retry generik beroperasi pada level HTTP. Mereka tidak bisa tahu bahwa respons 200 dengan JSON yang valid sebenarnya adalah kegagalan karena model tidak menggunakan tool yang Anda minta. Operasi bisnis yang kritis membutuhkan kriteria keberhasilan mereka sendiri dan logika fallback mereka sendiri.
Model kecil gagal dengan cara yang berbeda dari model besar. Model besar (GPT-4.1, Claude Sonnet) hampir selalu memanggil tool saat diminta. Model kecil pada inference engine yang cepat terkadang menghasilkan respons yang terlihat valid tetapi mengabaikan skema tool sepenuhnya. Ini bukan bug yang bisa Anda perbaiki dengan prompt engineering. Ini adalah kesenjangan kemampuan yang membutuhkan mitigasi arsitektural.
Uji dengan data produksi, bukan data sintetis. Tes awal kami dengan 6 pesan sintetis lulus pada setiap model. Sesi 60 pesan yang sebenarnya dengan riwayat tool call, timestamp, dan campuran bahasa gagal pada dua dari tiga model Groq. Kompleksitas data nyata mengekspos mode kegagalan yang tidak akan pernah ditemukan oleh data uji yang bersih.
LemonClaw adalah framework agent AI open-source dengan perutean multi-model bawaan, memori persisten, dan integrasi dengan 10+ platform chat. Seluruh sistem dual-layer fallback yang dijelaskan di sini disertakan dalam rilis open-source. Jalankan di server Anda sendiri: github.com/hedging8563/lemonclaw
Butuh 300+ model AI melalui satu API key? lemondata.cc menyediakan akses terpadu ke OpenAI, Anthropic, Google, DeepSeek, Groq, dan banyak lagi.
