This document defines the operational policy for retries and failure handling in the stateless Core + Platform architecture.
- In scope: Platform->Core HTTP transport behavior (
orchestrator/core_client.py) and Platform persistence contention handling in SQLite-backed session/finding/learning flows. - Out of scope: provider-side LLM determinism guarantees.
CoreClient applies bounded retry with linear backoff:
retry_attempts(default:2, minimum:1)retry_backoff_seconds(default:0.25, minimum:0.0)- retry delay =
retry_backoff_seconds * attempt
- HTTP
5xxresponses - network/transport exceptions (
URLError,TimeoutError,socket.timeout)
- HTTP
4xxresponses (immediately mapped toCoreClientHTTPError) - invalid JSON payloads (mapped to
CoreClientError)
CoreClientHTTPError(status_code, detail)for HTTP failuresCoreClientErrorfor transport/decode failures after retry exhaustion
Finding persistence applies bounded retries for transient SQLite lock failures:
- attempts:
3 - base backoff:
0.02seconds - delay =
0.02 * attempt
Only sqlite3.OperationalError containing locked is retried; other DB errors fail fast.
Core is stateless at API boundary. Platform transport retries may replay a request when failures occur before a successful response is observed.
Operationally this is treated as at-least-once transport semantics.
Session actions (accept/reject/advance/discuss) mutate workflow state and are not universally idempotent at UX level.
Therefore:
- Automatic retries are limited to transport/persistence layers where bounded and explicit.
- Clients should avoid blind re-submission of user actions after unknown completion unless they first reconcile session state.
- API consumers should prefer reading current session/finding state before replaying a mutating action.
- Keep retry bounds low to avoid duplicate work amplification.
- Log retry exhaustion and lock-contention events with request/session context.
- Alert on elevated retry-exhaustion rates (often indicates upstream outage or DB pressure).