Skip to content

docs(RFD): add proposal for forking at a specific message#629

Open
SteffenDE wants to merge 2 commits into
agentclientprotocol:mainfrom
SteffenDE:sd-fork-at
Open

docs(RFD): add proposal for forking at a specific message#629
SteffenDE wants to merge 2 commits into
agentclientprotocol:mainfrom
SteffenDE:sd-fork-at

Conversation

@SteffenDE

Copy link
Copy Markdown
Contributor

Based on #233 and #536.

The fork RFD already mentioned forking at a specific message. Since we now have the message-id RFD, we can extend fork with this capability to allow features like editing messages, regenerating responses, retroactively branching, etc.

@SteffenDE
SteffenDE requested a review from a team as a code owner March 3, 2026 16:27

@benbrandt benbrandt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think inclusive makes sense here.
Do we want to say something like this only works on agent messages?
Or, should we allow the agent to provide context on a given fork point?
Do we basically take user messages as the only valid fork points?

I think this could also solve the "edit previous message" case, but maybe then we want a way to say "don't create a new session, just truncate" which only some agents might support (codex would for example) just thinking about the edit use case that you may not always want to fully fork, but maybe we don't have to solve that right now

@SteffenDE

Copy link
Copy Markdown
Contributor Author

Do we basically take user messages as the only valid fork points?

I think we can let the agent respond with an error if it cannot fork from a specific message, but assume that by default any message id can be used as fork point.

The edit previous message is our main use case for Tidewave. I think it should still be a full fork. If clients want a "rewind current session" or similar, that should rather be a different method in my opinion, e.g. session/rewind with message id. If the concern is that each edit creates a new chat (listed in the session list), I guess we have to live with that. Maybe agents support deleting sessions at some point, so we could simulate a session/rewind with a fork at id, then deleting the old session.

@benbrandt

Copy link
Copy Markdown
Member

I think we could go with any message, but I also wonder if the agent should indicate a given message is a forkable point? So if you see some property on the message, you know it can fork from there and the client can indicate as such?

@SteffenDE

Copy link
Copy Markdown
Contributor Author

I'm wondering if we should have this as a field on the capability, like session: { fork: { atMessageId: { user: true, agent: false, thought: false } } }. But that might not be granular enough depending on the agent.

If it's on the message, the question would be where to put it. The messageId is on the update, so each agent_chunk would need to include not only the messageId, but also canBeForked: boolean (or similar). But then, would it be valid if an agent changes the boolean in a following update? Or should it be a separate session update notification { "sessionUpdate": "message_update", "forkable": true }. Should it be assumed true by default and the agent may send an update to mark it as non-forkable? The other way round? Lots of options.

@Nemtecl

Nemtecl commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Hello!

I'm really excited about this proposal!

I agree with @SteffenDE that we'll need the agent to indicate which messages are "forkable" points, especially for session/rewind (which will include features like reverting file changes, etc.).

For v1, do you think we could proceed with the current proposal and iterate as needed while it’s still unstable, @benbrandt ?

@SteffenDE

Copy link
Copy Markdown
Contributor Author

@benbrandt I updated the proposal to accomodate the problems I found trying to make this work with claude-agent-acp. I decided to introduce a separate forkId and forkPoint sessionUpdate notification, which allows this to work for agents that can't provide message IDs with the current RFD.

For the v2 prompting proposal, this could be a forkId on a user_message / agent_message instead, but it could also stay the same.

@AAEE86

AAEE86 commented Jul 14, 2026

Copy link
Copy Markdown

As a regular user of codeg, I often find myself wanting to edit a previous question or regenerate a response without losing the context of the current conversation. This forking feature would directly solve that pain point for me and make the tool much more flexible. I sincerely hope this proposal can move forward soon!

@hussain

hussain commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Client implementor here (ACP Patchbay — a multi-agent ACP client for VS Code). Reading this thread, the anchor machinery (forkable points, forkId, per-kind capability granularity) looks like a symptom of a root choice worth revisiting: fork is seed-by-reference, so the cut must happen inside the agent's store — which forces the agent to advertise, mark, and validate legal cut points.

Consider defining the inverse primitive first: seed-by-value — session/new with an optional history param carrying ACP wire-format history (the exact shape session/load already replays, _meta included). The client already holds the full story — it rendered every message — so it cuts wherever it wants:

fork-at-message = seed with the story truncated before that message — no anchor negotiation, no forkId, no canBeForked
edit-previous-message = truncate + append the replacement
and it buys things reference-fork never can: cross-agent handoff, backup/restore, and repairing sessions continued externally (a real divergence I've hit between an editor and a CLI sharing one session)
session/fork(sessionId) remains valuable as the optimized special case — same-store seeding that can reuse provider prompt cache and agent-private state, and the right base for rewind-with-file-reverts. Cost is the honest trade: value-seeding re-ingests tokens where native fork reuses cache — which is exactly why both belong: the general door, and the fast path through it.

The RFD's FAQ rejected extending session/new on the grounds that fork shouldn't set capabilities/MCP — but that reasoning applies to reference-seeding (context built under other options), not value-seeding, where the story is just context and the session is genuinely new. (#326 ended up giving fork the load options anyway.)

@benbrandt

Copy link
Copy Markdown
Member

@SteffenDE I've been thinking about this. I think we need an idea of "cursors" for various use cases:

  • Forking
  • Rewind/truncate
  • "attach" or "replay" points for loading.

Basically, I don't think it is always enough to have a tool id or message id. You have to know what are valid points the agent can do something with. These cursors would be opaque, so if the agent happens to reuse the message id, so be it, but we need someway for the agent to communicate "this is a valid point for this operation"

@hussain I strongly disagree with your point. I think the feature of seeing a session is nice. But it is inherently a lossy transition, because the various agents can store more information that they use internally in their own persistence. There is no guarantee the ACP representation has everything needed.

I still think we need to allow that use case because it is helpful for other scenarios that you describe. But I don't think it is the right choice for these scenarios.

@hussain

hussain commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

@benbrandt I agree for those scenarios, it would be a wast to seed new session. The gap against agent's store is real, and it makes me ask how ACP is looking at it from protocol prospective?
Agents have different ways of storing (source of truth). My understanding is that clients (IDE's, Extensions...etc) would need that source of truth to be carried in the wire, otherwise will end up with another storage in client side. I know this would actually needs definition first of what are those before even thinking about RFD.
There are times while implementing as ACP client where I feel the protocol is not carrying enough cross the wire to enable more features bridging, probably because I'm new in here and it would take me sometime to understand prospective of why things are the way they are.

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.

5 participants