Skip to content

[Proposal] Intelligent Session Auto-Titling: lazy generation, cheap models, topic-aware renames #99583

Description

@apoapostolov

Problem

Sessions start as untitled (/name shows a suggestion only on demand). Users must manually run /name to set a title. Multi-topic sessions keep their original title even after shifting topics entirely. Meanwhile, an LLM slug generator already exists in the codebase (llm-slug-generator) for memory filenames — it just isnt wired into session titling.

Related: #77165 (basic auto-title request), #94529 (auto-derive in sidebar), #81781 (improve derived titles beyond first message)

Proposal: Three-Phase Auto-Titling

Phase 1 — Lazy Initial Title (after N messages, not immediately)

Dont title on session creation or first message. Wait until N messages have passed (configurable, default 4-6). This avoids titles like "hi" or "help" from one-word openers, and gives enough context for a meaningful slug.

sessions:
  autoTitle:
    enabled: true
    triggerAfterMessages: 5       # wait for 5th message before first title gen
    model: "openai/gpt-4.1-mini"  # cheap model override, falls back to default

Phase 2 — Cheap Model for Title Generation

Title generation does NOT need a frontier model. A cheap, fast model works perfectly:

Model Cost per gen Latency
gpt-4.1-mini ~$0.00015 ~300ms
claude-haiku-4.5 ~$0.00030 ~400ms
deepseek-v3 ~$0.00005 ~500ms
Provider default varies varies

Config should allow a dedicated titleModel override separate from the session model, defaulting to the cheapest available provider model. Title prompts are tiny (~200 tokens input, ~10 tokens output) so cost is negligible even with frontier models, but the principle of using cheap models for cheap tasks matters.

Phase 3 — Periodic Topic-Aware Re-Titling

Sessions drift. A conversation that starts as "skill audit" might shift to "LinkedIn content strategy" after 30 messages. The title should track the active topic.

sessions:
  autoTitle:
    reTitleInterval: 20           # re-evaluate title every N messages
    reTitleWindow: 15             # use last N messages for context (sliding window)
    reTitleMinChange: true        # only rename if topic meaningfully changed

Implementation:

  • Every reTitleInterval messages, feed the last reTitleWindow messages to the title model
  • Compare generated title against current title (simple string similarity or LLM-based "did the topic change?")
  • Only apply rename if the new title is meaningfully different (avoid flickering)
  • Titles should be 2-4 word lowercase slugs: "skill-audit-cleanup", "linkedin-automation", "session-naming-proposal"

Reuse Existing Infrastructure

The llm-slug-generator already exists in dist/ and handles:

  • Short 1-2 word lowercase hyphenated slugs
  • LLM-based generation from conversation content
  • Memory filename integration

Wire this same generator (or a configurable variant) into session title mutation on the trigger conditions above.

UX Behavior

  • Title appears in sidebar, /sessions list, Control UI tabs, and session history
  • /name with no args shows current title + when it was last auto-generated
  • Manual /name <title> overrides and locks the title (no more auto-renames for that session)
  • /name --auto re-enables auto-titling for a manually-named session

Configuration Surface

sessions:
  autoTitle:
    enabled: false                # default off, opt-in
    triggerAfterMessages: 5       # messages before first title gen (min 3)
    model: null                   # null = cheapest available provider model
    reTitle:
      enabled: true               # periodic re-titling
      interval: 20                # messages between re-evaluations
      window: 15                  # last N messages used as context
      minDistance: 0.4            # string similarity threshold (0-1) to skip no-op renames

Edge Cases

  • Single-message sessions: never titled (below triggerAfterMessages)
  • Very short sessions: titled at message N, then session ends — perfectly fine
  • Rapid-fire messages: debounce title generation; dont fire on every message in a burst
  • Subagent sessions: auto-title based on task description (available immediately, no N-message wait needed)
  • Channel-bound sessions: may want different auto-title behavior (group chats vs DMs)

Precedents

  • ChatGPT: auto-titles after ~2-3 exchanges
  • Claude: auto-titles immediately from first prompt
  • Cursor: auto-titles chat sessions
  • All of them occasionally produce dumb titles from insufficient context — the triggerAfterMessages approach directly addresses this known failure mode

Scope

This is a gateway-side feature: the model call, title storage, and trigger logic all live in the gateway. The Control UI and TUI already consume and display session labels — no UI changes required beyond the existing #94529 and #89922 work.

Migration

Backward-compatible. Default is enabled: false. Existing /name behavior unchanged. Sessions with manually-set titles are not auto-renamed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low-priority cleanup, docs, polish, ergonomics, or speculative work.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🌊 off-meta tidepoolIssue quality rating does not apply to this item.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions