<!-- source: https://deepwiki.com/qhkm/zeptoclaw/10.3-provider-decorators -->

# Provider Decorators

- .claude/settings.json
- .gitignore
- src/agent/compaction.rs
- src/api/openai_types.rs
- src/api/routes/openai.rs
- src/cli/panel.rs
- src/error.rs
- src/kernel/provider.rs
- src/providers/error_classifier.rs
- src/providers/fallback.rs
- src/providers/mod.rs
- src/providers/plugin.rs
- src/providers/registry.rs
- src/providers/retry.rs
- src/providers/types.rs
- src/utils/sanitize.rs

This page documents ZeptoClaw's provider decorator system: `RetryProvider`, `FallbackProvider`, `RotationProvider`, and `QuotaProvider`. These decorators wrap base LLM providers to add automatic retry with exponential backoff, primary-to-secondary failover, multi-provider rotation, and per-provider cost/token quota enforcement.

For general LLM provider configuration, see [Provider Configuration](/qhkm/zeptoclaw/10.1-provider-configuration). For runtime model switching and provider selection, see [Runtime Model Switching](/qhkm/zeptoclaw/10.4-runtime-model-switching).

## Architecture Overview

The provider decorators use the decorator pattern to wrap base LLM providers. The standard stacking order is: base provider → `QuotaProvider` (per-provider) → `FallbackProvider` or `RotationProvider` → `RetryProvider` (outermost).

### Decorator Stack and Data Flow

```

```

**Diagram: Provider Decorator Stack with Quota Enforcement**

The system assembles this chain in `build_provider_chain` [src/kernel/provider.rs23-30](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/kernel/provider.rs#L23-L30) The `AgentLoop` holds a reference to the outermost provider, which delegates calls through the stack. Each decorator can intercept calls/errors and apply its policy. `QuotaProvider` wraps each individual provider to enforce per-provider limits [src/kernel/provider.rs157-160](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/kernel/provider.rs#L157-L160) while `FallbackProvider` [src/providers/fallback.rs154-168](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/fallback.rs#L154-L168) and `RetryProvider` [src/providers/retry.rs36-47](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/retry.rs#L36-L47) manage the reliability of the chain.

**Sources:** [src/kernel/provider.rs23-30](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/kernel/provider.rs#L23-L30) [src/kernel/provider.rs157-160](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/kernel/provider.rs#L157-L160) [src/providers/fallback.rs154-168](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/fallback.rs#L154-L168) [src/providers/retry.rs36-47](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/retry.rs#L36-L47)

## Retry Mechanism

### RetryProvider

The `RetryProvider` struct wraps any `LLMProvider` and adds automatic retry with exponential backoff. It intercepts errors from both `chat()` and `chat_stream()` methods [src/providers/retry.rs30-35](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/retry.rs#L30-L35)

**Sources:** [src/providers/retry.rs36-47](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/retry.rs#L36-L47) [src/providers/retry.rs71-79](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/retry.rs#L71-L79)

### Error Classification

The `is_retryable()` function determines which errors should trigger a retry. It handles structured `ProviderError` and classifies string-based errors using keywords [src/providers/retry.rs176-200](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/retry.rs#L176-L200)

**Retryable Errors:**

- ProviderError::RateLimit (HTTP 429) src/providers/retry.rs 191-192
- ProviderError::ServerError (HTTP 5xx) src/providers/retry.rs 193
- Explicit transient signals like "overloaded" or "timeout" src/providers/retry.rs 194-196

**Non-Retryable Errors:**

- Context window exceeded src/providers/retry.rs 131-141
- Authentication failures (401/403) src/providers/retry.rs 143-159
- Model not found (404) src/providers/retry.rs 161-168

**Sources:** [src/providers/retry.rs131-168](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/retry.rs#L131-L168) [src/providers/retry.rs176-200](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/retry.rs#L176-L200) [src/error.rs74-82](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/error.rs#L74-L82)

## Fallback and Rotation

### FallbackProvider

The `FallbackProvider` implements failover from a primary to a secondary provider using an internal `CircuitBreaker` [src/providers/fallback.rs60-69](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/fallback.rs#L60-L69)

The circuit trips after a `failure_threshold` of consecutive failures [src/providers/fallback.rs129-135](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/fallback.rs#L129-L135)

**Sources:** [src/providers/fallback.rs40-47](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/fallback.rs#L40-L47) [src/providers/fallback.rs154-168](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/fallback.rs#L154-L168) [src/providers/fallback.rs129-135](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/fallback.rs#L129-L135)

### RotationProvider

The `RotationProvider` manages N providers with health-aware selection [src/providers/rotation.rs149-158](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/rotation.rs#L149-L158)

**Sources:** [src/providers/rotation.rs44-58](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/rotation.rs#L44-L58) [src/providers/rotation.rs157-164](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/rotation.rs#L157-L164)

## QuotaProvider

### Overview

The `QuotaProvider` enforces per-provider usage limits. It checks the `QuotaStore` before allowing a request to proceed [src/providers/quota.rs170-174](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/quota.rs#L170-L174)

**Key Features:**

- QuotaPeriod : Reset cadence ( Monthly or Daily ) src/providers/quota.rs 42-48
- QuotaAction : Action on exceed ( Reject , Fallback , or Warn ) src/providers/quota.rs 53-61
- QuotaStore : Persistent storage in ~/.zeptoclaw/quota/usage.json src/providers/quota.rs 120-140

### Quota Enforcement Logic

```

```

**Diagram: Quota Enforcement Logic**

A `QuotaCheckResult::Warning` is issued when usage reaches 80% of the limit [src/providers/quota.rs128](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/quota.rs#L128-L128) If the action is `Fallback`, the provider returns an error that triggers the `FallbackProvider` or `RotationProvider` to select the next available backend.

**Sources:** [src/providers/quota.rs53-61](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/quota.rs#L53-L61) [src/providers/quota.rs105-113](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/quota.rs#L105-L113) [src/providers/quota.rs170-210](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/quota.rs#L170-L210)

## Implementation Details

### Decorator Chain Assembly

The assembly logic in `src/kernel/provider.rs` ensures that decorators are applied in the correct order to provide a robust execution environment:

1. Base Provider : Maps the backend (e.g., "anthropic", "openai") to a concrete struct like ClaudeProvider src/kernel/provider.rs 43-53
2. QuotaProvider : Wrapped around each base provider during the iteration of resolve_runtime_providers to track its specific usage src/kernel/provider.rs 157-160
3. Fallback/Rotation : Assembled if multiple candidates exist or if fallback is enabled in config src/kernel/provider.rs 184-210
4. RetryProvider : Applied as the final outer wrapper to the entire resolved chain src/kernel/provider.rs 28

### Plugin Provider

For non-native integrations, the `ProviderPlugin` acts as a base provider that communicates via JSON-RPC 2.0 over stdin/stdout [src/providers/plugin.rs3-5](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/plugin.rs#L3-L5) It is treated as any other base provider in the assembly chain.

**Sources:** [src/kernel/provider.rs23-30](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/kernel/provider.rs#L23-L30) [src/kernel/provider.rs43-53](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/kernel/provider.rs#L43-L53) [src/kernel/provider.rs157-160](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/kernel/provider.rs#L157-L160) [src/kernel/provider.rs184-210](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/kernel/provider.rs#L184-L210) [src/providers/plugin.rs3-5](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/plugin.rs#L3-L5)
