Skip to content

Session (experimental): add thread support and clone/branch method #1075

@mattzcarey

Description

@mattzcarey

Summary

The current Session (experimental) API stores a single linear conversation history per agent instance. There's no built-in concept of threads (multiple keyed conversation streams within a single session) or branching (forking a conversation at a point to explore different paths).

Problem

Real-world agent applications frequently need:

  1. Multiple conversation threads per session — A user interacting with an agent may have several parallel conversations or topics. Today, achieving this requires spinning up entirely separate Agent (Durable Object) instances, each with its own Session. There's no way to store multiple keyed conversation threads within a single agent instance.

  2. Branching / forking conversations — When exploring different paths (e.g., "what if I asked this differently?", A/B testing prompts, or tree-of-thought reasoning), there's no way to clone a conversation's history at a given point and diverge. The user must manually duplicate and manage message arrays.

Proposed API

Threads

Allow Session to manage multiple named threads, each with its own message history and compaction settings:

// Create or get a thread by key
const thread = session.thread("thread-abc");
await thread.append(message);
const messages = await thread.getMessages();

// List all threads
const threads = await session.listThreads();

// Delete a thread
await session.deleteThread("thread-abc");

The default behavior (no thread key) could remain as-is for backwards compatibility — internally treated as a "default" thread.

Clone / Branch

Allow cloning a thread's history to create a new branch point:

// Branch from an existing thread at its current state
const branch = await session.cloneThread("thread-abc", "branch-xyz");

// Optionally branch from a specific message ID
const branch = await session.cloneThread("thread-abc", "branch-xyz", {
  fromMessageId: "msg-42"
});

This copies the message history up to the specified point into a new thread, enabling divergent conversation paths without affecting the original.

Current Workarounds

  • Create separate Agent instances per conversation (wasteful, no shared state)
  • Manually manage message arrays outside of Session (loses compaction, persistence, and provider abstraction)

Context

  • Session implementation: packages/agents/src/experimental/memory/session/
  • Provider interface: packages/agents/src/experimental/memory/session/provider.ts
  • SQLite provider: packages/agents/src/experimental/memory/session/providers/agent.ts
  • Storage table: cf_agents_session_messages (currently has no thread/namespace column)

Implementation Notes

  • The SessionProvider interface would need thread-aware methods (or a threadId parameter on existing methods)
  • The SQLite provider's cf_agents_session_messages table would need a thread_id column
  • Clone could be implemented as a bulk INSERT ... SELECT with a new thread_id
  • Compaction settings could be per-thread or inherited from session defaults

Metadata

Metadata

Assignees

No one assigned

    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