Summary
Add conversation branching and message actions support in Copilot SDK so apps can natively support edit/retry branches plus built-in actions like copy and regenerate without custom renderer plumbing.
Problem / Use Case
Today advanced chat UX requires app-side workarounds:
- Branching must be implemented in external state and manually synced into SDK messages
- Default message UI does not expose a standard action API for common controls (copy, regenerate, custom actions)
- Teams rebuilding the same patterns risk inconsistent behavior for tools/artifacts/thinking across branches
- Rehydration after refresh is fragile when branch state and action behavior are app-defined
Use cases:
- Edit a user message and keep prior assistant responses as alternative branches
- Regenerate into a new branch (instead of overwrite)
- Add consistent message-level actions (copy, regenerate, branch nav, custom workflow actions)
Proposed Solution
Introduce native branching primitives and a message action extension point across SDK core/react/ui.
1) Branching in message model + runtime APIs
-
Extend message model with branch metadata:
-
parentId?: string | null
-
branchOrder?: number
-
branchId?: string (optional, or derived internally)
-
Add branch-aware APIs to useCopilot():
-
createBranch(fromMessageId: string): string
-
switchBranch(parentId: string | null, branchIndex: number): void
-
getVisibleMessages(options?): UIMessage[]
-
regenerate(options?: { mode?: "replace" | "branch" })
-
Provider config:
-
branching?: { enabled: boolean; defaultRegenerateMode?: "replace" | "branch" }
2) Standard message actions API
Add built-in message action definitions in CopilotChat:
copy action (enabled by default)
regenerate action (assistant messages, configurable mode replace/branch)
- optional custom actions via callback/slot API
Example props:
messageActions?: { copy?: boolean; regenerate?: boolean; custom?: MessageAction[] }
onMessageAction?: (action, message) => void
3) UI defaults for actions + branches
In default message renderer:
-
Show action row on hover/focus:
-
Copy
-
Regenerate
-
Branch navigation (if sibling branches exist)
-
Provide composable primitives:
-
<MessageActions />
-
<MessageAction type="copy" />
-
<MessageAction type="regenerate" mode="branch" />
-
<BranchNavigator />
4) Persistence + rehydration contract
- Ensure
initialMessages supports branch metadata
- Ensure
onMessagesChange emits active branch path/state
- Define deterministic behavior when branch metadata exists but active branch is missing
<CopilotProvider
runtimeUrl="/api/copilot-stream"
branching={{ enabled: true, defaultRegenerateMode: "branch" }}
>
<CopilotChat
messageActions={{
copy: true,
regenerate: true,
custom: [
{ id: "pin", label: "Pin", icon: PinIcon },
],
}}
onMessageAction={(action, message) => {
if (action.id === "pin") pinMessage(message.id)
}}
/>
</CopilotProvider>
function CustomFooter() {
const { regenerate, switchBranch } = useCopilot()
return (
<>
<button onClick={() => regenerate({ mode: "branch" })}>Regenerate as Branch</button>
<button onClick={() => switchBranch("parent_msg_id", 1)}>Switch Branch</button>
</>
)
}
Alternatives Considered
-
Keep branching/actions fully app-side with custom renderers and store sync
Works, but duplicates complex logic and causes inconsistent UX across apps.
-
Add only UI-level branch navigator
Insufficient without core branch semantics and persistence support.
-
Use separate threads instead of branches
Loses continuity and makes side-by-side alternatives harder.
Additional Context
Branching + actions are foundational for advanced agent UX (planning, approvals, edits, retries, and comparison workflows).
A native SDK approach would significantly reduce integration complexity and improve consistency for teams building production chat interfaces.
Before submitting:
Summary
Add conversation branching and message actions support in Copilot SDK so apps can natively support edit/retry branches plus built-in actions like copy and regenerate without custom renderer plumbing.
Problem / Use Case
Today advanced chat UX requires app-side workarounds:
Use cases:
Proposed Solution
Introduce native branching primitives and a message action extension point across SDK core/react/ui.
1) Branching in message model + runtime APIs
Extend message model with branch metadata:
parentId?: string | nullbranchOrder?: numberbranchId?: string(optional, or derived internally)Add branch-aware APIs to
useCopilot():createBranch(fromMessageId: string): stringswitchBranch(parentId: string | null, branchIndex: number): voidgetVisibleMessages(options?): UIMessage[]regenerate(options?: { mode?: "replace" | "branch" })Provider config:
branching?: { enabled: boolean; defaultRegenerateMode?: "replace" | "branch" }2) Standard message actions API
Add built-in message action definitions in
CopilotChat:copyaction (enabled by default)regenerateaction (assistant messages, configurable mode replace/branch)Example props:
messageActions?: { copy?: boolean; regenerate?: boolean; custom?: MessageAction[] }onMessageAction?: (action, message) => void3) UI defaults for actions + branches
In default message renderer:
Show action row on hover/focus:
Copy
Regenerate
Branch navigation (if sibling branches exist)
Provide composable primitives:
<MessageActions /><MessageAction type="copy" /><MessageAction type="regenerate" mode="branch" /><BranchNavigator />4) Persistence + rehydration contract
initialMessagessupports branch metadataonMessagesChangeemits active branch path/stateAlternatives Considered
Keep branching/actions fully app-side with custom renderers and store sync
Works, but duplicates complex logic and causes inconsistent UX across apps.
Add only UI-level branch navigator
Insufficient without core branch semantics and persistence support.
Use separate threads instead of branches
Loses continuity and makes side-by-side alternatives harder.
Additional Context
Branching + actions are foundational for advanced agent UX (planning, approvals, edits, retries, and comparison workflows).
A native SDK approach would significantly reduce integration complexity and improve consistency for teams building production chat interfaces.
Before submitting: