Bug
callOpenAICompat and callAnthropic make a single HTTP request per model call. If the upstream returns a transient 429 (rate-limit) or 5xx (server error), the call fails immediately and the model's response is recorded as an error in Phase 1. There's no retry mechanism.
Free-tier endpoints (NVIDIA NIM, OpenRouter :free models) are especially prone to transient 429s when load is high. A single blip kills an entire council session with no recovery.
Current behavior
const res = await postJSON(url, payload, headers);
if (res.status >= 400) return { success: false, content: `[ERROR ${res.status}: ...]`, ... };
One shot. No retry. No backoff.
Proposed fix
- Introduce
--max-retries N CLI flag (default 1, preserves current behavior — one attempt, one retry)
- Implement bounded retry with exponential backoff (2s, 4s, 8s...) for 429 and 5xx only
- After retries exhausted, fail fast with clear error message
- Connection-level errors (ETIMEDOUT, ECONNRESET) also retried once before failing
Usage after fix
node council.js run "<query>" --models "..." --chairman "..." --max-retries 3
Bug
callOpenAICompatandcallAnthropicmake a single HTTP request per model call. If the upstream returns a transient 429 (rate-limit) or 5xx (server error), the call fails immediately and the model's response is recorded as an error in Phase 1. There's no retry mechanism.Free-tier endpoints (NVIDIA NIM, OpenRouter
:freemodels) are especially prone to transient 429s when load is high. A single blip kills an entire council session with no recovery.Current behavior
One shot. No retry. No backoff.
Proposed fix
--max-retries NCLI flag (default1, preserves current behavior — one attempt, one retry)Usage after fix