$npx -y skills add vibeeval/vibecosystem --skill circuit-breakerAgent hata toleransi ve devre kesici pattern. Ust uste hata yapan agent'i durdur, cooldown uygula, fallback'e gec. Kaskatli hatalari ve sonsuz retry dongularini onler.
| 1 | # Circuit Breaker for Agents |
| 2 | |
| 3 | Agent'lar da servisler gibi basarisiz olabilir. Ayni hatayi tekrar tekrar denemek token israf eder ve sorunu cozmez. Circuit breaker bunu onler. |
| 4 | |
| 5 | ## 3 Durum |
| 6 | |
| 7 | ``` |
| 8 | CLOSED (Normal) |
| 9 | Agent calisir, hatalar sayilir. |
| 10 | Hata esigi asilirsa → OPEN'a gec. |
| 11 | |
| 12 | OPEN (Devre Kesik) |
| 13 | Agent CALISTIRILMAZ. |
| 14 | Cooldown suresi boyunca bekle. |
| 15 | Cooldown bitince → HALF-OPEN'a gec. |
| 16 | |
| 17 | HALF-OPEN (Test) |
| 18 | Tek bir istek gonder. |
| 19 | Basarili → CLOSED'a don. |
| 20 | Basarisiz → OPEN'a geri don (cooldown uzat). |
| 21 | ``` |
| 22 | |
| 23 | ``` |
| 24 | basarili hata esigi |
| 25 | ┌──────────┐ ┌───────────┐ |
| 26 | │ │ │ │ |
| 27 | ▼ │ ▼ │ |
| 28 | CLOSED ──────┼── OPEN ────── HALF-OPEN |
| 29 | ▲ │ │ │ |
| 30 | │ │ │ │ |
| 31 | └──────────┘ └───────────┘ |
| 32 | normal cooldown bitti |
| 33 | ``` |
| 34 | |
| 35 | ## Konfigrasyon |
| 36 | |
| 37 | ```typescript |
| 38 | interface CircuitBreakerConfig { |
| 39 | failureThreshold: number // Kac hata sonrasi OPEN (default: 3) |
| 40 | cooldownMs: number // OPEN'da bekleme suresi (default: 60000 = 1 dk) |
| 41 | halfOpenMaxAttempts: number // HALF-OPEN'da max deneme (default: 1) |
| 42 | resetAfterMs: number // Hata sayacini sifirla (default: 300000 = 5 dk) |
| 43 | onOpen?: () => void // OPEN'a gecince cagrilir |
| 44 | onClose?: () => void // CLOSED'a donunce cagrilir |
| 45 | } |
| 46 | |
| 47 | const DEFAULT_CONFIG: CircuitBreakerConfig = { |
| 48 | failureThreshold: 3, |
| 49 | cooldownMs: 60000, |
| 50 | halfOpenMaxAttempts: 1, |
| 51 | resetAfterMs: 300000, |
| 52 | } |
| 53 | ``` |
| 54 | |
| 55 | ## Uygulama |
| 56 | |
| 57 | ### Agent Seviyesinde |
| 58 | |
| 59 | ```typescript |
| 60 | class AgentCircuitBreaker { |
| 61 | private state: 'CLOSED' | 'OPEN' | 'HALF-OPEN' = 'CLOSED' |
| 62 | private failures = 0 |
| 63 | private lastFailureTime = 0 |
| 64 | private config: CircuitBreakerConfig |
| 65 | |
| 66 | constructor(private agentName: string, config?: Partial<CircuitBreakerConfig>) { |
| 67 | this.config = { ...DEFAULT_CONFIG, ...config } |
| 68 | } |
| 69 | |
| 70 | canExecute(): boolean { |
| 71 | if (this.state === 'CLOSED') return true |
| 72 | |
| 73 | if (this.state === 'OPEN') { |
| 74 | const elapsed = Date.now() - this.lastFailureTime |
| 75 | if (elapsed >= this.config.cooldownMs) { |
| 76 | this.state = 'HALF-OPEN' |
| 77 | return true |
| 78 | } |
| 79 | return false |
| 80 | } |
| 81 | |
| 82 | // HALF-OPEN: tek denemeye izin ver |
| 83 | return true |
| 84 | } |
| 85 | |
| 86 | recordSuccess(): void { |
| 87 | this.failures = 0 |
| 88 | if (this.state === 'HALF-OPEN') { |
| 89 | this.state = 'CLOSED' |
| 90 | this.config.onClose?.() |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | recordFailure(): void { |
| 95 | this.failures++ |
| 96 | this.lastFailureTime = Date.now() |
| 97 | |
| 98 | if (this.state === 'HALF-OPEN') { |
| 99 | this.state = 'OPEN' |
| 100 | return |
| 101 | } |
| 102 | |
| 103 | if (this.failures >= this.config.failureThreshold) { |
| 104 | this.state = 'OPEN' |
| 105 | this.config.onOpen?.() |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | getStatus(): { state: string; failures: number; agent: string } { |
| 110 | return { state: this.state, failures: this.failures, agent: this.agentName } |
| 111 | } |
| 112 | } |
| 113 | ``` |
| 114 | |
| 115 | ### Kullanim Ornegi |
| 116 | |
| 117 | ```typescript |
| 118 | const breakers: Record<string, AgentCircuitBreaker> = { |
| 119 | 'code-reviewer': new AgentCircuitBreaker('code-reviewer', { failureThreshold: 3 }), |
| 120 | 'security-reviewer': new AgentCircuitBreaker('security-reviewer', { failureThreshold: 2 }), |
| 121 | 'sleuth': new AgentCircuitBreaker('sleuth', { failureThreshold: 3 }), |
| 122 | } |
| 123 | |
| 124 | async function spawnAgent(name: string, task: string): Promise<string> { |
| 125 | const breaker = breakers[name] |
| 126 | |
| 127 | if (!breaker?.canExecute()) { |
| 128 | console.warn(`Circuit OPEN: ${name} -- fallback kullaniliyor`) |
| 129 | return executeFallback(name, task) |
| 130 | } |
| 131 | |
| 132 | try { |
| 133 | const result = await executeAgent(name, task) |
| 134 | breaker.recordSuccess() |
| 135 | return result |
| 136 | } catch (error) { |
| 137 | breaker.recordFailure() |
| 138 | console.error(`${name} basarisiz (${breaker.getStatus().failures}/${3})`) |
| 139 | |
| 140 | if (!breaker.canExecute()) { |
| 141 | return executeFallback(name, task) |
| 142 | } |
| 143 | throw error |
| 144 | } |
| 145 | } |
| 146 | ``` |
| 147 | |
| 148 | ## Fallback Zinciri |
| 149 | |
| 150 | Agent devre disiyken ne yapilacagi: |
| 151 | |
| 152 | | Agent | Fallback 1 | Fallback 2 | Fallback 3 | |
| 153 | |-------|-----------|-----------|-----------| |
| 154 | | code-reviewer | Manuel Grep review | Basit lint calistir | Kullaniciya bildir | |
| 155 | | security-reviewer | Grep ile secret scan | SAST tool calistir | Kullaniciya bildir | |
| 156 | | sleuth | scout ile arastir | Manuel debug | Kullaniciya bildir | |
| 157 | | kraken | spark ile parcali fix | Manuel implement | Kullaniciya bildir | |
| 158 | | verifier | Manuel build + test | Sadece build kontrol | Kullaniciya bildir | |
| 159 | | architect | planner ile basit plan | Kullaniciya sor | - | |
| 160 | | build-error-resolver | Manuel hata oku + fix | Kullaniciya bildir | - | |
| 161 | |
| 162 | ## Hata Tipleri |
| 163 | |
| 164 | Her hata ayni agirlikta degil: |
| 165 | |
| 166 | | Hata Tipi | Sayac Etkisi | Ornek | |
| 167 | |-----------|:------------:|-------| |
| 168 | | API timeout | +1 | Anthropic API timeout | |
| 169 | | Rate limit | +0 (beklenir) | 429 Too Many Requests | |
| 170 | | Invalid output | +1 | Agent bos cikti verdi | |
| 171 | | Tool error | +0.5 | Bash komutu basarisiz | |
| 172 | | Logic error | +2 | Agent yanlis dosyayi duzenledi | |
| 173 | | Crash |