-
Notifications
You must be signed in to change notification settings - Fork 447
Description
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:
-
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. -
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
SessionProviderinterface would need thread-aware methods (or athreadIdparameter on existing methods) - The SQLite provider's
cf_agents_session_messagestable would need athread_idcolumn - Clone could be implemented as a bulk
INSERT ... SELECTwith a newthread_id - Compaction settings could be per-thread or inherited from session defaults