This feature requires the LangGraph Agent Server. Run your agent locally with
langgraph dev or deploy it to LangSmith to use this pattern.What is branching chat?
Branching chat treats a conversation as a tree rather than a list. Each message is a node, and editing a message or regenerating a response creates a fork from that point. The original path is preserved as a sibling branch, so users can switch back and forth between different conversation trajectories. Key capabilities:- Edit any user message: rewrite a previous prompt and re-run the agent from that point
- Regenerate any AI response: ask the agent to produce a different answer for the same input
- Navigate branches: switch between different versions of the conversation using per-message branch controls
Set up useStream with history
To enable branching, passfetchStateHistory: true so that useStream
retrieves checkpoint metadata needed for branch operations.
Define a TypeScript interface matching your agent’s state schema and pass it as a type parameter to useStream for type-safe access to state values. In the examples below, replace typeof myAgent with your interface name:
Understand message metadata
ThegetMessagesMetadata(msg) function returns branch information for each
message:
When a message has only one version,
branchOptions contains a single entry.
After an edit or regeneration, new branch IDs are added to branchOptions,
and you can navigate between them.
Edit a message
To edit a user message and create a new branch:- Get the
parent_checkpointfrom the message’s metadata - Submit the edited message with that checkpoint
- The agent re-runs from that point, creating a new branch
- The message’s
branchOptionsgains a new entry - The view switches to the new branch automatically
- The agent re-runs from the fork point with the updated message
- The original version is preserved and accessible via the branch switcher
Regenerate a response
To regenerate an AI response without changing the input:- Get the
parent_checkpointfrom the AI message’s metadata - Submit with
undefinedinput and the parent checkpoint - The agent produces a fresh response, creating a new branch
Build a branch switcher
When a message has multiple branches, show a compact inline control with the current version index and navigation arrows:stream.setBranch(branchId) to
switch the conversation view to that branch. This is instant since all branch
data is already loaded via fetchStateHistory: true.
Switching branches affects not only the target message but also all subsequent
messages. If you switch to a different version of message 3, messages 4, 5, 6,
etc. will also update to reflect the conversation that followed that version.
How branching works under the hood
LangGraph persists every state transition as a checkpoint. When you submit with acheckpoint parameter, the backend forks from that point instead of
appending to the current conversation. The result is a tree structure:
Complete message component
Here is a full component that combines message display, editing, regeneration, and branch switching:Combine with optimistic updates
Combine branching with optimistic updates for a seamless editing experience. When the user saves an edit, optimistically show the updated message before the server responds:Add keyboard navigation
For power users, add keyboard shortcuts to navigate branches:Best practices
- Always enable
fetchStateHistory: without it,getMessagesMetadatacannot return branch information. - Only show the branch switcher when there are multiple branches: a
1/1indicator adds clutter without value. - Show branch controls on hover: branch navigation arrows and edit buttons should appear on hover to keep the UI clean.
- Keep the branch switcher compact: it sits inline with message controls and should not dominate the UI.
- Preserve scroll position: when switching branches, try to keep the viewport anchored to the message that changed.
- Indicate the active branch: use subtle visual cues (e.g., a colored dot or branch label) so users know which branch they’re viewing.
- Disable controls while streaming: don’t allow edits or regeneration
while the agent is actively streaming a response. Check
stream.isLoadingbefore enabling these actions. - Preserve edit text on cancel: if the user starts editing, then cancels, reset the textarea to the original message content.
- Test with deep branch trees: users who edit and regenerate frequently can create many branches. Ensure the branch switcher and data handling remain performant.
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

