Skip to content

docs: add multi-chat sessions proposal#184

Open
sandy081 wants to merge 4 commits into
mainfrom
sandy081/multi-chat-proposal
Open

docs: add multi-chat sessions proposal#184
sandy081 wants to merge 4 commits into
mainfrom
sandy081/multi-chat-proposal

Conversation

@sandy081
Copy link
Copy Markdown
Member

@sandy081 sandy081 commented Jun 2, 2026

Summary

Adds a draft design proposal (docs/proposals/multi-chat-sessions.md) for representing multiple chats within a single AHP session. This is a discussion document, not a protocol change — no types/ or generated code is touched.

The idea

Today an AHP session is exactly one linear chat (SessionState.turns + a single activeTurn). The proposal promotes the session to a thin container of shared context + a catalog of chats, introducing a new ahp-chat: channel that holds the per-chat conversation state a session has today:

ahp-root://
  └─ ahp-session:/<sid>      ← shared context + catalog of chats
       ├─ ahp-chat:/<cid-1>  ← turns + activeTurn
       ├─ ahp-chat:/<cid-2>
       └─ ...

This enables: shared context, branching/forking, concurrent turns, UI grouping, and task decomposition.

Resolved design decisions captured

  • Chat URI = opaque ahp-chat:/<cid>
  • Catalog lives as SessionSummary.chats (mirrors changesets); no listChats, no "primary chat" — chats are equal peers
  • Session aggregates (status/activity/modifiedAt) derived across chats
  • Breaking change: remove session-level turns/activeTurn (turns live only on the chat channel)
  • Config: chat-level model/agent/config overrides, inheriting from the session
  • activeClient stays session-level / shared
  • Chat forks are intra-session only
  • fetchTurns/completions target the chat channel
  • Versioning: handled by a SemVer bump (0.3.00.4.0), with an explicit rebuttal of the "capabilities first" convention (the change is removal-shaped + pre-1.0)

Also included

  • Validation against Claude Agent Teams (mapping + gaps)
  • Alternatives considered (single-tree, multi-session+context, tool-result subagents, additive capability advertisement)

Notes for reviewers

  • Docs-only; per AGENTS.md no CHANGELOG entry is required.
  • The proposal is intentionally placed under docs/proposals/ and not wired into the VitePress sidebar — it's a working design doc, not published spec.

Draft design proposal for representing multiple chats within a single
AHP session: a session becomes a thin container of shared context plus a
catalog of chats, with a new ahp-chat: channel holding per-chat turns.

Captures the resolved design questions (chat URI shape, catalog on the
session summary, session-level aggregates, removal of session-level
turns/activeTurn, chat/session config inheritance, session-level
activeClient, intra-session chat forks, chat-targeted fetchTurns/
completions, and the SemVer version story) along with validation against
Claude Agent Teams and the alternatives considered.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@sandy081 sandy081 self-assigned this Jun 2, 2026
@sandy081 sandy081 requested a review from connor4312 June 2, 2026 22:07
@connor4312
Copy link
Copy Markdown
Member

Thanks for this proposal, this is an interesting design space. I'm curious if you think we 'stop' at a a single level of nesting or if we go deeper. Like why could I not have a meta-lead session that delegates to other lead sessions that delegate to multiple chats? That would influence the design quite a bit.

No separate listChats command and no "primary chat" concept — all chats are equal peers.

I wonder if this actually needs to be the case? Team-based operations all have a lead chat. Even for forking, you will have an original chat you start with. If we do go more towards the direction of infinitely nestable chats, then having a 'root' node of the chat tree would simplify the model.

cc @TylerLeonhardt both for the Claude POV and his experience with George 😛

@sandy081
Copy link
Copy Markdown
Member Author

sandy081 commented Jun 3, 2026

Really like the depth question — it pushed me to think about whether multi-chat alone is the right abstraction or whether nesting belongs in the same model. After working through it I landed on a two-primitive composition I'd like to sketch, then explain why I want to land them as two PRs rather than one.

The shape I'd propose for depth. Add a parentSession?: URI to sessions, making sessions form a tree. Then the model has two orthogonal axes:

  • Chats (this proposal) = breadth within one shared context. Multiple parallel conversations on the same task/workspace. Lightweight.
  • Sub-sessions (follow-up) = depth via delegated tasks with their own context boundary. Each sub-session has its own workspace, model, config — exactly what createSession already creates, just with a parent link.
