Skip to main content

@finos/sail-browser-agent

Browser-ready FDC3 Desktop Agent for 2.2 and 3.0 — SailDesktopAgent, versioned DACP handlers, channel and intent state, app directory, and WCP BrowserAppConnection.

Location: packages/sail-browser-agent/

What it does​

  • Implements FDC3 Desktop Agent APIs via DACP for wire versions 2.2 and 3.0 (negotiated per app at WCP1; default advertised max is 3.0)
  • Browser-first: one DesktopAgent per host page, with FDC3 web apps connecting via WCP and per-app MessagePort
  • Keeps platform concerns (layout, workspace, storage, config) out of the core — those belong in @finos/sail-platform

Handler-level tests run under Node.js via Cucumber and Vitest, but the browser is the only supported deployment target.

How to integrate​

SailDesktopAgent is the entry point — construct it, implement AppLauncher, wire host UI through the grouped controllers. The app-connection edge (WCP handshake, per-app MessagePort, routing) is internal to the agent; there is no transport to configure and no lower-level composition path to assemble.

FDC3 Apps Your host FDC3 engine (in-tab)
(external) → contracts + controllers → new SailDesktopAgent()
fdc3.getAgent() launcher · intentResolver (BrowserAppConnection + DA)
channels · apps

Remote or server-hosted Desktop Agent (createWCPClient) is not a supported adoption path on v3. Cross-tab sync and native app transports are deferred as explicit future adapters — see the integrator guide.

Package layout​

packages/sail-browser-agent/src/
├── agent/ # DesktopAgent, SailDesktopAgent, config
├── host-contracts/ # AppLauncher, IntentResolver, ChannelControl, …
├── app-connection/ # BrowserAppConnection, MessagePortTransport, WCP protocol
├── handlers/ # DACP dispatch and request handlers
└── state/ # AgentState selectors and mutators

Documentation map​

DocPurpose
Add your app to SailApp developer onboarding — @finos/fdc3, app directory metadata, contexts and intents
Getting startedAdoption paths — browser-ready agent, host contracts, @finos/fdc3
Integrator guideDeep reference — host contracts, browser-first agent, WCP/DACP detail, heartbeat config
Composition & internalsDiagrams — how edge, DA, and host contracts interact
Engine BDD inventoryCucumber DACP suite in sail-headless-agent (v2/ / v3/)
Conformance harnessFINOS toolbox against sail-one, sail-finance, sail-v2-web

Quick start​

import { SailDesktopAgent } from "@finos/sail-browser-agent"
import type { AppLauncher } from "@finos/sail-browser-agent"

const appLauncher: AppLauncher = {
async launch(request, app) {
const instanceId = request.app?.instanceId ?? crypto.randomUUID()
// Mount iframe with name={instanceId} — required for WCP4 identity
return { appId: app.appId, instanceId }
},
}

const desktopAgent = new SailDesktopAgent({ appLauncher })

const { intentResolver, channels, apps } = desktopAgent
await apps.addDirectory("/apps.json")

intentResolver.onRequest(/* your picker UI */)
channels.onAppChannelChange(/* update channel chrome */)
apps.onConnect(/* tab / tile lifecycle */)

// Auto-started by default — iframe apps can await fdc3.getAgent()

Returns a single SailDesktopAgent with grouped host controllers (intentResolver, channels, apps); the browser edge starts and stops with desktopAgent.start() / desktopAgent.stop().

See the integrator guide for intent resolution, channel chrome, runtime catalog registration, and lifecycle.

Imports​

Everything public comes from the package root — there are no subpath exports.

import { SailDesktopAgent, DEFAULT_FDC3_USER_CHANNELS } from "@finos/sail-browser-agent"
import type { AppLauncher, IntentResolver, DirectoryApp } from "@finos/sail-browser-agent"

Message validation​

Inbound DACP and WCP messages are validated against the FDC3 schemas shipped by @finos/fdc3-schema for the connection's negotiated wire version (2.2 or 3.0).

ModeBehaviour
"off"No validation
"warn" (default)Log the failure, dispatch the message anyway
"strict"Reject the message with an FDC3 MalformedMessage error
const desktopAgent = new SailDesktopAgent({ appLauncher, validation: "strict" })

"warn" is the default because rejecting is a behaviour change — a client library sending a slightly off-spec shape works today, and "strict" would break it. Warn surfaces the problem in logs first so you can decide.