All docs

Host agent run and data scope

For legacy / existing business systems (host enhancement; see product spec §4.2.4). Runnable example and API walkthrough: examples/hr-multi-tenant/docs/HOST_LEGACY_INTEGRATION.md i

Source docs/en/site/sdk-host-agent-run.md

For legacy / existing business systems (host enhancement; see product spec §4.2.4). Runnable example and API walkthrough: examples/hr-multi-tenant/docs/HOST_LEGACY_INTEGRATION.md in the repo.


0. Legacy-host user model (three kinds of account)

A common question when connecting a legacy host: “Do we create a Cadau account for every business user?” — No. Keep three identities distinct:

IdentityWhere it livesHow manyUse
Cadau integration accountCadauOne set per legacy-host deploy (or one per customer, per ops policy)Host backend mints embed-token, calls Host Agent Run; password only in MINDLINK_* env vars
Legacy-host signed-in userHost business DBReal headcountAdmin, manager, employee self-service, and similar; they sign in on the host page and do not register on the Cadau main site
Cadau end userNot neededConversation and query identity is the host_actor on each request

Mapping (user view):

Legacy-host conceptCadau (currently delivered)
One host system (may contain several business tenants)One workspace
Assistants used by roleA few template agents (for example admin assistant, manager assistant, employee self-service)
Each conversation / server-side runCarries host_actor (legacy-host user identity); history, live support, tickets, and data queries are isolated by this person

Do not clone a Cadau agent per signed-in user. Person-to-person isolation is host_actor (history / live support / tickets) plus row/column policy on the workspace data connection (queries can also narrow by tenant key). “One Cadau workspace per host tenant” is §0.3 — not built in this phase.

0.1 Two kinds of legacy-host signed-in user

Typeactor_kindTypical scenehost_actor essentials
Business userbusinessAdmin, HR, manager running org / other peopleroles; a manager may include managed departments and subordinate employee ids
Employee useremployeeLook up self onlyMust include employee_id (bound to this tenant’s employee file)

host_actor fields (aligned with backend/internal/datasource/host_actor.go):

FieldRequiredMeaning
external_user_idYesHost signed-in user id; without it identity is invalid
actor_kindNo (can be inferred)business or employee. If omitted: employee when employee_id is present, otherwise business
employee_idRequired when employeeEmployee file id in this tenant
display_nameNoDisplay name
tenant_external_idNoHost tenant id (often used in query policy)
emp_noNoEmployee number
rolesNoFor example tenant_admin, manager, employee
managed_org_unit_idsNoManaged department id list
managed_employee_idsNoSubordinate employee id list
org_unit_id / org_unit_nameNoOwn department

Data-connection policy placeholders: {{host_actor.external_user_id}}, {{host_actor.actor_kind}}, {{host_actor.display_name}}, {{host_actor.tenant_external_id}}, {{host_actor.employee_id}}, {{host_actor.emp_no}}, {{host_actor.org_unit_id}}, {{host_actor.org_unit_name}}, {{host_actor.managed_org_unit_ids}}, {{host_actor.managed_employee_ids}} (the last two are comma-joined).

Silent provisioning: when the legacy host creates a business user or turns on employee self-service, write “user → template agent” assignment by role. If there is still no assignment the first time the assistant opens, the host BFF can backfill a default by role (HR example EnsureDefaultAgentAssignment).

0.2 Where the integration account comes from

SceneWhat to do
Local testing (HR example)In the web directory, npm run setup:mindlink: the script calls Cadau POST /auth/register for hr-embed-demo@mindlink.local (or signs in if it exists), probes workspace and agent IDs, writes MINDLINK_* into server/.env
Production / new legacy hostCreate a dedicated integration account by hand in Cadau (email or phone + strong password), invite it into the matching workspace; do not use the example demo email

The integration account and a legacy-host demo signed-in user (for example HR example 13800138000) are not the same person: the former only mints on the server; the latter is the business user who signs in on the page.

0.3 Path B workspaces: two ways (this phase only does the first)

Path B can split by how Cadau workspaces are drawn:

Way 1: host shares one workspace (this phase)Way 2: one workspace per tenant (later, if needed)
How to configureThe whole host system (including several business tenants) maps to one Cadau workspace; registration and MINDLINK_WORKSPACE_ID point at the same workspaceEach isolated host tenant maps to one Cadau workspace; the registration table stores different workspace IDs per tenant
Person to personhost_actor: history / live support / tickets isolated by signed-in userSame as left
Tenant to tenantQueries can narrow by tenant key in data-connection policy; support desk, seats, knowledge, standards/assets are still one copy per workspace. If one Cadau support group should serve several customer workspaces, use a support team (authorize support rights only; members need not join each customer workspace) — do not split workspaces the way 2 doesSupport queues and knowledge split naturally by workspace; you can still use a support team to take work across workspaces without adding members to every customer workspace
This phaseOnly this way (the HR example is this)Auto-create workspace on tenant open, copy assistants per tenant, and similar are not built; the notes below are explanation only

Way 2 (reserved; not this phase’s checklist)

If you do it later: each time you open a host tenant, create a Cadau workspace → invite the same (or per-customer) integration account → in that workspace create/copy assistants, knowledge, seats, data connections → host registration table stores that workspace ID. Mint switches to the workspace on the registration row, instead of every tenant falling back to one env var. Conversations and tickets in the old workspace do not migrate automatically.

Until you actually need it, do not rebuild production around way 2, and do not write way 2 as a required integration step.


1. New legacy-host connection checklist

When connecting a new legacy host or a new customer tenant, check in this order (concept layer; HR example script paths: HR embed example §7.3).

Cadau side (this phase: one workspace for the whole host)

  • [ ] Create a workspace (or confirm an existing one)
  • [ ] Prepare template agents in the workspace (admin / manager / employee self-service, or one shared)
  • [ ] Create a dedicated integration account and add it to that workspace (need not own the agents)
  • [ ] Configure a data connection (pointing at the legacy-host business DB, for example SQLite / MySQL / Postgres)
  • [ ] Write access_policy_json (you may compile a draft from host GET …/mindlink-access-policy then PUT it on the data connection)

Legacy-host side

  • [ ] Server env: MINDLINK_API_BASE, MINDLINK_INTEGRATION_*, MINDLINK_WORKSPACE_ID, MINDLINK_APP_ID; generate/analyze separately via MINDLINK_GENERATE_USER_AGENT_ID (or host settings). HR example local demo only uses HRMS_SEED_MINDLINK_USER_AGENT_ID (backfills assignment for the demo account at startup; not runtime widget config)
  • [ ] Host DB registers template agents (Cadau workspace ID + agent ID + app_id)
  • [ ] BFF: GET …/me/embed-session and POST …/me/agent-run both carry a complete host_actor
  • [ ] Legacy-host account-open flow stays the same: new users still register/import on the host; assign template agents by role

Automated and manual acceptance

  • [ ] npm run smoke:embed — embed path (see [README.md](/docs/sdk-host-embed) §8.1)
  • [ ] npm run smoke:host-agenthost_actor, policy compile, conversation isolation (legacy-host enhancement)
  • [ ] Manual: employees see only self, manager subordinates and column trimming; two accounts cannot see each other’s history, live support, or tickets (HR example: ACCEPTANCE_HOST_LEGACY.md in the repo)

2. Host LLM service (chosen agent answers)

Do not have the host backend call a large model directly; ask a chosen agent in the workspace to answer. Full integration (call chain, fields, conversation isolation, checklist): Host LLM service.

Summary: POST /api/v1/host/agent-runs (integration account; required user_agent_id, message, host_actor). Page widget and answer-on-behalf share identity and data policy. HR example wraps everyday Q&A as POST …/me/agent-run; generate jobs use the chosen analyze agent (.env / host settings, fresh: true) — see Host LLM service §5.1.


3. Data connection access_policy_json

Stored on the workspace data connection. Shape overview:

{
  "require_host_actor": true,
  "rules": [
    {
      "when": { "actor_kind": "employee" },
      "queries": {
        "employees_directory": {
          "force_params": {
            "employee_id": "{{host_actor.employee_id}}",
            "tenant_id": "{{host_actor.tenant_external_id}}"
          },
          "allowed_columns": ["id", "emp_no", "full_name", "org_unit_id", "lifecycle_status"]
        }
      },
      "tables": {
        "hr_employees": {
          "row_filter_params": {
            "id": "{{host_actor.employee_id}}",
            "tenant_id": "{{host_actor.tenant_external_id}}"
          },
          "allowed_columns": ["id", "emp_no", "full_name", "org_unit_id", "lifecycle_status"]
        }
      }
    }
  ]
}

Placeholders: see the §0.1 field table. Enforced at: query.run / table.preview / select.run. If there is no host_actor and the policy requires one, queries are refused.