ahp-session:/<root>            ← task, context A   (tree root)
  ├─ ahp-chat:/<c1>            ← conversation in A  ┐ breadth
  ├─ ahp-chat:/<c2>            ← conversation in A  ┘ (shared ctx)
  └─ ahp-session:/<sub>        ← sub-task, context B ┐ depth
        ├─ ahp-chat:/<c3>      ← conversation in B   │ (isolated ctx)
        └─ ahp-session:/<...>  ← nested arbitrarily  ┘

The two compose: a "meta-lead" is just a session whose children are sessions, each of which may have chats and further sub-sessions. Subagent / agent-team / dynamic-workflow style topologies all fall out — we're not modeling features, we're providing the two primitives whose combinations cover them.

On your "tree needs a root" point — I agree, and I think this resolves it: the session itself is the structural root of the tree. That lets us keep "chats are equal peers within a session" (no special primary-chat in state) and have a real root that owns aggregation and lifecycle. Both concerns met without contradiction.

But I'd like to land multi-chat first and sub-sessions as a separate proposal. Not because depth isn't important — because the two changes have very different shapes:

  1. Multi-chat = new channel type (ahp-chat:), new state shape, contained surface. Proves the channel pattern; we ship and learn.
  2. Sub-sessions = new dimension on an existing channel + hard cross-edge problems: result-reporting child→parent, dispose-cascade semantics, tree-aggregation rules under fan-out, cycle invariants, mixed-provider concerns. These deserve their own design pass, not a few bullets bolted onto a multi-chat PR.

Bundling them risks burying both. Sequencing is also cheaper pre-1.0 — smaller increments, fewer flying chunks of compatibility per release. The chat catalog and ahp-chat: channel here are designed so a later parentSession? addition composes cleanly without further breakage.

Happy to spin the sub-session proposal next if the direction sketched above resonates — or to discuss the shape further here before I do. What do you think?

…ions

Updates the multi-chat proposal in response to PR #184 review feedback:

- Add a Scope section clarifying that this proposal covers multi-chat
  (breadth) only; arbitrary nesting via sub-sessions (depth) is deferred
  to a separate proposal but designed to compose orthogonally.
- Add an 'Open implementation questions' subsection enumerating concerns
  that survive scoping to chat-only: cross-chat write coordination,
  disposal lifecycle, interactive routing under concurrency, aggregation
  bounds, session-wide turn history, default-chat UI hint, and forward
  compatibility with sub-sessions.
- Add a closing paragraph to the alternatives section sketching the
  two-primitive (chats = breadth, sub-sessions = depth) composition that
  a future proposal will introduce.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@connor4312
Copy link
Copy Markdown
Member

connor4312 commented Jun 4, 2026

I did some research and discussion with my agent. Specifically in thinking about multi-chats, I want to get to a place where we can model big multi-agent systems native in AHP. Obviously we don't need to one-shot Gas Town into this initial proposal, but we should create a foundation for that. With that perspective our findings were:

  • A lead chat probably does make a good deal of sense. Basically everyone does this: Gas Town, Claude Agent Teams, AutoGen, LangGraph, CrewAI, MetaGPT, and ChatDev. This could just be a pointer on the session state to the primary chat that's running, e.g. defaultChat?: URI
  • We probably don't need nested subsessions, so I retract my earlier proposal. This doesn't seem to be something folks have found much use for yet, it seems that more explicit coordination primitives are sufficient (mailboxes, tasks, beads, etc)
  • We should keep a flexible lineage indicator (union type) so that subchats can indicate not just when they were forked, but also if they were spawned off other operations in chat. We don't need to represent all of these initially, but we should structure that field in a sufficiently flexible way.

So tl;dr I think your initial proposal is pretty good 😄 However I would not put this stuff on the SessionSummary unless you need it as part of the session list prior to subscribing to a session. I'm actually going to break SessionSummary out of the SessionState as part of #187

gpt did some nice research here and ended up concluding with generally the same model that I had in my head https://chatgpt.com/share/6a2190f5-c3c0-83ea-adb9-38f32747d022

