Skip to content

[Feature] Add conversation branching and message actions support in Copilot SDK #66

@ankushchhabradelta4infotech-ai

Description

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:

  • I've searched existing issues to make sure this isn't a duplicate
  • I've read the documentation

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions