Skip to main content

App messaging

AI Apps can exchange information with the application they run inside. This lets an app react to what a user does elsewhere, for example opening a panel in an ERP system such as Infor M3, and send an answer back, for example a value to fill into a field.


What it is and why it helps​

Vince Platform can run inside another application, such as a company portal like Infor OS. In that setup the app you built in App Builder sits inside Vince Platform, which sits inside that application (the host).

With app messaging, the surrounding application and your app can send each other short messages:

  • Down to the app: the host tells the app what the user is doing, for example which M3 program, panel and field they are on.
  • Up to the host: the app answers with what should happen, such as setting a field to a value the app has worked out.

This makes it possible to build helpers that sit next to the screen the user works in, such as an M3 panel, look things up, apply your own rules, and fill in the result, without the user copying anything by hand.

The host, for example a script in Infor OS on an M3 panel, sends an m3Trigger message through Vince Platform to the app. The app works out an answer and sends an m3Response message back through Vince Platform to the host, which fills in the requested fields.

The examples on this page use Infor OS and M3, because that is a common setup. The same messaging works with any application that embeds Vince Platform: use custom events for other systems. More ways for apps and their surroundings to work together are planned.


Key terms​

TermWhat it means
HostThe application around Vince Platform that the app runs inside, for example Infor OS
EventA named message, such as m3Trigger. Both sides must use the exact same name
Message (payload)The information that travels with an event, such as the program, panel and field. It is plain data: text, numbers, yes/no values, lists
m3TriggerA ready-made event from the host to the app. Says which M3 program and panel the user is on, and optionally a field and its value
m3ResponseA ready-made event from the app to the host. Repeats the program, panel, field and value, and adds response actions
Response actionAn instruction in an m3Response. Today the supported action is SET: put this value into this field
appReadyA custom event the app sends when it has loaded, so the host knows it can start sending messages. It has no message. This is a recommended convention, not a built-in event
Custom eventAny other event name you and the host agree on, such as customerSelected. Custom events work with any host and any system, not only M3

The shape of the ready-made events​

EventDirectionContents
m3TriggerHost to appprogram and panel (required), field and val (optional)
m3ResponseApp to hostprogram and panel, optional field and val, and responseActions: a list of { type: "SET", key, value }

For these two events the platform recognises the shape and tells the app so. For any other event name the message is passed on as it is and the app has to check it, see Good to know.


Build it with App Builder​

You do not write the app code yourself. Describe the events in a prompt and App Builder generates the code. Copy a prompt below and adapt the names.

tip

Three things make these prompts work: name each event exactly as the host spells it, list the fields in the message, and say what the app should do when the message arrives. See Prompting for general habits.

A basic two-way app​

Build an app that communicates using three host events:
1. appReady - when the app loads, publish this event with no payload to signal that it is ready.
2. m3Trigger (incoming) - subscribe to this event. Its payload is { program, panel, field, val }.
3. m3Response (outgoing) - after receiving an m3Trigger, publish a response that repeats the program, panel, field and val from the trigger, plus responseActions: [{ type: "SET", key, value }]. Decide the key and value from the app's own logic, never copy them from the trigger.
Show the latest m3Trigger it received on screen so I can see what arrives.

Look up item details​

Build an app that listens for the host event m3Trigger. Publish appReady with no payload when the app loads. When m3Trigger arrives with program MMS200, take the item number from the val field, call the workflow resource 'get-item' with it, and show the item name, status and warehouse on screen. Show a friendly message while loading and if the item is not found.

Tell the host what the user picked​

Build a customer list from the resource 'customer_table' showing customer number, name and country. When the user clicks a row, publish a custom host event named customerSelected with the payload { customerId } where customerId is the customer number of that row. Highlight the selected row.

Only work inside Infor OS​

Build an app that checks which host it is running in. When the host is Infor OS, subscribe to m3Trigger and show the program, panel and value it receives. When it is not running inside Infor OS, show a friendly message that says "Open this app from Infor OS to use it" and do not show anything else.

