Skip to main content

Remote Component Plugins

This guide explains how to build a new remote_component plugin for the Assistant Workbench. remote_component is a View Extension view schema, not a trigger type: it can be listed from a normal view slot, or it can be opened explicitly by a tool result with xpert.extension_view. All data access and mutations still go through the platform’s authenticated View Extension APIs. Use this pattern when a plugin needs a full custom UI rather than a declarative table, list, stats, or detail view.

Architecture

A remote component plugin has at least two pieces. Add a tool entry only when the view should be opened on demand by an Agent conversation:
  1. ViewExtensionProvider: provides the manifest, data, parameter options, actions, and remote component HTML entry.
  2. Remote React page: runs inside a sandboxed iframe and communicates with the host through postMessage.
  3. Optional tool entry: returns _meta['xpertai/visualization'] with type: 'xpert.extension_view' for tool-triggered scenarios.
The iframe is intentionally not trusted as an API client. It does not receive:
  • access token
  • API base URL
  • assistantId
  • hostId
  • hostType
  • permission information
The request path is:
Authentication and authorization happen in data-xpert and xpert-pro:
  • data-xpert Web attaches the current user’s OIDC token through authenticatedFetch.
  • data-xpert API verifies the current user and resolves assistantCode to the effective assistant.
  • data-xpert API always forwards to hostType=agent and hostId=<assistant.assistantId>.
  • xpert-pro checks view host access, manifest visibility, and action permissions before invoking the provider.

Define Stable Keys

Use stable keys because they are part of the contract between the view host, Workbench canvas, optional tool result, and provider.
The public view key is:

Choose a Trigger Mode

remote_component can enter the host UI in two ways:
  • Slot-listed view: the host calls GET /api/view-hosts/:hostType/:hostId/slots/:slot/views, receives the view manifest, and renders the remote component for that slot.
  • Tool-triggered view: the tool result carries _meta['xpertai/visualization'], and the host opens the view only after that tool is used.
Use a slot-listed view when the plugin should appear as a regular extension entry for a host page. Use a tool-triggered view when the UI should appear only as the result of a specific tool call, such as “open metric management”.

Optional: Return a Tool-Triggered View

The tool should only open the view. It should not return the full page data.
Do not put host identity, API URLs, tokens, or permissions in the tool result. The data-xpert backend derives the effective assistant host from the current user session.

Provide a Remote Component Manifest

Register a ViewExtensionProvider and return a remote_component + react + iframe manifest from the agent.workbench.main slot.
Use action-level permissions when mutations require stronger permissions than reading the view.

Return the Iframe HTML Entry

The provider returns a single HTML document for the iframe. Use renderRemoteReactIframeHtml() from @xpert-ai/plugin-sdk so all plugins share the same shell, reset, theme variables, and .xui-* UI classes.
The entry value is a provider-local key, not a browser URL. The ViewExtension API rejects unsafe values such as absolute URLs, .., and backslashes.

Implement the Remote Bridge Client

The iframe page sends requests to the parent window and waits for matching requestId responses.
The Workbench host only accepts messages from the iframe contentWindow and checks the instanceId.

Example: Load the Metric List

The remote page does not call fetch. It asks the host for view data:
The host turns that into:
data-xpert API resolves the assistant and forwards to xpert-pro:
The provider handles the query:
The result is sent back to the iframe as:

Example: Save One Metric

Create and edit can share one form. The remote page submits an action request:
The host turns the action into:
The provider performs the mutation:
Mutation actions should return refresh: true on success so the host can invalidate cache and the remote page can reload the current query.

Parameter Options

Use requestParameterOptions for select boxes and dependent fields.
Provider implementation:

Styling

Remote components should use the shared .xui-* classes provided by renderRemoteReactIframeHtml():
  • .xui-app
  • .xui-toolbar
  • .xui-control
  • .xui-input
  • .xui-button
  • .xui-button-primary
  • .xui-table
  • .xui-modal
  • .xui-notice
The host sends init.theme.tokens, and the helper maps them to --xui-* CSS variables. Plugin CSS should only add business layout and should not redefine the base control visuals.

Build Assets

If the remote script is stored under the plugin source directory, make sure the package build copies it to the production output.

Test Checklist

Before shipping, verify:
  • the tool returns a valid xpert.extension_view payload
  • the public view key matches <providerKey>__<manifestKey>
  • the manifest returns remote_component + react + iframe
  • getRemoteComponentEntry returns HTML without token, API URL, assistantId, or hostId
  • list loading uses requestData
  • saving uses executeAction
  • parameter options work for both standalone and dependent fields
  • unauthorized users cannot access the view host
  • mutation actions have stricter permissions when needed
  • the iframe works with sandbox="allow-scripts" and no direct network credentials