Skip to main content
After this page you understand how a native app embeds an agent: a WebView plus a message protocol, with nothing to install.
The native app and the agent widget across the WebView boundary, with app to widget messages and widget to app messages

Architecture

There is no native library to add to your app. Your app opens a WebView pointing at the agent’s widget URL.
The DistributeMobile App panel generates this URL with your region already set. Without region, the widget uses the default region, which loads the wrong backend for an organization in any other region. An unknown region value stops the widget from loading. The app and the widget then exchange JSON messages. Every message is an object with a type field prefixed tars:, so foreign messages are ignored. The full field-level contract is in the bridge events reference.

How each direction travels

App to widget messages are posted into the page with window.postMessage, which every platform snippet does through its script injection call. Widget to app messages take a different path. The widget sends them with window.parent.postMessage, the same call it uses inside the web embed iframe. In a top-level WebView window.parent is the page itself, so the message stays in the page. Your app must listen for message on window and relay every tars:-prefixed message to its own native channel.

Enabling the bridge

The bridge is gated per agent. Open DistributeMobile App on the agent and turn on Enable Bridge Events. The toggle also reveals ready-made snippets for React Native, Swift/UIKit, and Kotlin/Android, plus a bridge events reference. With the toggle on, gambit editors gain bridge event configuration.

The capabilities handshake

The widget posts tars:ready twice, and the two messages mean different things. The widget page posts a bare tars:ready as soon as it mounts, with no other fields. That message only says the page is loaded and listening. The app starts the session by posting tars:init, carrying its platform, chrome preferences, and optional end user data. The bridge answers with a second tars:ready, declaring its protocol version and capabilities: navigate, data, and close. Only the first tars:init takes effect, later ones are ignored. The widget answers only a tars:init that arrives after it mounts. An init posted before that is dropped and never answered. Post tars:init when the bare tars:ready arrives, or resend it until a tars:ready with capabilities comes back. A repeat init after the handshake is ignored, so a resend is safe. After the handshake, the widget emits events as the conversation reaches gambits with configured bridge events, and the app can inject data or send commands at any time.

Chrome control

tars:init can hide parts of the widget chrome so the conversation sits flush inside a native screen. showHeader and showCloseButton both default to true.

What the bridge is for

The bridge turns a conversation into a native flow step. A flow can hand captured variables to the app, ask the app to navigate to a native route, or close the chat screen. The app can push the signed-in end user’s data into the conversation instead of asking again.