Skip to content

feat: per-thread session isolation via --session-id / --resume #144

@bchoor

Description

@bchoor

Problem

All messages across every channel, topic, and thread route to the same agent and share a single Claude session via -c (continue last). A Telegram topic and a Discord thread hitting the same agent bleed context into each other, and there's no way to have isolated conversations per thread without defining a separate agent per context — which doesn't scale.

Related: #125 #81 #72

Proposed Solution

Use --session-id (Claude) and resume <session-id> (Codex) to track multiple independent sessions per agent, keyed by (agent_id, thread_id) stored in the existing SQLite DB.

Key insight: Claude's --session-id <uuid> lets you pre-assign a UUID before the call — so you own the session ID from the start, no stdout parsing needed. -r <uuid> resumes it on subsequent messages.

New table:

CREATE TABLE thread_sessions (
    agent_id   TEXT NOT NULL,
    thread_id  TEXT NOT NULL,  -- e.g. "telegram:652", "discord:thread:abc"
    session_id TEXT NOT NULL,  -- UUID
    provider   TEXT NOT NULL,
    created_at INTEGER NOT NULL,
    updated_at INTEGER NOT NULL,
    PRIMARY KEY (agent_id, thread_id)
);

Invocation changes:

  • First message in a thread → generate UUID, claude --session-id <uuid> -p "msg", persist it
  • Subsequent messages → claude -r <uuid> -p "msg"
  • Codex → codex exec resume <uuid> for existing threads, plain codex exec for new (parse session ID from JSONL output on first run)
  • Reset → delete the row, next message starts fresh
  • Fork → claude -r <uuid> --fork-session -p "msg" (free bonus)

Result

telegram topic 652  →  session UUID-A  (isolated)
telegram topic 29   →  session UUID-B  (isolated)
discord thread xyz  →  session UUID-C  (isolated)

Same agent folder. No config changes needed. Survives restarts. New threads get fresh sessions automatically.

Scope

~200 lines across 4 files:

  • src/lib/db.ts — new table + getThreadSession / saveThreadSession
  • src/lib/invoke.ts — replace -c with --session-id / -r <id> logic
  • src/queue-processor.ts — pass threadId into invokeAgent
  • src/channels/telegram-client.ts + discord-client.ts — set threadId from message_thread_id / channelId

Note: OpenCode has no --session-id equivalent yet — falls back to current -c behavior for that provider.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions