Skip to content

Channel /new wipes ALL agent sessions, not just the channel-derived one #4868

Description

@neo-wanderer

Summary

The channel-side /new command (Telegram, Discord, Slack, etc.) currently calls the kernel's reset_session(agent_id), which deletes every session for that agent — the default session plus every per-channel session and any cron/trigger-spawned ones — and creates one fresh session in its place.

For users who run an agent across multiple surfaces (e.g., dashboard + Telegram + Discord on the same hand), typing /new in any one channel silently destroys the in-flight history on all the others.

Repro

  1. Same agent reachable from the dashboard and from Telegram.
  2. Have an active session on each (different SessionIds — one is SessionId::for_channel(agent,"telegram:<chat>"), the other is the default).
  3. Send /new in Telegram.
  4. Observe: dashboard session row is gone (GET /api/sessions/<dashboard-sid> → 404).

Code path

  • crates/librefang-channels/src/bridge.rs:4730"new" command handler calls handle.reset_session(aid) with no scope.
  • crates/librefang-kernel/src/kernel/session_ops.rs:168reset_session(agent_id):
    • line 176: get_agent_session_ids(agent_id) — iterates all sessions
    • line 199-202: delete_agent_sessions(agent_id) — transactional delete of every session row for that agent
    • The comment at line 173-174 documents the agent-wide intent: "Auto-save session summaries for ALL sessions (default + per-channel) before clearing, so no channel's conversation history is silently lost."

Summaries are saved to memory before the delete, but the full transcripts are unrecoverable.

Expected

/new invoked from a channel should reset only that channel's SessionId::for_channel(agent, "<channel>:<chat>"). Other channels and the dashboard session should be untouched.

The agent-wide reset is still useful as a separate explicit operation (e.g., dashboard "Reset agent" button, POST /api/agents/{id}/reset), but the channel /new user-mental-model is "start a fresh chat here", not "wipe everything across every surface."

Proposed change

  1. Add an optional scope to the kernel API:

    pub fn reset_session(&self, agent_id: AgentId, scope: ResetScope) -> KernelResult<()>
    // where
    pub enum ResetScope { Agent, Session(SessionId) }

    ResetScope::Session(sid) saves a summary for that one session, deletes that one row, creates a fresh per-channel session keyed the same way (so the channel's next message lands on the new one), and leaves all other sessions intact.

  2. In bridge.rs:4730, derive the channel-scoped SessionId the same way inbound channel messages do (SessionId::for_channel(agent, "<channel>:<chat>")) and pass ResetScope::Session(sid) to the kernel.

  3. Keep the agent-wide variant for the dashboard / explicit "reset agent" path. /reboot and compact likely want the same scoping treatment — currently they share the agent-wide footgun.

Backward compatibility

The HTTP route POST /api/agents/{id}/reset and the dashboard reset button can keep agent-wide semantics by passing ResetScope::Agent. Only the channel command handler changes user-visible behavior, which is the bug.

Notes

  • Confirmed on main (commit visible in librefang/crates/librefang-kernel/src/kernel/session_ops.rs:168).
  • Workaround for now: don't use /new in a channel if you have other live sessions on the same agent. Pull session summaries from the agent's memory store if you need to reconstruct what was deleted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/channelsMessaging channel adaptersarea/kernelCore kernel (scheduling, RBAC, workflows)has-prA pull request has been linked to this issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions