Skip to main content
The gateway detects when the host was frozen (laptop sleep, VM pause / snapshot / live-migrate) and drives recovery on thaw — restart channel sockets when idle, refresh presence, and coalesce missed cron fires.

Quick Start

1

Default — sensible thresholds

The gateway compares wall-clock and monotonic time on every run-loop tick. A wall-clock jump that runs far ahead of monotonic elapsed time is a freeze — recovery fires on the next tick after resume.
2

Tuned thresholds — slower loop, higher tolerance

Match tick_interval_s to your run-loop cadence and set gap_threshold_s above your worst legitimate stall.

How It Works

On Linux CLOCK_MONOTONIC does not advance while the host is suspended, so wall-clock running far ahead of monotonic is a positive signature of a freeze the process could not otherwise observe. Detection rule — a gap is reported only when both are true: The second condition rejects the NTP / manual-clock-step false positive: if monotonic advanced a full tick or more, the process was alive and no recovery fires.

Choosing between Freeze-Thaw and Scale-to-Zero

Freeze-Thaw handles the involuntary suspend; Scale-to-Zero handles the intentional one.

Configuration Options

WallClockGapThawPolicy constructor

ThawDecision — result of every observe() call

@dataclass(frozen=True) — assigning to a field raises.

ThawPolicyProtocol — custom detectors

@runtime_checkable protocol with a single method. Implement your own detector and pass it wherever a ThawPolicyProtocol is accepted — isinstance(policy, ThawPolicyProtocol) succeeds without inheritance.

Imports

These names export from praisonaiagents.gateway. Top-level praisonaiagents does not re-export them. BotOS itself imports from praisonai.bots.

Common Patterns

Disable in tests

Use enabled=False to keep the wiring in place while turning detection off — no code removal.

Custom detector implementing ThawPolicyProtocol

Custom detectors must still ignore NTP steps — reuse the built-in guard or replicate it.

Log the observed freeze window

Read ThawDecision.gap_seconds in a hook to record how long the host was suspended.

Best Practices

If the run-loop ticks every 30s, set tick_interval_s=30.0. Otherwise a legitimate stall longer than the configured interval can look like a freeze, and the “monotonic stalled” guard loses its meaning.
GC pauses, cold starts, and NTP jitter shouldn’t trip the detector. 60s is a safe floor — raise it if your environment has known long stalls, lower it only when you need faster freeze detection and your loop is reliably quick.
LoopWatchdog uses time.monotonic() and is deliberately blind to frozen hosts — monotonic doesn’t advance during a suspend, so the watchdog never notices. Freeze-Thaw is a separate, complementary policy that watches wall-vs-monotonic divergence.
A forward wall-clock correction (NTP step / manual set) leaves monotonic advancing in step with the loop — proof the process kept running. The built-in detector already ignores this, so it never churns healthy sockets. Custom detectors must do the same or they’ll restart transports needlessly.

Scale to Zero

Intentional-suspend counterpart — quiesce the gateway when idle and wake on the next message.

Loop Watchdog

Event-loop liveness watchdog — deliberately blind to host suspends.

Graceful Drain

Drain in-flight turns cleanly on shutdown before the process exits.

Liveness

Application-level connection liveness for detecting silently-dead sockets.