Skip to content

[FEATURE]: ability to revert/fork from the ai message, not only from the user's #8689

Open

Description

@art-shen

Feature hasn't been suggested before.

  • I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

PROBLEM: Currently, we can only respond to or create a fork from the user's message, which is suboptimal in many ways. We cannot revert to the middle of the AI model's actions or some of the model's thoughts, to correct/address them right away.

E.g., it's common for me to only have one message at the start of the session, which effectively prevents me from using these options. Sometimes, when I realise that the AI model is behaving incorrectly, I can’t do anything about it except start the session again from the very beginning.

If OpenCode provided the ability to revert or fork from one of the model's messages or tool calls, we could choose the exact moment when the model started to malfunction, which would increase the efficiency of the whole workflow tremendously.

Is it possible to support that?

Activity

  1. added
    discussionUsed for feature requests, proposals, ideas, etc. Open discussion
    on Jan 15, 2026
  2. github-actions commented on Jan 15, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    Feel free to ignore if none of these address your specific case.

  3. JosXa commented on Feb 16, 2026

    @JosXa
    Contributor

    Yes please!

    We can fork only from our own messages. Why? Is there any particular reason for that?
    Most of the time, I want to branch out with whatever the current state of the conversation is, not my own message, which might be 200 messages up...

    Workaround: Abort streaming, send a dummy message, fork from that, continue

  4. bigs commented on Feb 17, 2026

    @bigs

    This one was bugging me, so I've prepared a diff that implements it with a nice little tab modifier in the "fork" dialog that lets you toggle between user messages and assistant messages as fork points. If you'd like, I'd be happy to contribute it upstream!

    Edit: Just reviewed the contributor guidelines. Understandable that anything touching the UX has more guardrails around the process. Happy to submit my changes through that, but definitely understand if you're not taking outsider contributions on this.

  5. OverHash commented on Mar 11, 2026

    @OverHash

    Related to #3903

  6. mutageneral commented on Mar 24, 2026

    @mutageneral

    yes pls. mimo is asking me what to work on next, I would like to be able to just choose an answer no stress and be able to click on my answer later to fork and it would ask me the question again in the new copied session, so I could pick a different answer. even better if you can switch models inbetwix!!!

  7. MichaelYochpaz commented on Apr 4, 2026

    @MichaelYochpaz
    Contributor

    I'd also be happy to have this option. I have an issue where an agent attempted to open an image, and it failed, and any subsequent messages fail with the same error because of this image.

    I have to revert a long session of many agent messages back to my original message because I can't just remove this last agent message trying to load the image, causing the issue.

  8. removed
    discussionUsed for feature requests, proposals, ideas, etc. Open discussion
    on May 3, 2026
  9. iamvaibhav commented on Jun 23, 2026

    @iamvaibhav

    very much needed!

  10. MaciejGorczyca commented on Aug 16, 2026

    @MaciejGorczyca

    This is ridiculous that this feature was present before and was REMOVED at some point THEN unaddressed for almost a year.

    I asked AI to write simple and easy bat script that can fork ANY session from ANY message. Quick and elegant without any deep work inside OpenCode itself AND without waiting for mercy from contributors.

    Usage: opencode_fork_any_message.bat ^<sessionID^> ^<messageID^> [basic_auth] [cookie_token] [port]

    You can set OPENCODE_AUTH and OPENCODE_TOKEN as env variables to not pass it every time you fork something.

    If you are coding, you can probably easily find session tokens, cookies, headers, etc by yourself. Or ask your favorite AI agent.

    opencode_fork_any_message.txt

  11. m0wer commented on Aug 26, 2026

    @m0wer

    Especially relevant for sessions where instead of new messages, there are just questions replied by the user (which count as AI messages, not the user's).

  12. amanteaux commented on Oct 13, 2026

    @amanteaux

    This feature would be very appreciated, especially since questions from agent are not considered as user messages.

  13. opencodejr commented on Oct 29, 2026

    @opencodejr
    Contributor

    Thanks for the detailed write-up, @art-shen! You're asking to be able to fork (or revert) from an assistant message or tool call, not only from your own messages, so you can branch from the exact point where the model went off track. That matters most in sessions that started with a single prompt.

    In the current version the fork dialog only lists user messages. The session backend can already fork at any message, though, so this is mainly about what the TUI and app let you pick. Maintainers will consider it.

    Related issues:

    Until then, a workaround mentioned in the comments here is to stop the response, send a short dummy message, and fork from that message.

  14. Cossack13 commented on Nov 3, 2026

    @Cossack13

    +1 — and I'd extend the scope: an answer to the question tool is a user message in substance, so it deserves to be a first-class revert/fork point, not just a side effect of the AI turn.

    Why this hurts in practice:

    • A session driven through question answers can end up with a single user prompt in the transcript. The answer arrives as form.replied { id, sessionID, answer } into the pending tool call, no Session.Message.User is created, so the whole "ask → answer → 30 tool calls" block collapses into one revert unit.
    • Consequence: after a chain of questions /undo jumps straight back to the start of the session. bug: hitting /undo after answering question undoes last prompt #12625 describes exactly this — "Answer it → hit /undo → back at the start :(".
    • There is no setting to change it: Session.Message.Info has no message type for a form answer, and session.undo selects the last type === "user" && text.trim(). The answer simply never enters the transcript as a message.

    What I'd expect:

    1. revert.stage / fork can target the message (or part) that carries the question tool call, so /undo lands back on the question and it can be answered differently.
    2. Ideally the answer is recorded as a real user-role message (either type: "user" or a distinct type that session.undo treats as a boundary), so it shows up in the transcript and in session.context.

    Note: Session.Revert already accepts partID and POST /api/session/{id}/revert/stage supports it — the TUI just doesn't pass it. So part-level reverting may be mostly a client-side change.

    Real cost of the current behaviour: my orchestrator agent asks 5–10 clarifying questions per session, and each answer is a decision point I may want to revisit. Because one /undo can wipe hours of work, I've stopped using the question tool and ask in plain text instead — worse UX for both sides.

  15. yassine-safraoui commented on Nov 4, 2026

    @yassine-safraoui

    I’d find this very useful for debugging agent behavior: fork immediately after a tool call, ask the agent why it took that action, and use that feedback to improve skills or prompts.

    The challenge is exposing that power without cluttering the UI. I’d separate this into two workflows:

    1. Keep the command-palette fork dialog simple: user messages plus “Full session.”

    The TUI already offers “Full session,” and I think the web/desktop app should follow that approach. It lets you duplicate the conversation while retaining the latest assistant reply.

    For an earlier assistant reply, there’s already a workable shortcut if another user message follows it: fork from that following user message, then clear the restored text from the composer. That preserves the preceding assistant output. It’s slightly counterintuitive, but I’d prefer it over listing every assistant message in the dialog just to avoid clearing the input.

    2. Put granular fork actions directly in the conversation trace.

    For individual tool calls, reasoning blocks, edits, or other supported boundaries, the fork action should appear beside the item itself—for example, on hover or keyboard focus.

    The decision to fork from a particular action usually happens while reading that action. The user has already scrolled through the trace and found the relevant point. Sending them to a separate “fork from action” picker would force them to find that same item again among potentially hundreds of entries.

    Making that picker sufficiently navigable could also mean recreating much of the conversation view inside another dialog. An inline action avoids that disconnected workflow and keeps the main fork dialog focused.

    This shouldn’t be hover-only: touch users need an equivalent way to reveal the action, perhaps through a long press or contextual menu. A confirmation could also help prevent accidental forks, although the exact interaction would need consideration.

    In short: “Full session” in the existing fork dialog, and contextual actions in the trace for finer-grained branching. That provides both capabilities without turning the message picker into an exhaustive list of everything the agent did.

  16. dluc commented on Nov 4, 2026

    @dluc

    please add this feature in the UI. In the meantime I resorted to a plugin providing /fork-full-session:

    ctx.add(Command, () => {
      const current = ctx.sessions.current()
    
      return {
        id: "fork-full-session",
        title: "Fork full session",
        group: "Sidecar",
        slash: { name: "fork-full-session" },
        enabled:
          !!current &&
          !current.pending &&
          current.server.connected &&
          current.server.compatible,
    
        run: async () => {
          const session = ctx.sessions.current()
          if (!session || session.pending ||
              !session.server.connected || !session.server.compatible) return
    
          const client = session.server.client
          const server = session.server.id
          const sessionID = session.id
    
          try {
            const fork = await client.session.fork({ sessionID }, { signal: ctx.signal })
            if (!ctx.signal.aborted) {
              ctx.tabs.open({ server, id: fork.id }, { focus: true })
            }
          } catch {
            if (!ctx.signal.aborted) {
              ctx.toast.show({
                title: "Could not confirm the fork",
                description: "Check your sessions before trying again; the fork may have been created.",
                variant: "error",
              })
            }
          }
        },
      }
    })
  17. balabommablock-cpu commented on Nov 11, 2026

    @balabommablock-cpu

    I read the current dev code (7b830a4) to see how far off this is. It's closer than the thread suggests.

    Already there

    • The stored fork already has two boundaries: before a message and through a message (packages/schema/src/session-fork.ts). The projector copies < seq or <= seq.
    • In v2 each assistant step is its own message with its own snapshot. So "through this step" already means "right after this tool round".
    • The TUI fork dialog has Full session.

    Missing

    1. The API only takes before (ForkInput in packages/core/src/session.ts). through is only used for "no message given = whole session". So you can't say "through this assistant message", and that's why the dummy-message trick exists. A through?: messageID input looks like a small change.
    2. Web/desktop dialog has no Full session (packages/app/src/session/commands/fork-dialog.tsx lists user messages only). The TUI does.
    3. The inline "Fork" action is user-only (MessageAction in session-ui/src/message/action-machine.ts). With (1), the same action could show on settled assistant steps.

    Smallest version, in order

    • through on the fork API.
    • Full session in the web/desktop dialog, matching the TUI.
    • "Fork from here" on a settled assistant step in the timeline, as @yassine-safraoui suggested. Keep the dialog short and put the action where you're reading.

    Later, separate: re-answering a question. The answer sits inside the same step's tool part, so "through" keeps the old answer and "before" drops the question. That needs a part-level boundary or the answer stored as its own user row (@Cossack13's point). It's worth its own issue so it doesn't hold up the simple part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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