For the script author​

This section is for the person who writes the script on the host side, for example an H5 script in M3. Business users can skip it.

The messages always come in the same order. The app first says it is ready, then the host sends what the user did, and the app answers.

First the app sends appReady through Vince Platform to the host. Then the user opens a screen in the host, and the host sends m3Trigger through Vince Platform to the app. The app works out an answer and sends m3Response through Vince Platform back to the host, which fills in the fields. The host and the app never talk directly.

Host side: send a message to the app​

The host sends a message to the Vince Platform frame it embeds. Read the address of Vince Platform from the frame itself instead of typing it in, because it differs between tenants. Never use '*' as the target address.

// Find the frame that shows Vince Platform (use the id of your own frame)
const vinceFrame = document.getElementById('vince-live');
// The address Vince Platform runs on, taken from the frame
const vinceOrigin = new URL(vinceFrame.src).origin;

vinceFrame.contentWindow.postMessage({
type: 'vinceHostEvent',
event: 'm3Trigger',
data: { program: 'CRS610', panel: 'E', field: 'CUNO', val: 'C-1001' }
}, vinceOrigin);

Host side: receive the app's answer​

window.addEventListener('message', (event) => {
// Only accept messages from Vince Platform
if (event.origin !== vinceOrigin) { return; }
if (event.data?.type !== 'vinceHostPublish') { return; }

const { event: eventName, data } = event.data;
if (eventName === 'appReady') {
sendTrigger(); // the app has loaded: now send the first m3Trigger (your own function)
}
if (eventName === 'm3Response') {
for (const action of data.responseActions ?? []) {
if (action.type === 'SET') {
setField(action.key, action.value); // your own function
}
}
}
});

The host waits for the app's appReady message before it sends the first m3Trigger, see Good to know.

App side: what App Builder generates​

You normally never write this yourself. It is shown so you can recognise the code. The app talks to the host through VinceApiBridge.

// Tell the host the app has loaded
VinceApiBridge.publishToHost('appReady');

// Listen for m3Trigger. The function returned by onHostEvent stops listening.
const stopListening = VinceApiBridge.onHostEvent('m3Trigger', (data, envelope) => {
// envelope.host.id is 'infor-os' inside Infor OS, otherwise 'unknown'
// envelope.hasContract is true when the message has the expected shape
if (!envelope.hasContract) { return; }

// Send the answer. The actions come from the app's own logic.
VinceApiBridge.publishToHost('m3Response', {
program: data.program,
panel: data.panel,
field: data.field,
val: data.val,
responseActions: [{ type: 'SET', key: 'ITNO', value: 'ABC123' }]
});
});

// A custom event sent up to the host
VinceApiBridge.publishToHost('customerSelected', { customerId: 'C-1001' });

// A custom event received from the host: check the data before using it
VinceApiBridge.onHostEvent('customerSelected', (data) => {
if (typeof data?.customerId !== 'string') { return; }
showCustomer(data.customerId); // the app's own function
});

Good to know​

  • Wait for appReady. A message sent before the app has loaded is lost. Have the app publish appReady when it loads and let the host send its first message only after that.
  • It only works when embedded. Messages travel only when the app runs inside a host. In the App Builder preview, or when the app is opened on its own, nothing arrives and anything the app sends is dropped.
  • Keep messages small and plain. A message can be at most 64 KB and should contain plain data only: text, numbers, yes/no values, lists and simple objects.
  • Rebuild older apps. Apps built before 22 September 2026 need to be rebuilt and republished to get the latest messaging.
  • Custom events are not checked. Only m3Trigger and m3Response have a defined shape. For any other event, make the app check the data before it uses it. In App Builder, say so in the prompt, for example "ignore the message if customerId is missing".
  • Troubleshooting. Open the App Bridge logs in the editor to see which messages arrive and which are dropped. See Troubleshooting.

Further reading​