Incorporates connor4312's review (#184 (comment)) and the supporting multi-agent-systems research note:

- Reframe motivation: session = coordination scope, chats = conversation
  streams over that scope (the AHP-as-DAP/LSP framing). Make explicit
  that the protocol does not model agent hierarchies; those are host
  concerns.
- Move chats[] catalog from SessionSummary to SessionState. Keeps the
  session-list view cheap and aligns with issue #187 (splitting
  SessionSummary out of SessionState) so the dual-update problem is not
  re-created. Subscribing to the session delivers the full catalog.
- Add Q11: defaultChat?: URI on SessionState — a UI input-routing hint
  for unaddressed messages. Explicitly framed as routing, not hierarchy;
  chats remain equal peers at the protocol level.
- Add Q12: replace fork-specific forkedFrom with a ChatOrigin
  discriminated union (userCreated / forked / createdByOperation).
  Populate userCreated and forked now; createdByOperation reserved for
  future coordination-primitives work — declaring the union shape now
  avoids a breaking change when operations land.
- Rewrite §12 forward-direction: drop sub-sessions / parentSession as
  the next axis. Replace with coordination primitives (work items,
  operations, assignments) as the natural follow-up — matches the
  DAP/LSP philosophy and what real multi-agent systems coordinate
  around in practice.
- Drop the resolved 'UI default chat hint' and 'forward-compat with
  sub-sessions' items from open implementation questions (now covered
  by Q11 and §12 respectively).
- Update §8 surface, §7 compat notes, and breaking-change table for
  the catalog move and the new fields.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@sandy081
Copy link
Copy Markdown
Member Author

sandy081 commented Jun 4, 2026

Thanks for the deep dive — really helpful, and the framing from your research note shifted the proposal in a few important ways. Just pushed 0a9f5ef with the changes; summary of where we landed:

Adopted from your comment + research note:

  • Reframed motivation around "session = coordination scope, chats = conversation streams over that scope" (the AHP-as-DAP/LSP framing). Made it explicit that the protocol does not model agent hierarchies / roles — those are host concerns.
  • defaultChat?: URI on SessionState (new Q11). Documented as a UI input-routing hint for unaddressed messages, not a hierarchy marker — chats remain equal peers at the protocol level. Survey of multi-agent systems in your note cited as supporting evidence.
  • ChatOrigin discriminated union instead of a single forkedFrom (new Q12). Populated initially with userCreated and forked; reserved createdByOperation for the future coordination-primitives work. Declaring the union shape now means later provenance kinds land additively.
  • Moved chats[] from SessionSummarySessionState to keep the session-list view cheap and avoid re-creating the dual-update problem Remove SessionSummary from SessionState #187 is fixing. Added a coordination note about Remove SessionSummary from SessionState #187 in §4. (No chatCount rollup on the summary — for our session-list UX it isn't needed; can be added additively later if anyone wants list-view badges.)
  • Retracted the sub-sessions follow-up framing in §12. Replaced with a "Future direction: coordination primitives, not session trees" section pointing at work items / operations / assignments as the natural next axis — matches the DAP/LSP philosophy and what real multi-agent systems coordinate around. The chat catalog and ChatOrigin shapes here are designed to compose with that direction without further breaking changes.

Not adopted (and why):

  • Surveyed for role / purpose / parentChat on chats per your research's recommendation — agree these are host concerns and stayed out of the proposal.

Assuming we're aligned on the above, I'll start on the implementation (types in types/channels-chat/, codegen, reducers + tests, then per-client updates). Will open the implementation PR(s) against the same branch family so you can review incrementally. Shout if anything in the latest commit looks off before I get too far in.

- Replace 'createdByOperation' variant with 'tool' to avoid name overlap
  with ChangesetOperation* (which uses 'operation' for an unrelated
  concept). Tool-spawned chats are the realistic near-term path anyway.
- Rename variants per AHP style: 'userCreated' → 'user', 'forked' → 'fork'.
- Use a const enum ChatOriginKind as the discriminator (matches existing
  AHP convention, e.g. PendingMessageKind, TerminalClaimKind).
- Tool variant carries { chat: URI, toolCallId: string } so it references
  the tool call that spawned it; Fork variant carries { chat, turnId }
  for the branched-from point.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants