Skip to content

Add opt-in interactive-session idle auto-close (sessions.interactive_archive_after_hours)#182

Open
serxa wants to merge 2 commits into
mainfrom
serxa/interactive-idle-autoclose
Open

Add opt-in interactive-session idle auto-close (sessions.interactive_archive_after_hours)#182
serxa wants to merge 2 commits into
mainfrom
serxa/interactive-idle-autoclose

Conversation

@serxa

@serxa serxa commented Jul 17, 2026

Copy link
Copy Markdown
Member

Motivation — why you'd enable this

Nerve only cleaned up interactive sessions via a 30-day staleness backstop and the max_sessions overflow cap. Leaving idle chat sessions (web/telegram/…) open for days has real downsides that an opt-in short idle cutoff addresses:

  • Timely memory consolidation. A session's content is memorized when it closes. A chat left open for days isn't consolidated into long-term memory until it finally does — a short idle cutoff makes that happen promptly, so the assistant's memory reflects recent conversations sooner.
  • Context & cost hygiene. An idle session keeps its entire conversation context. Resuming a day-old thread reloads (and re-caches) all of it — well past the prompt-cache TTL, so it's a cache miss anyway. Closing idle sessions keeps active context focused instead of silently ballooning.
  • Fresh starts. On chat surfaces it's usually desirable that a message sent after a long gap begins a fresh conversation rather than silently resuming yesterday's stale thread.
  • No dangling questions. If the agent asked something via ask_user and the user never answered, that pending question lingers on the open session. Auto-closing the idle session expires it cleanly, so there's no phantom pending question (and nothing for the periodic expiry pass to try to inject into a session the user has clearly moved on from).
  • Session-list hygiene. Keeps the active list tidy without waiting a month for the 30-day backstop.

It's opt-in precisely because the opposite preference is also valid — users who want long-lived, always-resumable sessions simply leave it off (the default).

Why a separate knob (not just a smaller archive_after_days)

archive_after_days is global — it archives every session class (cron, persistent-cron which reuse a session across runs, and external/satellite sessions). Lowering it to close chats quickly would also prematurely archive those and break their continuity. Interactive and background sessions simply want different retention, so this is a distinct, interactive-scoped policy — hence the explicit name interactive_archive_after_hours rather than a finer-grained archive_after_days.

What it does

Adds sessions.interactive_archive_after_hours (default 0 = disabled). When set > 0, the periodic cleanup also archives interactive sessions (web/telegram/discord/slack/whatsapp) idle longer than that many hours — memorizing them and expiring any pending ask_user question. Cron and persistent sessions are excluded (they keep their own long rotation / the archive_after_days backstop).

  • SessionsConfig.interactive_archive_after_hours (+ from_dict).
  • SessionManager.run_cleanup(..., interactive_archive_after_hours=0) — the short cutoff, skipped entirely when 0.
  • SessionStore.get_stale_interactive_sessions and NotificationStore.expire_pending_questions_for_session (both additive).
  • Gateway cleanup loop passes the config through.

Default behaviour is unchanged

  • interactive_archive_after_hours defaults to 0, and the new cutoff block is skipped entirely when 0.
  • The cleanup cadence stays every 6 hours by default; it only tightens to hourly when the feature is enabled (finer resolution is only needed then).
  • New DB methods are additive; the new archived_interactive stat is 0 when disabled.

Testing

Added TestArchiveAndCleanup cases: disabled (default) leaves idle interactive sessions untouched, enabled archives them, and cron sessions are excluded even when enabled. Full suite: 1550 passed, 2 skipped.

serxa and others added 2 commits July 17, 2026 22:29
…r_hours)

Interactive chat sessions were only cleaned by the 30-day staleness backstop and the max_sessions cap. Leaving them open for days delays memory consolidation (a session is memorized on close), keeps stale context around to be reloaded/re-cached on resume, silently resumes day-old threads, and lets an unanswered ask_user question dangle. This adds an opt-in short idle cutoff to address that.

sessions.archive_after_hours (default 0 = disabled) archives interactive sessions (web/telegram/discord/slack/whatsapp) idle beyond it, memorizing them and expiring any pending question; cron/persistent sessions are excluded. Default behavior is unchanged: the block is skipped when 0, and the cleanup cadence stays 6h unless the feature is enabled (then hourly). Adds additive SessionStore.get_stale_interactive_sessions + NotificationStore.expire_pending_questions_for_session, and tests incl. a default-unchanged case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rity

The knob is scoped to interactive sources only (distinct from the global archive_after_days backstop that covers cron/persistent/external too), so the explicit name avoids it reading like a finer-grained archive_after_days.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@serxa serxa changed the title Add opt-in interactive-session idle auto-close (sessions.archive_after_hours) Add opt-in interactive-session idle auto-close (sessions.interactive_archive_after_hours) Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant