Skip to main content
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

TypePayloadDescription
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

TypePayloadDescription
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:
ParameterValueDescription
IDENTITY_TOKENJWT stringSets the initial identity token for BYOI
HIDE_LOGIN"true"Hides the Thesys login UI
appRenderContextTRAY_EMBED_WIDGET | FULLSCREEN_EMBED_WIDGET | CHATBAR_EMBED_WIDGETTells 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>