All docs

Host embed

Directory: sdk/host-embed

Source docs/en/site/sdk-host-embed.md

Directory: sdk/host-embed Who this is for: third parties who put a Cadau embed assistant into their own business system. This folder is a complete handover pack.

Handover: this directory (sdk/host-embed/) is the main doc pack for third-party integration (overview, contract, website integration, knowledge writing, HR walkthrough, legacy-host enhancement). Give this folder to the integrating team and they can start. Runnable full-stack examples and some mechanism source-of-truth still live elsewhere in the repo (see the links below); those links break if you copy only this folder.

Audience: teams embedding a Cadau conversation assistant in their own system (ERP, OA, industry SaaS, and similar) — business admins, backend and frontend developers, and ops.

After this page you can: mount the assistant on a host page, assign different agents per signed-in user, let the assistant guide people to open business pages from the reply, and confirm that signed-in users cannot see each other's conversation history, live support, or tickets.

Technical contract (fields, SSE, error codes): Embed contract (V1.5.12). Copy-paste frontend notes: Website integration. Path A static example: examples/cadau-embed-site/. Path B full-stack example: examples/hr-multi-tenant/ and HR embed example.

Sibling SDKs: appsdk · platform-plugin · agent-capability · this directory. Overview: sdk/README.md.

Note: the script the browser loads is still /embed/mindlink-widget.min.js on the site (HTTP route; independent of this doc folder name).


Documents in this directory

DocumentWhat it is
README.md (this page)Third-party integration overview and rollout path
Embed contractTypeScript types, SSE, error codes, delivered-capability table
Website integrationHost-page init, env vars, in-reply navigation (hand to frontend)
Host knowledge writingHow to write agent knowledge and navigation links
HR embed exampleHR multi-tenant example: APIs, tables, config
Host LLM serviceHost backend asks a chosen agent to answer (instead of calling a model directly)
Host agent run and data scopeLegacy-host user model, workspace split, data-connection row/column policy
Generate predefined queries from host codeGenerate query JSON from host lists/modules and import into Cadau (in-repo; not part of this folder handover)

1. What you get

On your business pages:

  • A conversation assistant in the bottom-right corner (or inline), talking to a Cadau My agent you already configured;
  • Conversation goes through the Cadau server, so you can gate access, audit, and revoke;
  • The assistant can put clickable navigation links in replies; one click opens the matching page in your system with filters (for example “pending orders” or “this employee’s file”);
  • When the user says “open such-and-such page for me”, the widget can run the first registered navigation automatically after the reply finishes (you can turn this off; see §8.3).
  • (Optional) The host backend can also ask a chosen agent to answer (approval summaries, suggest jobs by department, and similar — the user need not see the widget). See Host LLM service.

Cadau does not own: your sign-in users, business permissions, or business database. Who the user is and which menus they see is still the host system’s job.


2. Who does what

flowchart LR
  subgraph ML["Cadau (agent provider)"]
    UA["Configure agents and knowledge"]
    ET["Issue embed access tokens"]
    CHAT["Conversation and retrieval"]
  end

  subgraph Host["Third-party host (your system)"]
    ADM["Register agents, assign users"]
    BFF["Backend mints tokens"]
    UI["Business page + conversation widget"]
  end

  ADM --> BFF
  BFF -->|"integration account"| ET
  UI -->|"short-lived token"| CHAT
  UA --> CHAT
RoleOwnsDoes not own
Cadau adminCreate agents, mount knowledge documents, agree on an app id, provide public URLs, (production) prepare a dedicated integration accountHost business users, host menu permissions
Host adminIn the host admin UI, register the agent IDs to connect, and assign assistants and operation scopes by signed-in userClick “generate token” in Cadau for every end user
Host developerEmbed-session API, mount the widget, navigation whitelist, network proxyPut Cadau passwords or long-lived tokens in the browser
End userTalk to the assistant on the business pageSign in to the Cadau main site (not needed for embed)

3. Which of the two paths to use

A: public site supportB: host business system
Typical caseOfficial site / landing-page support assistantAssistant inside ERP, OA, or industry SaaS
Host configCadau site URL, agent ID, website-embed tokenRegister/assign + backend mint + must pass the signed-in user (host_actor)
Host backend needed?NoYes (at least an embed-session style API)
Different agent per personUsually one config for the whole siteYes (assign by signed-in user)
Click “generate token” in Cadau?Yes (token can be short- or long-lived; can be revoked)Production: backend mints; UI generate is mostly for local testing
Live supportWidget “Live support” (must be on and someone on duty) and “Submit a ticket”Same widget; do not build your own support desk. Cadau uses seats in this workspace or a support team — see HR embed example §10.4
Who can see conversations / live support / ticketsWebsite visitors in the same browser (not signed in)The current signed-in user (must pass host_actor); A cannot see B’s
Cadau workspaceDecided by the embed token (usually one agent for the site)This phase: the whole host shares one workspace. One workspace per tenant is Host agent run and data scope §0.3 — not built yet

Recommendation:

Minting (B): the host backend uses a Cadau integration account to call POST /api/v1/user-agents/{agentId}/embed-token, then hands the short-lived embed token to the browser. End users do not sign in to the Cadau main site.


4. Cadau-side prep (agent owner)

Before you change the host, finish this table in Cadau (align with the host side first if needed):

StepActionOutput
1Sign in to Cadau, enter the target workspaceWorkspace ID
2My agents → create or pick an assistant, mount knowledge documents (business notes, list of pages that can be opened)Agent ID (UUID)
3Agree with the host on app id app_id (for example your-corp-hr, mindlink-embed)Globally unique string; distinguishes integrators
4(Path B) Prepare a dedicated Cadau integration account (email or phone + password)Store on the server only
5Add the integration account to the agent’s workspace (it need not own the agent)Can switch into that workspace before minting
6Confirm public URLs: widget script, API prefixSee the table below
ItemTypical path
Widget scripthttps://<your Cadau host>/embed/mindlink-widget.min.js
API prefixhttps://<your Cadau host>/api/v1

Path B does not need you to click “generate token” in Cadau for every host user. The host backend mints with the same API as the UI button.

(Path A required) On that assistant, Manage → Website embed generate a token. The page only needs site URL + agent ID + token (no workspace ID). For widget “Live support” and “Submit a ticket”, turn them on under the same agent’s Live support, and assign seats in this workspace or authorize a support team (when nobody is on duty, only submit-ticket remains). Full copy can be taken from Copy website integration notes on that page.


5. Host side: what admins do

In your admin UI (or ops scripts):

5.1 Register agents to connect

Create one registration row per Cadau agent you will connect. Store the agent ID only, not the embed token:

FieldWhat it is
Display nameName admins and users see
Cadau agent IDUUID from §4 step 2
App idSame as Cadau and the mint request; may default from global config
Workspace IDThis phase: same Cadau workspace as MINDLINK_WORKSPACE_ID (the whole host shares one). One workspace per tenant: Host agent run and data scope §0.3 — not built yet

(Optional) generate/analyze agent: when the host backend runs jobs such as “suggest jobs”, point at another agent already configured in Cadau — MINDLINK_GENERATE_USER_AGENT_ID in .env, or pick it on the “embed assistant registry” admin page (overrides the env var). This is not the bottom-right conversation assistant. See Host LLM service §5.1.

5.2 Assign by signed-in user

  • The assignment subject is the host signed-in user (the account behind a phone / employee number), not the employee file id (unless they are the same).
  • For each user choose: which registration row, and which operation scopes (query only, whether create/edit/delete is allowed — host-defined enums).
  • Users with no assignment: the business page does not show the assistant, or the embed-session API returns “no assistant yet”.

HR multi-tenant example: sidebar User managementConnected agents / Configure agent; details in HR embed example §8.


6. Host side: developer checklist

6.1 Data layer (path B)

At least two tables (names are yours):

  1. Registered agents (§5.1 fields)
  2. User–agent assignments (tenant + user → registration row + permission scopes)

6.2 Embed-session API (path B core)

Provide an API like this (path is yours; keep the meaning):

GET /api/v1/.../me/embed-session
Authorization: Bearer <host sign-in token>

Server logic:

  1. Confirm the host user is signed in;
  2. Look up whether they have a valid assignment;
  3. No assignment → return 200, body with available: false and a reason (do not use 404, which browsers treat as a hard error);
  4. Has assignmentsign in to Cadau with the integration account → switch workspace → call

POST /api/v1/user-agents/{agentId}/embed-token body example: { "app_id": "your-app", "ttl_seconds": 3600 };

  1. Return these fields to the frontend (names may match the example):
Response fieldUse
access_tokenWidget auth.token
expires_atWidget auth.expires_at (ISO 8601)
user_agent_idAgent ID
workspace_idWorkspace ID
app_idApp id
host_actorCurrent signed-in user → init.host_actor (path B isolates history / live support / tickets by this person; host data queries use it too)
widget_scriptScript URL the browser loads
api_base_urlAPI prefix the browser uses to call Cadau (prefer same origin as the page; see §6.4)

Integration-account password and Cadau internal URL live only in server env vars. Do not commit them to the frontend repo.

Cadau mint order (server calls, not the browser):

POST /api/v1/auth/login
POST /api/v1/workspaces/{workspaceId}/switch
POST /api/v1/user-agents/{userAgentId}/embed-token

6.3 Mount the widget on the frontend

  1. The user opens a business page that should have the assistant;
  2. (B) Request embed-session with the host sign-in token; or (A) read static config;
  3. Load widget_script dynamically;
  4. Initialize:
<script src="https://<Cadau host>/embed/mindlink-widget.min.js"></script>
<script>
  const widget = window.MindLinkWidget.init({
    app_id: "your-app-id",
    api_base_url: "https://<public API prefix>/api/v1",
    user_agent_id: "<agent UUID>",
    workspace_id: "<workspace UUID>",
    auth: {
      token: "<embed access_token>",
      expires_at: "<ISO 8601>"
    },
    // Path B required: same host_actor as embed-session (isolates history / support / tickets; also host data queries)
    // The widget sends X-Host-External-User-Id automatically; the host page does not set that header
    host_actor: { external_user_id: "…", actor_kind: "employee" },
    theme: "auto",
    position: "bottom-right",
    locale: "zh-CN",
    entry: {
      auto_open: false,
      auto_execute_navigation: true
      // hide_launcher: true skips the corner button; a host button calls widget.open()
    }
  });

  widget.on("action", function (ev) {
    if (ev.type !== "action") return;
    handleHostNavigation(ev.action);
  });
</script>
  1. Before the token expires: mint again on the backend, then widget.updateAuth({ token, expires_at }). When the signed-in user changes, widget.updateHostActor(hostActor) (or init again).

Inline embed: position: "inline" + container: "#your-container-selector". Web Component: see Website integration §4.1.

Reference code (in the Cadau repo; not part of this folder handover):

  • HR example mount: examples/hr-multi-tenant/web/src/mindlinkOrgEmbed.ts
  • HR example navigation: examples/hr-multi-tenant/web/src/mindlinkHostActions.ts

6.4 Network and security

