Chat Branching
Fork any conversation at any message to explore alternative paths, test different prompts, or preserve a working state before experimenting.
Overview
Chat branching lets you create multiple independent conversation threads within a single chat session. Each branch starts from a point in the conversation history and continues independently from that point forward. Branches share the same document workspace and uploaded files, but their message histories are separate.
Every chat starts with one branch (the default branch). You can create as many additional branches as needed. Common use cases include:
- A/B testing prompts -- fork after your initial setup and try different approaches in parallel branches without losing either result.
- Exploring alternatives -- ask the model to try a different approach in a new branch while keeping the original intact.
- Rolling back -- fork before a risky or experimental direction so you can return to the fork point if things go wrong.
- Isolating concerns -- use separate branches for different subtopics in a long-running project.
Each branch is identified by a unique external ID in branch_xxx
format and has a user-supplied display name. Branches record which branch
they were forked from (their parent) and at which message sequence number
the fork occurred.
Note: Documents uploaded to the workspace are shared across all branches within a chat. A document uploaded on one branch is searchable on all other branches.
Creating a Branch
You can create a new branch at any time from the Branches panel in the chat toolbar. This creates a branch forked from the end of the current active branch -- all current messages are included in the new branch's history.
- Open the chat toolbar and click the Branches button (the branch icon).
- Click the New Branch button at the bottom of the panel.
- Enter a display name for the branch. The name is required.
- Optionally select a system prompt template to apply to the new branch.
- Click Create. The branch is created and you are switched to it automatically.
The branch selector in the toolbar updates to show the new branch as the active selection.
Fork from a Message
You can also fork a branch at a specific point in the conversation history by clicking the fork icon on any individual message. This creates a branch that diverges at that message -- messages after the fork point on the current branch are not included in the new branch's history.
- Hover over any message in the conversation to reveal its action buttons.
- Click the fork icon (git-fork) on the message.
- The fork modal opens with the fork point pre-set to that message's sequence number.
- Enter a display name and optionally select a system prompt template.
- Click Create. The new branch starts from that point in the history.
The forkAfterSequence field on the branch record stores the
sequence number at which the fork occurred, giving you a precise record
of the branch's origin in the parent's history.
Switching Branches
The branch selector dropdown in the toolbar always shows all available branches for the current chat. Select a branch from the dropdown to switch to it immediately. The message list clears and reloads with the selected branch's history.
Switching a branch also restores the branch's system prompt override, if one was configured when the branch was created.
You can also switch branches from the Branches panel by clicking a branch name in the tree list.
Branch Panel
The Branches panel provides a visual overview of all branches in the chat using a git-tree style layout. Open it by clicking the branch icon in the toolbar.
The panel renders branches as a flat tree. Each branch is displayed as a row with:
- A colored lane indicator dot (each branch lane has a distinct color).
- The branch display name as a clickable button that switches to that branch.
- A delete button (available when more than one branch exists).
The currently active branch is visually highlighted. Child branches are indented under their parent to reflect the parent-child tree structure.
A New Branch button at the bottom of the panel opens the fork modal to create a branch from the current position in the active branch.
Branch System Prompts
Each branch can carry an optional system prompt override. When a branch has a system prompt set, that prompt replaces the chat-level system prompt during context assembly for all messages on that branch.
Branch system prompts are set at fork time by selecting a template from
the template selector in the fork modal. Templates are fetched from
GET /chat/api/templates and appear as options in the dropdown.
If no template is selected, the branch inherits the chat's default system
prompt.
Switching branches automatically restores the target branch's system prompt in the canvas state so subsequent messages on that branch use the correct prompt.
Note: System prompt overrides apply per-branch. Changing the chat-level system prompt does not affect branches that have an override already set.
Automatic Forking
The system can automatically fork the conversation when the context window approaches its limit. When this happens, the active branch is forked automatically into a new branch with a generated name, and the user is notified by a toast message:
Context limit approaching -- forked to "Branch Name"
This automatic fork is triggered by a server-sent x_context_fork
event in the streaming response. The new branch ID and name are provided
in the event payload. The branch selector is updated automatically and the
active branch switches to the new fork without requiring any user action.
Each branch maintains a rolling summary of older messages and a
summaryThroughSequence counter so that summarized history
can be reconstructed efficiently within the token budget.
Deleting Branches
Branches can be deleted from the Branches panel. Click the delete icon on any branch row to remove it. Deleting a branch requires confirmation.
The last remaining branch cannot be deleted -- at least one branch must always exist in a chat. If you attempt to delete the last branch, a toast error is shown and the operation is cancelled.
Deleting a branch also deletes all of its sub-branches (child branches that were forked from it). The confirmation dialog notes this.
Branches are soft-deleted in the database. The record remains with a
deleted_at timestamp but is excluded from all list queries.
If the active branch is deleted, the UI automatically switches to the
first remaining branch.
Branch API
All branch operations are available via the chat API. All endpoints require authentication.
List Branches
GET /chat/api/{chatId}/branches
Returns all active branches for the chat ordered by creation date.
curl https://api.xerotier.ai/chat/api/550e8400-e29b-41d4-a716-446655440000/branches \
-H "Cookie: session=your_session_token"
{
"branches": [
{
"id": "branch_ABCdef123456789012345678",
"name": "Main",
"parentId": null,
"systemPrompt": null,
"createdAt": "2026-04-07T10:00:00Z"
},
{
"id": "branch_XYZabc987654321098765432",
"name": "Experiment A",
"parentId": "branch_ABCdef123456789012345678",
"systemPrompt": "You are a concise assistant.",
"createdAt": "2026-04-07T10:15:00Z"
}
]
}
Create Branch
POST /chat/api/{chatId}/branch
Creates a new branch forked from the current active branch.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| namerequired | string | Yes | Display name for the new branch. |
| branchrequired | string | Yes | The ID of the parent branch to fork from. |
| atSequenceoptional | integer | No | Fork after this message sequence number. When omitted, the fork point is the end of the parent branch. |
| templateIdoptional | string | No | System prompt template ID to apply to the new branch. |
curl -X POST https://api.xerotier.ai/chat/api/550e8400-e29b-41d4-a716-446655440000/branch \
-H "Cookie: session=your_session_token" \
-H "Content-Type: application/json" \
-d '{
"name": "Experiment A",
"branch": "branch_ABCdef123456789012345678",
"atSequence": 12
}'
Delete Branch
DELETE /chat/api/{chatId}/branch/{branchId}
Soft-deletes a branch and all of its sub-branches. Returns HTTP 400 if deleting the last branch is attempted. Returns HTTP 204 on success.
curl -X DELETE https://api.xerotier.ai/chat/api/550e8400-e29b-41d4-a716-446655440000/branch/branch_XYZabc987654321098765432 \
-H "Cookie: session=your_session_token"
Data Model
Each branch is persisted as a chat_branches record linked
to the parent chat. The key fields are:
| Field | Type | Description |
|---|---|---|
id |
string | External branch identifier in branch_xxx format (24 random alphanumeric characters after the prefix). |
name |
string | User-supplied display name for the branch. |
parentId |
string (nullable) | External ID of the parent branch this was forked from. Null for the root branch. |
forkAfterSequence |
integer (nullable) | Sequence number after which the fork occurred. Null when forked from the end of the parent. |
systemPrompt |
string (nullable) | Optional system prompt override for this branch. When set, replaces the chat-level system prompt during context assembly. |
rollingSummary |
string (nullable) | Periodically generated summary of older messages on this branch, used to keep context within the token budget. |
summaryThroughSequence |
integer (nullable) | The highest sequence number covered by the rolling summary. Messages after this point are included verbatim in context. |
lastResponseId |
string (nullable) | Most recent Responses API response ID for conversation chaining. Updated after each completed assistant response on this branch. |
createdAt |
string | ISO 8601 timestamp when the branch was created. |
deletedAt |
string (nullable) | ISO 8601 timestamp when the branch was soft-deleted. Null for active branches. |
Related Pages
- Chat Memory -- saving and recalling per-workspace knowledge across conversations.
- Document Workspace -- uploading documents that are shared across all branches.