#5141·PraisonAI

CLI: auto session titles are built but not wired into the default session store — `session list` shows opaque IDs instead of generated titles

Author: MervinPraisonCreated Sep 18, 2026Updated Sep 18, 2026
Labelsbugclaude

Summary

The SDK already ships a session-title generator (generate_title_async / generate_title) and an auto_title() method, but they are only reachable on HierarchicalSessionStore. The DefaultSessionStore / ProjectSessionStore that the CLI actually uses for run/chat/code never call it, so a session's title is only ever an explicit --title, the agent name, or the session ID. The result is that praisonai session list (and resume pickers) show opaque identifiers rather than meaningful, human-readable titles derived from the first exchange — even though the capability to generate them is already implemented.

This is the same "built but uncomposed" class as #3734/#2903: the feature exists; it just isn't wired into the default path.

Current behaviour

  • src/praisonai-agents/praisonaiagents/session/title.py implements generate_title(...) and generate_title_async(...) (module __all__ = ["generate_title", "generate_title_async"]).
  • src/praisonai-agents/praisonaiagents/session/hierarchy.py (~line 599) implements async def auto_title(self, session_id) — "Generate and set title automatically from first exchange" — but this lives only on HierarchicalSessionStore.
  • DefaultSessionStore (session/store.py) has rename_session() (~line 1625, sets metadata["title"]) but no automatic title generation; _session_title() (~line 1886) falls back to the explicit metadata title, else the session id / agent name.
  • A repo-wide search shows generate_title/auto_title are not invoked from the CLI session path (src/praisonai-code/praisonai_code/cli/session/ and cli/state/project_sessions.py), and DefaultSessionStore never calls them. So the CLI never auto-titles a session.

Net effect: after several run --continue/chat sessions, session list is a wall of IDs/agent-names, making it hard to pick the right session to resume — the core session-continuity UX the CLI is otherwise strong at.

Desired behaviour

After the first user↔assistant exchange in a CLI session (when no explicit --title was given), the CLI generates a short title via the existing generate_title_async on a cheap/non-blocking path and persists it to metadata["title"], so session list, resume pickers, and session show display meaningful names. Failure to generate must degrade silently to the current fallback (never block or error the run).

Layer placement

  • Primary layer: wrapper (CLI). The trigger and persistence belong in the CLI session flow — src/praisonai-code/praisonai_code/cli/state/project_sessions.py / cli/session/ — where the first-exchange boundary and the store are already handled.
  • Why not core: core already provides the generator (session/title.py) and a reference auto_title() (session/hierarchy.py); no new runtime capability is required. Only a small optional core touch (below) would make it store-agnostic.
  • Why not wrapper: it is wrapper — listed for completeness.
  • Why not tools: not an agent-callable integration.
  • Why not plugins: not a lifecycle guardrail/policy; it reuses an existing helper rather than adding a hook plugin.
  • Secondary touch (optional): core — optionally lift auto_title() from HierarchicalSessionStore onto a shared base or expose a tiny post-first-turn hook on DefaultSessionStore, so any store benefits without duplicating the CLI trigger. Keep it minimal and backward-compatible.
  • 3-way surface (CLI + YAML + Python): no — this is a CLI session-management UX behaviour; the underlying generate_title_async remains available to Python callers as today.

Proposed approach

  1. In the CLI session persistence path (project_sessions.py / cli/session/), after the first assistant turn and when metadata["title"] is unset and no --title was passed, call generate_title_async(user_msg, assistant_msg) on a non-blocking path and rename_session()/persist the result.
  2. Reuse HierarchicalSessionStore.auto_title as the reference implementation; guard with the same best-effort try/except (silent fallback on failure).
  3. Optionally (secondary) move auto_title to a shared base so DefaultSessionStore gains it directly.

Resolution sketch

  • cli/state/project_sessions.py: add a first-exchange hook that invokes the existing generator and persists metadata["title"].
  • Reuse praisonaiagents.session.title.generate_title_async; do not reimplement.
  • Test: a fresh CLI session with no --title acquires a non-ID metadata["title"] after the first exchange, and generation failure leaves the existing fallback untouched.

Severity

Low-medium. No correctness impact, but a clear daily-use UX win for session continuity (a strength of the CLI): it makes session list/resume legible by composing an already-shipped capability, at negligible cost.

Validation

  • src/praisonai-agents/praisonaiagents/session/title.pygenerate_title / generate_title_async (implemented, exported).
  • src/praisonai-agents/praisonaiagents/session/hierarchy.py (~L599) — auto_title() exists but only on HierarchicalSessionStore.
  • src/praisonai-agents/praisonaiagents/session/store.pyDefaultSessionStore.rename_session (~L1625) and _session_title (~L1886) show manual/fallback titling only; no auto-generation.
  • src/praisonai-code/praisonai_code/cli/state/project_sessions.py and cli/session/ — no call to generate_title/auto_title, confirming the CLI never triggers it.
  • Distinct from #3133 (which concerns store-identity coherence, not title generation).