RequirementNotes
Browser access to CadauProduction: prefer a same-origin reverse proxy (for example https://your-host/mindlink-api/v1), or configure CORS
Do not mix hostnamesIn development, do not mix localhost and 127.0.0.1; that often breaks CORS
Tokens not in the repoProduction: never commit long-lived tokens in .env to Git; path A only in dev
Revoke accessThat assistant Manage → Website embed can revoke a registration; after revoke the API returns embed_token_revoked

Server env example (path B):

MINDLINK_API_BASE=https://mindlink.internal/api/v1
MINDLINK_API_BASE_PUBLIC=https://your-host.com/mindlink-api/v1
MINDLINK_WIDGET_SCRIPT=https://mindlink.internal/embed/mindlink-widget.min.js
MINDLINK_INTEGRATION_EMAIL=integration@your-corp.com
MINDLINK_INTEGRATION_PHONE=
MINDLINK_INTEGRATION_PASSWORD=<server only>
MINDLINK_APP_ID=your-corp-app
MINDLINK_WORKSPACE_ID=<workspace UUID shared by the whole host>
MINDLINK_GENERATE_USER_AGENT_ID=<optional: generate/analyze agent UUID>

Embed token TTL and whether the widget is inline have code defaults; they need not go in .env. The integration account can sign in to Cadau with email or phone (same as the HR example server/.env).


7. In-reply navigation: let the assistant open business pages

7.1 How it works

  1. In the agent knowledge documents, agree: when a jump is needed, use a Markdown link with protocol mindlink://action/;
  2. The user clicks the link (or the widget fires it when auto-navigation is on) → the host page receives an action event;
  3. The host page whitelists the action name and params, then routes or opens a drawer.

7.2 Link syntax (put this in knowledge documents)

`Open pending orders`
`View org chart`
  • Action name: a business action you register on the host page; prefer page.<module>;
  • Query params: passed through to the host page (status, id, label, and similar); label may be display-only.

7.3 Host-page whitelist (required)

const HOST_ACTIONS = {
  "page.orders": (params) => {
    app.navigate("/orders", { status: params.status || "" });
  },
  "page.org": (params) => {
    app.navigate("/org", { tab: params.tab || "tree" });
  },
};

function executeHostAction(action, params) {
  const fn = HOST_ACTIONS[action];
  if (!fn) {
    app.toast("This navigation is not supported yet");
    return;
  }
  fn(params);
}

Do not run unsafe protocols such as javascript:. Unknown actions should say “not supported yet”.

7.4 Auto-navigation

entry.auto_execute_navigation defaults to true: when the user clearly says “open / jump to…”, after the streamed reply ends the widget automatically runs the first host-executable mindlink://action/ link in the body (same filter as clicks). To require a manual click, set it to false.

Knowledge documents must say: when the user asks to open a page, put 1–3 registered links at the end of the reply, and the first host-executable link must be the most relevant target.

Writing spec: Host knowledge writing.


8. Recommended rollout order

PhaseGoalFocus
1. Prove the widget (1–2 days)Any page can conversePath A or HR example smoke:embed; confirm script and API are reachable
2. BFF + assignmentDifferent assistants per userTables, embed-session, admin UI, frontend fetches session then inits
3. Legacy-host enhancement (optional)Backend asks an agent to answer; row/column isolation on the business DBSee Host LLM service, Host agent run and data scope
4. ProductionOperable and auditableDedicated integration account, short TTL, HTTPS, knowledge documents, §10 acceptance

8.1 Automated smoke (HR example)

A smoke test is a scripted minimum integration check in real API order: no browser, fail fast on any step. Use it after config changes or a release to confirm “we can even start testing”.

In examples/hr-multi-tenant/web (Cadau :8080 and HR backend :18089 already running, server/.env has MINDLINK_*):

CommandWhat it checks
npm run smoke:embedEmbed path: Cadau widget script → HR sign-in → embed-session → use the embed token against Cadau conversation/chat
npm run smoke:host-agentLegacy-host enhancement: compile mindlink-access-policy, embed-session has the right host_actor (admin/manager/employee), agent-run conversation isolation

Not a substitute for full acceptance: SQLite data connections, writing access policy, and UI still need a manual pass (HR example: examples/hr-multi-tenant/docs/ACCEPTANCE_HOST_LEGACY.md in the repo).

8.2 Local HR example

# See examples/hr-multi-tenant/README.md
cd examples/hr-multi-tenant/web
npm run setup:mindlink    # registers the integration account and writes ../server/.env
cd ../server && go run ./cmd/hrms-server   # separate terminal
cd ../web && npm run dev
# Browser http://localhost:5180 ; demo login 13800138000 / Demo-HR-2026
npm run smoke:embed         # optional: embed smoke
npm run smoke:host-agent    # optional: legacy-host enhancement smoke

Register an existing Cadau agent into the HR example:

cd examples/hr-multi-tenant/web
npm run link:mindlink-agent -- <MindLink agent UUID>

Note: link:mindlink-agent reads/writes local SQLite backend/mindlink.db by default. If Cadau’s main DB is Postgres (common in local development), invite the integration account into the workspace in the Cadau UI, and check mindlink_workspace_id on the registration row; or re-run setup:mindlink.


9. Observability: how the agent owner sees embed conversations

Embed conversations are stored under the Cadau identity used to mint, and do not appear in that identity’s personal Messages list.

The agent owner on the Cadau main site:

  1. My agents → Run history;
  2. Pick the assistant on the left;
  3. Source: Embed (filter by app id);
  4. Open a conversation read-only.

From the agent Manage → Overview you can click View run history to jump to that assistant’s embed records.


10. Integration and acceptance checklist

Cadau

  • [ ] Agent created, knowledge documents mounted (including the list of pages that can be opened)
  • [ ] app_id matches the host
  • [ ] B: integration account can sign in, is in the agent’s workspace, and can mint
  • [ ] Workspace ID on the registration row matches the agent’s real workspace (this phase: the whole host shares one Cadau workspace)
  • [ ] (Optional) that agent has Live support on (seats in this workspace or an authorized support team); support covering this workspace is on duty; the widget shows “Live support / Submit a ticket”

Host backend

  • [ ] Register and assign APIs work
  • [ ] Assigned users: embed-session returns available: true and access_token
  • [ ] Unassigned users: available: false (HTTP 200)
  • [ ] Integration password is not in the frontend or a public repo

Host frontend

  • [ ] After sign-in the assistant appears and can stream a conversation
  • [ ] When different users are assigned different agents, conversation identity is correct (B)
  • [ ] (B) init received host_actor; two signed-in users cannot see each other’s history, live support, or tickets
  • [ ] (A) two website visitors cannot see each other’s history, live support, or tickets (a new browser or cleared site data is a new visitor)
  • [ ] Two visitors can ask at the same time and each get a reply; when overloaded the widget says “Too many people talking right now. Try again in a moment.”
  • [ ] Before the token expires, updateAuth or re-entering the page can mint again
  • [ ] (Optional) navigation links in replies jump correctly; auto-navigation matches expectations
  • [ ] Unknown navigation has a friendly message

Legacy-host enhancement (if you connect Host Agent Run / business-DB queries)

  • [ ] Host BFF sends a complete host_actor on embed-session / agent-run
  • [ ] Workspace data connection is configured and access_policy_json is written
  • [ ] Employee self-service sees only their own rows; manager/admin scope matches expectations; conversations do not leak across users
  • [ ] (Optional) npm run smoke:host-agent passes

Security and ops

  • [ ] Production is mainly B; A is dev-only
  • [ ] Cadau API is same-origin proxied or CORS is compliant
  • [ ] Integration-account rotation and token revoke are documented
  • [ ] Production uses a self-created integration account, not the HR example demo email

11. FAQ

SymptomCheck
Widget does not appearNo assignment, embed-session 503, network/CORS, api_base_url not same origin as the page
Embed-session 502Integration account not in the workspace; wrong agent ID; app_id mismatch; wrong workspace ID
Assistant opens but conversation failsuser_agent_id / app_id / workspace differ from mint time; token expired
embed_token_revokedCadau revoked the registration; mint again
unauthorizedToken invalid or expired; call updateAuth or fetch embed-session again
A/B behavior differsAlign on the same agent ID and knowledge documents
After switching accounts you still see the previous user’s history / support / ticketsPath B must pass the current signed-in user into init.host_actor; after switch, updateHostActor or init again. Unsigned website visitors in the same browser are isolated by browser, not by account
Embed conversations are missing from Cadau MessagesExpected; the owner looks under Run history → Embed
Do I click “generate token” in Cadau for every agent?No (path B); register the ID, mint at runtime
Does the host backend still need its own model connection?No. Ask a chosen agent to answer; see Host LLM service

12. Document index (this directory)

ResourceWhat it is
Website integrationHost-page init, env vars, navigation examples (hand to frontend)
Embed contractTypeScript types, SSE, error codes, delivered-capability table
Host knowledge writingKnowledge documents and in-reply navigation (including mindlink://action/)
HR embed exampleHR example APIs, tables, config
Host LLM serviceHost backend asks a chosen agent to answer
Host agent run and data scopeLegacy-host user model, new-host checklist, data-connection policy
Generate predefined queries from host codeGenerate query JSON from host code and import (in-repo)
Cadau UIThat assistant Manage → Website embed (generate notes, token register and revoke)

13. Maintenance

ItemValue
Doc typeThird-party host integration overview
Aligned contractSDK契约.md V1.5.12
Reference exampleexamples/hr-multi-tenant (in-repo; not part of this folder handover)
Updated2026-08-17 (docs aligned with implementation: contract version, relative paths, concurrent-reply-limit semantics, next-step chips)