Session Consumer Claims: Operator Guide
Session consumer claims protect sessions from premature pruning when a registered plugin still owes work on them. This page covers configuration, monitoring, and operational behaviour.Configuration
Consumer-claim settings live undersession.storage.consumerClaims in
openclaw.json:
All keys are optional; omitting the
consumerClaims block uses the defaults above.
Backend requirements
Operational behaviour
Reconciler sweep + lease reaper
The gateway runs a single timer onsweepCadenceMs that performs two operations per
tick:
- Reconciler sweep — for each registered consumer, queries sessions for the
consumer’s agent updated past the consumer’s watermark, derives the lane from
session_key, and materializes claim rows (idempotent on the(session_id, consumer_id, effect_kind, schema_version)key). The watermark advances tomax(updated_at)of the candidates scanned — not only the materialized ones — so idle lanes do not re-scan the same rows every tick. - Lease reaper — resets expired leases. Claims with
attempt_countundermaxAttemptsreturn topendingfor retry; claims at or over the budget transition todlqand emit adlq_terminaldiagnostic (once, at the transition).
enabled = 0) still has its owed work
preserved: the sweep keeps materializing claims for it, and the prune gate pins
those claims until either the consumer is re-enabled or the 30-day backstop
releases them.
Prune gating
Session pruning is obligation-gated, not purely age-based. Before deleting a session past the age cutoff, the prune gate checks all consumer watermarks — including disabled ones — so a disabled consumer’s backlog is not silently dropped before the backstop fires.- Floor (not prunable): any consumer has a live claim, a pending/claimed claim
within the progress window (
progressWindowMs, default 24h), a pending/claimed claim within the retention backstop (maxRetentionBackstopMs, default 30d) — even for a disabled consumer — or a watermark that post-dates the session’s last activity. - Ceiling (released for prune): all claims are
processedordlq, OR the session exceedsmaxRetentionBackstopMs. The progress window is a soft liveness signal (consumer is lagging); the backstop is the hard release. Past the progress window but within the backstop, a session is still pinned; only past the backstop is it released (and abackstop_releasedorskipped_backlogdiagnostic is emitted).
Diagnostic events
The system emits diagnostic events:dlq_terminal— a claim reachedmaxAttemptsand was dead-lettered by the lease reaper. Emitted once at the DLQ transition (not at every prune sweep), so a surviving DLQ claim does not produce repeated events.backstop_released— a session exceeded the 30-day backstop and was released for pruning despite a non-terminal (pending/claimed) claim. Emitted at prune-gate evaluation time for enabled consumers.skipped_backlog— same release condition asbackstop_released, but for a consumer whose watermark is disabled. Signals that re-enabling the consumer would have resumed from this watermark, but the backstop released the session first.
onDiagnosticEvent or inspect via the diagnostics-otel extension
if configured.
Operational observability
Gateway RPC: sessions.claims.status
The gateway exposes sessions.claims.status as a server method. It returns:
- consumers — per-consumer per-lane status: consumer ID, lane, effect kind,
enabled flag, and counts by claim status (
pending,claimed,processing,dlq,processed). - stalledLeases — claims with expired leases still in
claimed/processingstate, grouped by session. - lastSweepTs — timestamp of the last reconciler sweep tick.
- recentEvents — last N diagnostic events from the in-memory ring buffer.
getClaimsForSession), so sessions with
only terminal claims are not returned.
CLI: wednesdayai sessions claims status
docs/cli/sessions.md for full CLI reference.
Learning-core consumer
Theextensions/learning-core plugin declares sessionConsumers in its
manifest and processes the session.end effect via the onSessionWorkAvailable
hook. It reads transcripts from the durable conversation store (not volatile
in-memory event messages), then calls claimSessionWork() → processAgentEndFromClaim()
→ ackSessionWork().
Reconciliation
The gateway sweep now reconciles watermarks against the active plugin registry on every tick. Watermarks belonging to unregistered consumers are purged (viapurgeConsumer) so prune-gate is not pinned indefinitely by a removed plugin’s
cursor. The purge gate uses manifest-declared consumer IDs (not load-filtered
active consumers) to avoid purging watermarks when a plugin transiently fails to
load.
Known limitations
setEnabled(false)for registered-but-disabled consumers is a placeholder until a disabled-state signal is carried in the registry.dlq_terminalandbackstop_releaseddiagnostics are emitted through the global event system, not the session-consumer ring buffer — they are not surfaced bysessions.claims.status.consumerClaims.leaseMsandretryBaseMsare resolved from config but not yet wired through to the claim store (uses hardcoded defaults).