SDK Resilience
This page covers the SDK resilience layer (tappass.resilience): how the SDK degrades when the TapPass server is unreachable, the three fail modes, the circuit breaker, and the local audit buffer.
ResiliencePolicy
Section titled “ResiliencePolicy”from tappass.resilience import ResiliencePolicy, FailMode
policy = ResiliencePolicy( mode=FailMode.FAIL_OPEN_CACHED, cache_ttl_seconds=300, max_offline_requests=100, local_audit_path=".tappass_audit_buffer.jsonl", circuit_failure_threshold=3, circuit_recovery_timeout=30.0,)| Parameter | Type | Default | Env var | Description |
|---|---|---|---|---|
mode |
FailMode |
FAIL_CLOSED |
TAPPASS_FAIL_MODE |
Degradation mode (fail_closed, fail_open_cached, fail_open_logged) |
cache_ttl_seconds |
int |
300 | TAPPASS_CACHE_TTL |
How long cached responses stay valid |
max_offline_requests |
int |
100 | TAPPASS_MAX_OFFLINE_REQUESTS |
Hard cap on degraded-mode calls (0 = unlimited) |
local_audit_path |
str |
.tappass_audit_buffer.jsonl |
TAPPASS_LOCAL_AUDIT_PATH |
Path for the local audit buffer file |
circuit_failure_threshold |
int |
3 | TAPPASS_CIRCUIT_FAILURE_THRESHOLD |
Consecutive failures before the circuit opens |
circuit_recovery_timeout |
float |
30.0 | TAPPASS_CIRCUIT_RECOVERY_TIMEOUT |
Seconds before OPEN → HALF_OPEN |
alert_on_degradation |
bool |
True |
— | Log a WARNING when entering degraded mode |
Load everything from the environment in one call:
policy = ResiliencePolicy.from_env()An invalid TAPPASS_FAIL_MODE value logs a warning and falls back to fail_closed.
Fail modes
Section titled “Fail modes”| Mode | Behavior | Use case |
|---|---|---|
FAIL_CLOSED |
Caller raises TapPassConnectionError. Agent stops. |
Regulated environments where ungoverned operation is unacceptable. Default. |
FAIL_OPEN_CACHED |
Serves the last-known-good cached response; audit entries queued locally. | Production agents that must stay available through short outages. |
FAIL_OPEN_LOGGED |
Continues ungoverned; every call logged locally with classification DEGRADED. |
Development and low-risk agents. |
Degraded responses
Section titled “Degraded responses”Responses served in a fail-open mode carry:
response["tappass"]["degraded"] = Trueresponse["tappass"]["degraded_reason"] # e.g. "TapPass unreachable — ConnectError (serving from cache)"response["tappass"]["classification"] = "DEGRADED" # synthetic responses (no cache)Cached responses additionally include tappass.cache_age_seconds.
ResilienceManager
Section titled “ResilienceManager”Orchestrates the circuit breaker, cache, and audit buffer:
from tappass.resilience import ResilienceManager
manager = ResilienceManager(ResiliencePolicy.from_env())
if manager.should_attempt_request(): try: data = post_to_tappass(...) # your HTTP call manager.record_success() manager.cache_response(cache_key, data, model="gpt-4o-mini") except ConnectionError as exc: degraded = manager.handle_connection_failure( messages, model="gpt-4o-mini", cache_key=cache_key, original_error=exc, ) if degraded is None: # fail_closed (or offline cap hit) raise data = degradedKey members:
| Member | Description |
|---|---|
is_degraded |
True while the circuit is open |
offline_request_count |
Calls served since the circuit opened |
degraded_duration_seconds |
Time since the circuit opened (None when closed) |
record_success() / record_failure() |
Drive the circuit breaker |
handle_connection_failure(messages, model, cache_key, original_error) |
Returns a degraded response dict for fail-open modes, None for fail-closed |
flush_audit_buffer(client, url) |
Drain buffered audit entries to {url}/audit/ingest; returns count flushed |
status() |
Diagnostic dict (mode, circuit state, cache size, buffered entries, …) |
Circuit breaker
Section titled “Circuit breaker”TapPassCircuitBreaker(failure_threshold=3, recovery_timeout=30.0). States:
CLOSED ──── requests flow normally │ N consecutive failures (default 3) ▼OPEN ────── fallback, no connection attempts │ recovery timeout expires (default 30s) ▼HALF_OPEN ── probe one request → success: CLOSED / failure: OPENPublic API: state (CircuitState), is_open, consecutive_failures, record_success(), record_failure(), should_attempt(), reset(), to_dict(). Thread-safe.
ResponseCache
Section titled “ResponseCache”Thread-safe last-known-good cache. Keyed by caller-supplied key (the SDK helper _make_cache_key keys by a hash of the model and last user message; small bounded LRU-style cache). Served only in FAIL_OPEN_CACHED mode within TTL. This is a safety net, not a performance cache.
LocalAuditBuffer
Section titled “LocalAuditBuffer”Spill buffer for AuditEvents while the server is down. Serializes to JSONL on disk; drain() returns the events and deletes the file for replay after recovery. has_pending() reports unflushed in-memory events or a non-empty buffer file. The buffer is plaintext JSONL — protect local_audit_path with filesystem permissions.
Next steps
Section titled “Next steps”- Agent client — the chat path this layer protects
- SDK environment variables — all resilience env vars in one table
- Troubleshooting — diagnosing connectivity problems