Integration via iframe
iframe has two common integration forms:
- Embed the full ChatBI page directly. This is the fastest way to reuse the complete Q&A experience.
- Load Copilot JS SDK in the parent page, embed a HENGSHI Dashboard in an iframe, and let the parent Copilot take over the assistant capability inside the iframe.
Start with the overview
If you have not yet clarified the boundary between API, JS SDK, and iframe, read Data Agent Integration Overview first.
Option 1: embed the full ChatBI page
This option is suitable when:
- you want the fastest way to launch a usable entry
- your frontend resources are limited and you do not want to build the chat UI yourself
- you accept reusing the complete HENGSHI page
- you do not need to split chat results into multiple modules inside your own page
Minimal example:
<iframe
src="https://your-hengshi-host/copilot"
width="100%"
height="100%"
style="border: 0;">
</iframe>As long as the current browser already has a HENGSHI login session, or you have completed single sign-on integration, the page can display ChatBI directly.
Common URL parameters
Specify the data source
Converse with the chart's data source:
?appId={App ID}&chartId={Chart ID}Converse with a dataset model in a data package:
?dataAppId={Data Package ID}&datasetId={Dataset ID}Converse with multiple data sources:
?dataSources=[{"dataAppId":{Data Package ID1},"datasetId":{Dataset ID1}},{"dataAppId":{Data Package ID2},"datasetId":{Dataset ID2}}]Tip
dataSources needs to be URL encoded first.
Specify the chart theme
?chartTheme={Dashboard Theme ID}Display only specified conversations
?conversationId={conversationID1,conversationID2}&chatUid={uid1,uid2}Authentication
?activeAuth=jwt-param&jwtParam={JWT parameter}Option 2: parent Copilot SDK takes over an iframe Dashboard
Use this option when your own portal page already embeds Copilot through JS SDK Integration, and you also want to embed a HENGSHI Dashboard in the same page.
The effect is:
- the Copilot sidebar is shown only in the parent page, not inside the iframe Dashboard
- assistant entries in the iframe Dashboard, such as opening the assistant, Dashboard interpretation, and chart interpretation, open the parent Copilot
- when Agent needs to read or edit the iframe Dashboard, it uses business actions and business objects proxied from the iframe
- the parent page can use any route and can be cross-origin from HENGSHI. It does not depend on a test route such as
/sdk/
Minimal runnable example
This example assumes:
- the parent page is your own portal page
- Copilot JS SDK is loaded from the HENGSHI service
- the iframe embeds a HENGSHI Dashboard at
/app/{appId}/dashboard/{dashboardId} - the parent Copilot takes over the assistant capability inside the iframe
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Copilot SDK + iframe Dashboard</title>
<script>
window.__hs_sdk_base_url__ = 'https://your-hengshi-host';
</script>
<script src="https://your-hengshi-host/assets/hengshi-copilot@<version>.js"></script>
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
}
#dashboard-frame {
width: 100%;
height: 100%;
border: 0;
}
</style>
</head>
<body>
<div id="copilot-root"></div>
<iframe id="dashboard-frame" title="HENGSHI Dashboard"></iframe>
<script>
const hengshiHost = 'https://your-hengshi-host';
const appId = 43900;
const dashboardId = 2;
const dashboardUrl = new URL(`/app/${appId}/dashboard/${dashboardId}`, hengshiHost);
dashboardUrl.searchParams.set('agentHost', 'parent');
dashboardUrl.searchParams.set('parentOrigin', window.location.origin);
document.getElementById('dashboard-frame').src = dashboardUrl.toString();
const copilot = new window.Copilot(document.getElementById('copilot-root'), {
locale: 'en-US',
draggable: {
enable: true,
bounds: 'window',
minWidth: 440,
minHeight: 440,
position: { x: window.innerWidth - 480, y: 24 },
size: { width: 440, height: window.innerHeight - 48 },
},
});
</script>
</body>
</html>Usually you do not need to manually register the iframe. After the parent page loads hengshi-copilot@<version>.js, the SDK tracks iframes on the page. When the iframe page declares parent hosting through URL parameters, the bridge is established automatically.
iframe URL parameters
| Parameter | Recommended | Description |
|---|---|---|
agentHost=parent | Yes | Lets Agent / Copilot capability inside the iframe be hosted by the parent SDK. |
copilotHost=parent | Compatible | Compatible form of agentHost=parent. Use agentHost=parent for new integrations. |
parentOrigin={parent origin} | Yes | Specifies the allowed parent origin, such as https://portal.example.com. Use origin only, without path, query, or wildcard. |
copilotParentOrigin={parent origin} | Compatible | Compatible form of parentOrigin. |
agentHost=local | Optional | Explicitly lets the iframe page use its own Copilot instead of parent takeover. |
copilotHost=local | Optional | Compatible form of agentHost=local. |
agentBridge=true | Advanced | Explicitly enables the Agent bridge only. It is not the same as full parent Copilot takeover. Do not use it as the default integration choice. |
Recommended URL:
https://your-hengshi-host/app/43900/dashboard/2?agentHost=parent&parentOrigin=https%3A%2F%2Fportal.example.comparentOrigin is used for security validation. After it is configured, the iframe accepts parent messages only from that exact origin. If the value is wrong, the bridge does not fall back to a looser mode.
Behavior after takeover
After parent takeover, users see one Copilot:
- the iframe Dashboard no longer shows its own Copilot sidebar
- assistant entries inside the Dashboard open the parent Copilot
- the actions area in the parent Copilot can show the Dashboard's "Smart Interpretation" action
- chart interpretation sends chart context to the parent Copilot
For Agent, the iframe Dashboard is not part of the parent page DOM. Agent should not operate inside the iframe through parent-page clicks, drags, or route navigation. It should read and modify the Dashboard through business capabilities proxied from the iframe.
If debug logs show tools such as execute_action, inspect_element, read_path, and patch_object accessing the iframe Dashboard, that is expected. They are used to read Dashboard context, inspect chart configuration, and submit dashboard patches.
Cross-origin and security requirements
For cross-origin integration, check these items:
- the iframe
srcpoints to a real HENGSHI page URL, such as/app/{appId}/dashboard/{dashboardId} - the parent page has loaded
hengshi-copilot@<version>.js - the iframe URL includes
agentHost=parent - the iframe URL includes the exact
parentOrigin - the HENGSHI site allows your portal page to embed it in an iframe
- if the iframe uses
sandbox, it must at least allow scripts and same-origin capability, such asallow-scripts allow-same-origin - login session, JWT, or SSO allows both the iframe page and the parent SDK to access HENGSHI APIs
The security boundary is origin, not route path. The parent page can use any route, but its origin must exactly match parentOrigin.
Local debugging Q&A
Q: How do I run a local SDK + iframe Dashboard verification page?
In a local development environment, the usual flow is:
make production
bash ./nginx.sh
brew services reload nginxThen open the local proxy, for example:
http://localhost:8881/If the parent page and HENGSHI site are served separately, a common setup is:
Parent page: http://localhost:8882/
iframe: http://localhost:8881/app/{appId}/dashboard/{dashboardId}?agentHost=parent&parentOrigin=http%3A%2F%2Flocalhost%3A8882/sdk/ is only a local test route. It is not part of the product protocol. In real integrations, the parent page route is decided by your own system.
Q: Why is there no Copilot sidebar inside the iframe?
When the iframe URL uses agentHost=parent, this is expected. The Copilot sidebar is hosted by the parent SDK, and the iframe does not render a duplicate sidebar.
Q: Why does the parent Copilot not show "Smart Interpretation"?
Check these items first:
- whether the parent page has loaded
hengshi-copilot@<version>.js - whether the iframe URL includes
agentHost=parent - whether
parentOriginexactly matches the parent page origin - whether the iframe has loaded the Dashboard page instead of a login page, blank page, or error page
- whether the current user has permission to read the Dashboard and charts
- whether the browser console reports CSP,
X-Frame-Options, or login-session blocking errors
Q: Why can Agent not directly click buttons inside the iframe?
In the parent SDK scenario, Agent's browser window is the parent page, not the inner iframe page. Direct clicks, navigation, or drag operations only operate on the parent page.
The correct path is to let the iframe Dashboard expose business actions and business objects through the bridge. Agent then reads, interprets, or modifies the Dashboard through those capabilities.
Q: Is a 400 or 500 from /api/chat/completions caused by the iframe bridge?
Usually no. The iframe bridge handles context, actions, and message communication between the parent page and iframe. It does not rewrite the chat request body into another JSON format.
Suggested checks:
- 400 with JSON parse error: check whether the request body is valid JSON and whether
content-typeisapplication/json - 401 / 403: check login session, JWT, CSRF, and user permission
- 500 returned by local nginx: check nginx error log first, then confirm
/apiis proxied to the expected backend, such as develop or rc - 500 returned by backend: continue with backend service logs and model configuration
What iframe is not suitable for
- deep customization of the internal chat window UI
- splitting Q&A results into multiple business modules in different page regions
- using only backend capability without reusing the page
- using it as a standard chart protocol output capability
If you need these capabilities, read JS SDK Integration or API Integration.
Summary
If you only need the fastest way to embed the full ChatBI page, iframe /copilot directly.
If the parent page already uses Copilot JS SDK and the iframe embeds a HENGSHI Dashboard, add agentHost=parent to the iframe URL so the parent Copilot takes over the assistant capability inside the iframe.