All tunable parameters in one validated place. Pass a config dict or load from YAML/env — never hardcode in prod.
| 97 | # ============================================================================= |
| 98 | |
| 99 | class ControlLayerConfig(BaseModel): |
| 100 | """ |
| 101 | All tunable parameters in one validated place. |
| 102 | Pass a config dict or load from YAML/env — never hardcode in prod. |
| 103 | """ |
| 104 | total_tokens: int = Field(800, ge=64, le=128_000) |
| 105 | max_attempts: int = Field(3, ge=1, le=10) |
| 106 | max_input_chars: int = Field(2000, ge=64, le=32_000) |
| 107 | timeout_seconds: float = Field(30.0, ge=0.01, le=300.0) |
| 108 | base_delay_ms: float = Field(50.0, ge=1.0, le=5_000.0) |
| 109 | max_delay_ms: float = Field(2000.0, ge=100.0, le=30_000.0) |
| 110 | jitter_ms: float = Field(25.0, ge=0.0, le=500.0) |
| 111 | # Circuit breaker |
| 112 | cb_failure_threshold: int = Field(5, ge=2, le=50) |
| 113 | cb_recovery_seconds: float = Field(30.0, ge=5.0, le=300.0) |
| 114 | # Audit |
| 115 | audit_log_path: str = Field("audit.jsonl") |
| 116 | model_name: str = Field("cl100k_base") # tiktoken encoding |
| 117 | |
| 118 | @field_validator("max_delay_ms") |
| 119 | @classmethod |
| 120 | def max_gt_base(cls, v, info): |
| 121 | base = info.data.get("base_delay_ms", 50.0) |
| 122 | if v < base: |
| 123 | raise ValueError("max_delay_ms must be >= base_delay_ms") |
| 124 | return v |
| 125 | |
| 126 | |
| 127 | class ResponseSchema(BaseModel): |
no outgoing calls