Episode ini menyiapkan agent menghadapi jaringan yang tidak sempurna: menangani rate limit dan throttling dari LLM provider, memasang circuit breakers dan retry policies, hingga graceful degradation ketika service eksternal mati tanpa mematikan agent.

Di episode 13 agent kalian tahu siapa pemanggilnya dan berperilaku sesuai persona. Tapi ada satu kenyataan yang tidak bisa dihindari: service eksternal tidak selalu sehat. LLM provider bisa throttle request kalian, tool API bisa down, jaringan bisa lambat. Agent yang tidak menyiapkan ini akan berubah dari "asisten cerdas" menjadi "kumpulan error" saat sistem lain terganggu.
Roadmap episode ini: menghadapi rate limit dan throttling dari provider model, memasang circuit breakers dan retry policies yang benar, lalu membangun graceful degradation supaya agent tetap berfungsi (meski terbatas) saat service lain mati.
Semua LLM provider membatasi berapa banyak request per menit dan berapa token per menit yang boleh dipakai akun kalian. Ketika kalian melewatinya, provider mengembalikan status 429 bersama header Retry-After yang memberi tahu kapan boleh mencoba lagi.
Pola yang salah: langsung mencoba ulang tanpa jeda. Itu hanya memperburuk throttle. Pola yang benar: exponential backoff dengan jitter — jeda yang makin panjang setiap percobaan, ditambah sedikit keacakan supaya banyak agent yang retry serentak tidak membentuk gelombang.
export function delayMs(attempt, baseMs = 500) {
const exponential = baseMs * 2 ** attempt;
const jitter = Math.random() * exponential * 0.3;
return exponential + jitter;
}
export async function withRetry(fn, { maxAttempts = 5 } = {}) {
let lastError;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await fn();
} catch (err) {
lastError = err;
if (err.status !== 429 && err.status !== 502 && err.status !== 503) {
throw err;
}
await new Promise((r) => setTimeout(r, delayMs(attempt)));
}
}
throw lastError;
}Perhatikan: hanya error tertentu yang layak di-retry. Status 429, 502, dan 503 menandakan masalah sementara; status 400 berarti permintaan memang salah dan retry tidak akan pernah berhasil.
Retry-After memberi tahu waktu tunggu yang diinginkan provider. Menghormatinya jauh lebih baik daripada menebak dengan backoff:
export async function withRetryAfter(fn, maxAttempts = 3) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const res = await fn();
if (res.status !== 429) return res;
const seconds = Number(res.headers.get("Retry-After")) || 2;
await new Promise((r) => setTimeout(r, seconds * 1000));
}
throw new Error("rate limit exceeded");
}Untuk workload yang bisa diprediksi, pertimbangkan juga token bucket di sisi kalian: alokasikan kuota request per detik ke agent, sehingga kalian throttle diri sendiri sebelum provider melakukannya. Ini lebih sopan untuk provider dan lebih stabil untuk latensi agent.
Retry menangani gangguan sesaat. Tapi kalau provider mati total selama lima menit, retry hanya akan membuang waktu dan biaya. Di sinilah circuit breaker berperan: ia memantau rasio kegagalan dan "memutus" aliran request setelah ambang batas tercapai, lalu membiarkan service istirahat.
State machine circuit breaker punya tiga keadaan:
export class CircuitBreaker {
constructor({ threshold = 5, cooldownMs = 30_000 } = {}) {
this.threshold = threshold;
this.cooldownMs = cooldownMs;
this.failures = 0;
this.state = "closed";
this.openedAt = null;
}
async call(fn) {
if (this.state === "open") {
if (Date.now() - this.openedAt > this.cooldownMs) {
this.state = "half-open";
} else {
throw new Error("circuit is open");
}
}
try {
const result = await fn();
this.failures = 0;
this.state = "closed";
return result;
} catch (err) {
this.failures += 1;
if (this.failures >= this.threshold) {
this.state = "open";
this.openedAt = Date.now();
}
throw err;
}
}
}Pasang satu circuit breaker per dependency (satu untuk LLM provider, satu untuk tiap tool API penting), jangan satu untuk semuanya — kalau tool cuaca mati, agent tidak perlu berhenti menjawab pertanyaan non-cuaca. Uji perilakunya dengan skenario simulasi lewat bun run test sebelum menyentuh production.
Saat service eksternal tidak tersedia dan circuit breaker terbuka, agent tidak boleh ikut mati. Ia harus menurunkan kualitas layanan secara elegan:
weather_api gagal, coba weather_fallback yang datanya lebih kasar tapi tetap ada.Strategi fallback tool yang umum di Hermes:
const toolChain = [
fetchCurrencyLive,
fetchCurrencyCached,
];
export async function getRate(pair) {
for (const source of toolChain) {
try {
return { value: await source(pair), source: source.name };
} catch {
continue;
}
}
return { value: null, error: "semua sumber kurs tidak tersedia" };
}Poin penting: jangan menyembunyikan degradasi. Kalau jawaban memakai data cache yang basi, sampaikan itu ke user. Transparansi seperti ini menjaga kepercayaan jauh lebih baik daripada menyajikan data lama seolah-olah real-time.
Info
Pilihan terakhir yang paling aman adalah menolak dengan sopan: "Maaf, layanan kurs sedang gangguan, coba lagi sebentar lagi." Gagal dengan jelas jauh lebih baik daripada menjawab salah dengan percaya diri.
Resilience tanpa pengukuran hanya keberuntungan. Lacak metrik berikut untuk tiap dependency:
open.Metrik ini bisa diumpankan ke observability agent (episode 7) dan dijadikan alarm: circuit breaker yang terbuka lebih dari beberapa menit berarti ada service yang benar-benar perlu ditangani manusia.
Episode 14 membuat agent kalian kebal guncangan. Kalian menghadapi rate limit dengan exponential backoff ber-jitter dan menghormati header Retry-After, menahan serangan kegagalan dengan circuit breaker ber-state machine, serta menurunkan kualitas layanan secara elegan lewat fallback tool dan cache last-known-good — sambil tetap transparan soal data yang mungkin basi.
Inti yang harus dibawa pulang:
429, 502, 503 layak dicoba; error lain dibiarkan gagal.Retry-After dan tambahkan jitter supaya retry massal tidak mengguncang provider.closed, open, dan half-open.Episode 15 berikutnya kita membuat agent kalian hemat dan cepat: Performance Optimization — meminimalkan biaya prompt dan pemakaian token, caching respons model dan hasil tool, serta profiling latensi runtime. Sampai jumpa!