AI agent Anda baru saja melakukan percakapan selama 30 menit dengan seorang pengguna. Mereka mendiskusikan persyaratan proyek, berbagi preferensi, dan membuat keputusan. Kemudian pengguna mengetik /new untuk memulai sesi baru.
Agent mencoba mengonsolidasikan percakapan tersebut ke dalam memori jangka panjang. 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.
Ini terjadi lebih sering daripada yang Anda bayangkan. Dalam runtime Hermes Agent, konsolidasi memori memiliki tingkat kegagalan ~15% pada model tunggal mana pun sebelum kami menambahkan fallback khusus. Untuk fitur yang seharusnya menjadi infrastruktur yang tidak terlihat, hal itu tidak dapat diterima.
Jika Anda membangun permukaan produk di sekitarnya dan bukan hanya subsistem memori, sandingkan halaman ini dengan panduan chatbot satu kunci dan panduan rate limiting AI API. Daya tahan memori hanya penting ketika agent tersebut benar-benar hidup di dalam aplikasi yang dapat digunakan.
Bagaimana Framework Lain Menanganinya (Mereka Tidak Melakukannya)
Kebanyakan framework AI agent memperlakukan konsolidasi memori sebagai panggilan LLM sederhana. Jika berhasil, bagus. Jika tidak, memori akan hilang.
Baseline Hermes Agent menggunakan model yang sama untuk konsolidasi seperti untuk percakapan. Panggilan Claude Sonnet yang berbiaya $0,003 dan memakan waktu 8+ detik, hanya untuk merangkum chat yang tidak akan pernah dilihat pengguna. Ketika panggilan itu gagal (rate limit, timeout, error model), framework mencatat peringatan dan melanjutkan. Konteks pengguna hilang.
nanobot, framework populer lainnya, memiliki arsitektur yang sama. Satu model, satu upaya, 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 bukan kasus ekstrem. Dengan tingkat kegagalan 15% pada model tunggal mana pun, 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 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, terkadang gagal menghasilkan pemanggilan fungsi yang valid pada prompt yang kompleks. API mengembalikan 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 pemanggilan tool, tidak menemukannya, dan menyerah.
Mode kegagalan kedua adalah yang paling berbahaya. Transport layer mengira semuanya berhasil. Business layer tahu bahwa itu tidak berhasil. Retry tingkat HTTP sebanyak apa pun tidak akan memperbaiki model yang tidak memahami skema tool Anda.
Arsitektur Fallback Dua Lapis
Kami menyelesaikan ini dengan dua loop fallback independen yang beroperasi pada level yang berbeda:
Pengguna mengirim /new
│
▼
consolidate() ─── Fallback Business Layer
│ "Apakah model memanggil save_memory?"
│ Tidak → coba model berikutnya dalam rantai
│
▼
_chat_with_retry() ─── Fallback Transport Layer
│ 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) (pilihan 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 membantu. Beralih ke model yang berbeda dengan bobot 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 berarti menambahkan satu baris kode. Tidak ada file konfigurasi yang perlu disinkronkan, tidak ada variabel lingkungan yang perlu diperbarui, tidak ada skrip deployment yang perlu dimodifikasi.
Transport Layer: Fallback Berantai dengan Deteksi Siklus
Mesin retry menelusuri rantai fallback menggunakan set visited untuk mencegah loop tak terbatas:
async def _chat_with_retry(self, kwargs, original_model):
# Fase 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")
# Fase 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)
# Selesaikan 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 model berikutnya dalam rantai
return LLMResponse(content="Service unavailable.", finish_reason="error")
Set visited sangat penting. Tanpa itu, rantai seperti A→B→A akan berulang selamanya. Dengan itu, mesin mencoba setiap model tepat satu kali.
Resolusi gateway juga penting. Model yang berbeda membutuhkan format API yang berbeda. Model Claude merute melalui gateway format Anthropic (tanpa akhiran /v1). Model GPT merute melalui gateway yang kompatibel dengan OpenAI (dengan /v1). Model Groq menggunakan endpoint lain lagi. Mesin fallback menyelesaikan 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 berasumsi semua model menggunakan protokol yang sama. Dalam produksi, dengan 19 model di 4 format API yang berbeda, asumsi tersebut langsung hancur.
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 model 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.
Wrapper timeout (asyncio.wait_for) juga memicu fallback. Jika sebuah model memakan waktu lebih dari 30 detik (umum terjadi pada error Cloudflare 524 pada upstream yang lambat), fungsi tersebut menangkap TimeoutError dan mencoba model berikutnya alih-alih 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. Ini menjadikannya kandidat sempurna untuk model yang cepat dan murah.
Kebanyakan 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 ~5 detik. Default sebelumnya (gpt-4.1-mini) memakan waktu 8+ detik. Biaya per konsolidasi turun dari ~$0,003 menjadi ~$0,001.
Risikonya: model Groq memiliki tool calling yang kurang andal pada prompt yang kompleks. Itulah alasan mengapa fallback dua lapis ada. Ketika llama-3.3-70b gagal memanggil tool, qwen3-32b mengambil alih. Jika itu juga gagal, 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 ke dua instance runtime Hermes Agent dan mengujinya dengan percakapan Telegram yang nyata.
Deployment pertama (hanya fallback satu lapis):
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."
Transport layer menangkap kegagalan pertama dan melakukan fallback. Namun, qwen3-32b mengembalikan teks tanpa memanggil tool. Fallback satu lapis tidak bisa menangani ini. Ini adalah skenario tepat di mana framework lain akan kehilangan memori secara diam-diam.
Deployment kedua (fallback dua lapis):
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 satu model cadangan saja.
Ketika model utama 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 tersimpan. Pengguna melihat "Sesi baru dimulai." dan tidak tahu bahwa semua ini terjadi.
Kesenjangan Arsitektur
Sistem memori vs. alternatifnya, fitur demi fitur:
| Kapabilitas | Framework AI Agent Tipikal | Desain fallback dua lapis |
|---|---|---|
| Model konsolidasi | Sama dengan percakapan (mahal, lambat) | Rantai model independen, Groq-accelerated |
| Penanganan kegagalan | Catat peringatan, memori hilang | Fallback dua lapis, sedalam 5 model |
| Fallback transport | Retry model yang sama 3x | Fallback berantai di berbagai model berbeda |
| Fallback logika bisnis | Tidak ada | Verifikasi tool call + pergantian 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, grep-searchable |
| 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 pelacak masalah framework lain. Fallback dua lapis, katalog model tersembunyi, resolusi gateway per model, fallback yang dipicu timeout: tidak ada satu pun dari ini yang ada di nanobot atau framework agent open-source lainnya yang telah kami periksa.
Apa yang Kami Pelajari
"Permintaan berhasil" bukanlah "tugas berhasil." Mesin retry generik beroperasi pada level HTTP. Mereka tidak 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 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 kapabilitas yang membutuhkan mitigasi arsitektural.
Uji dengan data produksi, bukan data sintetis. Pengujian awal kami dengan 6 pesan sintetis lulus pada setiap model. Sesi 60 pesan yang nyata dengan riwayat tool call, timestamp, dan bahasa campuran gagal pada dua dari tiga model Groq. Kompleksitas data nyata mengungkap mode kegagalan yang tidak akan pernah ditemukan oleh data uji yang bersih.
Ini juga mengapa panduan rate limiting AI API penting di sini. Sistem memori tidak hanya membutuhkan “model yang lebih baik.” Ia membutuhkan kebijakan transport, pemeriksaan keberhasilan logika bisnis, dan tangga fallback yang tidak runtuh di bawah kegagalan provider biasa.
Artikel ini menjelaskan pola keandalan dari Hermes Agent. Gunakan pola arsitektur di sini sebagai referensi untuk daya tahan memori, desain fallback, dan perutean model yang sadar gateway.
Butuh 300+ model AI melalui satu API key? tokenlab.sh menyediakan akses terpadu ke OpenAI, Anthropic, Google, DeepSeek, Groq, dan banyak lagi.
