If you’re using the embed widget npm package, you don’t need this page — the widget handles all postMessage communication internally. This protocol is for developers who embed the agent using a direct iframe and want programmatic control.
The Thesys agent iframe communicates with the parent window using the browser’s postMessage API. Messages are plain objects with a type field that identifies the action.
Parent → Iframe
Send messages to the agent by calling postMessage on the iframe’s contentWindow:
const iframe = document.getElementById('thesys-agent');
iframe.contentWindow.postMessage(
{ type: 'THESYS_SEND_MESSAGE', message: 'Hello!', newThread: false },
new URL(iframe.src).origin
);
Always use a specific targetOrigin (e.g. new URL(iframe.src).origin) instead of "*" to prevent leaking data if the iframe navigates to an unexpected URL.
Message Types
| Type | Payload | Description |
|---|
THESYS_SEND_MESSAGE | { message: string, newThread: boolean } | Send a user message to the agent |
THESYS_SET_INPUT | { message: string, newThread: boolean } | Prefill the chat input without sending |
THESYS_IDENTITY_TOKEN_REFRESHED | { identityToken: string } | Provide a fresh identity token after a refresh request |
Iframe → Parent
The agent sends messages to the parent window. Listen for them with addEventListener:
const expectedOrigin = new URL(iframe.src).origin;
window.addEventListener('message', (event) => {
if (event.origin !== expectedOrigin) return;
if (!event.data || typeof event.data.type !== 'string') return;
switch (event.data.type) {
case 'THESYS_WIDGET_CLOSE':
// Agent requested to close
break;
case 'THESYS_WIDGET_OPEN':
// Agent requested to open
break;
case 'THESYS_WIDGET_TOGGLE':
// Agent requested to toggle open/close
break;
case 'THESYS_IDENTITY_TOKEN_REFRESH_NEEDED':
// Identity token expired — fetch a new one and send it back
break;
}
});
Always validate event.origin against the expected iframe origin to prevent unauthorized windows from triggering actions.
Message Types
| Type | Payload | Description |
|---|
THESYS_WIDGET_CLOSE | (none) | The agent is requesting to be closed |
THESYS_WIDGET_OPEN | (none) | The agent is requesting to be opened |
THESYS_WIDGET_TOGGLE | (none) | The agent is requesting to toggle its visibility |
THESYS_IDENTITY_TOKEN_REFRESH_NEEDED | (none) | The identity token has expired; parent should provide a new one |
Identity Token Refresh
When a BYOI identity token expires during an active session, the agent sends THESYS_IDENTITY_TOKEN_REFRESH_NEEDED to the parent. The parent should fetch a new token from its backend and reply with THESYS_IDENTITY_TOKEN_REFRESHED:
const iframe = document.getElementById('thesys-agent');
const agentOrigin = new URL(iframe.src).origin;
window.addEventListener('message', async (event) => {
if (event.origin !== agentOrigin) return;
if (event.data?.type === 'THESYS_IDENTITY_TOKEN_REFRESH_NEEDED') {
try {
const res = await fetch('/api/thesys-token');
const { token } = await res.json();
iframe.contentWindow.postMessage(
{ type: 'THESYS_IDENTITY_TOKEN_REFRESHED', identityToken: token },
agentOrigin
);
} catch (error) {
console.error('Failed to refresh identity token:', error);
}
}
});
If the parent doesn’t respond within 10 seconds, the agent shows an error modal to the user.
URL Parameters
When embedding via a direct iframe, you can configure the agent through URL query parameters:
| Parameter | Value | Description |
|---|
IDENTITY_TOKEN | JWT string | Sets the initial identity token for BYOI |
HIDE_LOGIN | "true" | Hides the Thesys login UI |
appRenderContext | TRAY_EMBED_WIDGET | FULLSCREEN_EMBED_WIDGET | CHATBAR_EMBED_WIDGET | Tells the agent which embed layout context it’s running in |
<iframe
id="thesys-agent"
src="https://console.thesys.dev/app/your-slug?IDENTITY_TOKEN=eyJ...&HIDE_LOGIN=true"
style="width: 100%; height: 600px; border: none;"
></iframe>