Add plugin registry for Duo Agentic Chat message widgets

What does this MR do and why?

The Duo Chat panel is the central UI for AI features in GitLab, so teams outside the core chat group want to contribute custom message renderers to it. Today the only way to do that is to edit core files: Edit duo_agentic_chat_state_manager.vue, a component that has grown to roughly 2100 lines.

This MR introduces a plugin registry that lets a team register a message renderer without touching core chat code. It migrates the existing MessageToolStartFlow renderer onto it as proof that the mechanism works end to end.

This is the first iteration of the plugin architecture described in the design document linked below. It ships only the messageWidgets capability. Empty states, slash commands, and alerts are also named in the design document but are deliberately out of scope here.

Architecture

flowchart TB
    subgraph Initialization
        init[init_duo_panel.js]
        init --> |constructs| registry[DuoChatPluginRegistry]
        init --> |calls| initPlugins[initializePlugins]
        initPlugins --> |registers| registry
    end

    subgraph Engine["Engine (services/)"]
        registry
        registry --> |validates via| capabilities[CAPABILITIES list]
        capabilities --> |iterates| msgWidgets[message_widgets.js]
        msgWidgets --> |validates shape| validation{Validation}
        validation --> |pass| accept[Accept registration]
        validation --> |fail| sentry[Report to Sentry]
    end

    subgraph Features["Features (plugins/)"]
        pluginsIndex[plugins/index.js]
        pluginsIndex --> |imports| startFlow[start_flow/]
        startFlow --> sfMessageWidget["message_tool_start_flow.vue (message widget)"]
        startFlow --> sfSlashCommand["start flow slash commands (in the future)"]
    end

    subgraph VueTree["Vue Component Tree"]
        init --> |provides registry| stateManager[duo_agentic_chat_state_manager.vue]
        stateManager --> |resolves renderers from| registry
    end

    initPlugins --> pluginsIndex

New code, split into engine and features:

  • services/plugin_registry.js DuoChatPluginRegistry, holding registered plugins in a private field. registerPlugin validates a registration before accepting it.
  • services/plugin_capabilities/message_widgets.js — the one capability shipped in this iteration. A capability owns one field of the plugin contract and provides validation of that field's shape plus mapping of registrations to the data a core component consumes. The registry iterates a CAPABILITIES list and never names a capability itself, so adding a capability later is a new module plus one array entry, with no engine change.
  • plugins/start_flow/ — the first plugin. message_tool_start_flow.vue moved here from components/messages/, along with the message-matching predicate that used to be inlined in the state manager.
  • plugins/index.jsinitializePlugins(registry), which registers every bundled plugin. Adding a plugin going forward is one import and one array entry here.
  • index.js — barrel export of the registry class.

Wiring: init_duo_panel.js constructs the registry, calls initializePlugins, and provides it to the Vue tree. duo_agentic_chat_state_manager.vue injects it (defaulting to an empty registry) and resolves its message renderers from it instead of the previous hardcoded list.

A malformed plugin registration is dropped and reported to Sentry rather than thrown, so one bad contribution cannot stop the chat panel from initializing. Error messages name the offending capability and entry index, for example messageWidgets[0] `matchMessage` must be a function.

References

Design document, which is the source of the plugin API this implements: https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/ai_chat/#extensible-plugin-architecture-goal-2

Screenshots or screen recordings

Not applicable. No visual or behavioural change.

How to set up and validate locally

  1. Open the Duo Chat panel.
  2. Send a prompt that triggers a flow, so the agent emits a start_flow tool call.
  3. Confirm the flow widget still renders as before: the pill or expanded card appears, the workflow status polls and updates, and clicking it opens the session.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Enrique Alcántara

Merge request reports

Loading
Loading