Platform plugins
Put specialist systems such as HR, warehouse, compliance, email, and cameras on the app desktop as full web modules.
Source docs/en/site/sdk-platform-plugin.md
Directory: sdk/platform-plugin Who this is for: app-style platform plugins (apps-desktop iframe) — register platform_plugins[], launch_token, knowledge sync, in-plugin assistant, plugin_invoke.
Code packages: go/ (Go), js/ (TypeScript), contracts/, templates/starter/.
Conversational capabilities (call APIs from Messages, do not register platform_plugins) live in
agent-capability. They are not part of this directory’s registration flow.
Related:
- Product specification §4.2.4 (platform plugin module)
- Workspace capability packs (work-assistant internet,
http_request) - Skill composition spec (how conversation calls business APIs)
- host-embed/Embed contract (in-plugin embed assistant)
- How agents use knowledge documents (how knowledge enters conversation)
- Sibling SDKs: appsdk · host-embed · agent-capability · this directory
1. Which to pick (vs agent-capability)
Only apps-desktop iframe plugins use platform_plugins[] + this directory’s code packages. Do not register “face recognition, drawing, call a business API” as apps-desktop plugins by default — those belong in agent-capability.
| | Agent capabilities (agent-capability) | Plugin apps (this directory) | |--|-----------------------------------|------------------------| | User scene | Talk to a work assistant in Messages | Open full web on the apps desktop | | Register platform_plugins | No | Yes | | Docs | agent-capability | This page + sdk/README.md |
1.2 App-style platform plugin (example: org chart)
- Register
platform_plugins[]inmindlink.json(entry_base_url,upstream_url, and similar). - The user opens it from the apps desktop; Cadau issues a
launch_token; the iframe loads your web. - Optional: sync knowledge documents for workspace agents to retrieve; embed an assistant on the plugin page (embed widget).
Examples: plugins/hr/ (official HR + knowledge sync + plugin_invoke); plugins/email/ (email, IMAP/SMTP); plugins/camera/ (cameras, face-recognition attendance, security, recording playback). User notes: help/product-features/platform-hr.md, platform-email.md, platform-camera.md. When a plugin is open, the action assistant on the Cadau shell uses the workspace default app assistant (work assistant); other product modules still use the help assistant.
1.3 UI plus plugin capability from Messages
You can combine these (current implementation). Registering one platform_plugins row does not automatically give you all of them:
| Capability | Path |
|---|---|
| UI and human operations | App-style platform plugin (this SDK) |
| Agents understand plugin background | Plugin knowledge sync → workspace knowledge plugin-{module_id}/ (§7) |
| Step-by-step plugin-domain work from Messages | Plugin repo ships a skill pack → install into the workspace skill center (§7.5); agents in the workspace can recall it by default |
| Agent calls an HTTP API outside the plugin from Messages | agent-capability (skills + internet capability pack) |
Synced plugin knowledge is injected by conversation retrieval. It does not automatically register plugin REST as agent tools, and it does not automatically turn the skills/ directory into skill-center entries — install per §7.5. To “run a face-recognition API” from Messages, you still need a skill + http_request (or MCP later).
1.4 Decision tree
Need a full web UI on the apps desktop?
├─ No → agent-capability: capability service + skills + internet capability pack
└─ Yes → app-style platform plugin: platform_plugins + sdk/platform-plugin/go*
├─ Also need background notes in conversation? → knowledge/ sync (§7)
├─ Also need a procedural how-to? → skills/ shipped → install into skill center (§7.5)
└─ Also need to call an external HTTP API from Messages? → add skills + internet capability pack
2. Who does what (app-style platform plugins)
| Who | Does |
|---|---|
| Cadau | Sign-in, workspace, apps-desktop iframe shell, launch_token, session check, workspace knowledge retrieval, embed assistant script |
| Plugin | Own UI, business APIs, database; Markdown source of truth lives in the plugin repo; sync to Cadau as needed |
| SDK | sdk/README.md — Go/TS packages, API contract, starter skeleton |
Cadau does not provide a full business SDK (for example org-chart CRUD). The plugin builds its own business APIs, keys data by workspace_id, and has no separate sign-in.
An open fill dialog must let the app assistant recognize it and fill it back (§6.2). That is a platform capability, not special to one app.
3. Connection flow
sequenceDiagram participant U as User participant ML as Cadau participant P as Platform plugin U->>ML: Open plugin from apps desktop ML->>ML: POST launch → launch_token ML->>P: iframe entry_url?launch_token=… P->>ML: GET /platform-plugins/session P->>P: Optional SyncKnowledgeFromDir P->>ML: POST /platform-plugins/embed-token P->>ML: Load /embed/mindlink-widget.min.js U->>ML: Talk to the assistant in the plugin (including synced knowledge)
- Register
platform_plugins[]inmindlink.json(module_id,entry_base_url,upstream_url, and similar). - The plugin entry reads
launch_tokenand callsGET /api/v1/platform-plugins/sessionto verify identity. - The plugin syncs
knowledge/*.mdto Cadau (see §5). - If there is a fill dialog: report
plugin_ui_changedand implementfill_open_form(see §6.1). - Optional: issue an embed-token and embed a Cadau assistant on the plugin page.
4. SDK packages
Third-party developer entry: [../../../sdk/README.md](/docs/sdk-overview)
| Package | Path | Use |
|---|---|---|
| Overview + contract + skeleton | sdk/ | Enough to start |
| Go | sdk/platform-plugin/go | Plugin backend: session, knowledge sync, middleware, CSP, fill_open_form |
| TypeScript | sdk/platform-plugin/js (@mindlink/plugin-sdk) | Plugin frontend: API client, iframe session, report/fill draft, mount embed assistant |
| Skeleton | sdk/platform-plugin/templates/starter/ | Copy-and-run minimal plugin |
| API contract | sdk/platform-plugin/contracts/API.md | REST detail |
Example: plugins/hr/ (official HR plugin + knowledge sync + plugin_invoke). The old org-chart example was merged into this plugin. User notes: help/product-features/platform-hr.md; knowledge: plugins/hr/knowledge/.
5. Workspace data namespace (shared Cadau DB)
Official recommendation: plugin business data lives in the same Cadau database, isolated by workspace:
| Backend | Isolation | session field |
|---|---|---|
| PostgreSQL | CREATE SCHEMA ws_<workspace_id> | data_namespace.schema |
| SQLite | {RUNTIME_DIR}/workspaces/{id}/plugin_ns.db | data_namespace.path / dsn |
- Cadau Ensures this idempotently on workspace create and launch/session.
- The plugin reads
data_namespacefrom theGET /platform-plugins/sessionresponse and migrates its own business tables. - The plugin process must reach the same
DATABASE_URL(Postgres) or the SQLite path on the same host (for Docker development, mountRUNTIME_DIRor switch to Postgres).
Third parties may still use a separate DB (row isolation by workspace_id only); that can coexist with the namespace approach.
6. Agents operating the plugin (plugin_invoke)
Every platform plugin should provide:
operations.json(or configureoperations_url): operation name, description,mutates,min_role,dangerous, parameter schema.POST /api/agent/invoke: verify the short-lived plugin_invoke JWT Cadau issued (notlaunch_token), run the business, return JSON.- When there is a fill dialog:
fill_open_form(mutates: false) + iframe reports the current UI (§6.1). Read-only apps with no dialog may omit this.
The help assistant and work assistants can both call the tool plugin_invoke (on the help side, this is the only tool). Writes default to min_role=admin; dangerous=true requires user confirmation then confirm=true. Calls are written to plugin_invoke_audit.
6.1 Recognize the open form (required if you have one)
When the user opens a fill dialog / drawer / draft in the app, the app assistant on the Cadau shell must:
- When asked “what is on screen”, name this form, not only the tab.
- Unless they name another record, natural-language operations default to the current screen (open app, tab, fill dialog). They do not need to name “this form”. Write fields back into the current draft and show them immediately.
formmay be omitted; the host fills the open dialog. - Until the user says “save / create / submit / complete”, do not call create/update operations that write the system immediately.
This is a platform convention, independent of HR. Field-level contract: [contracts/API.md §3.2](/docs/sdk-platform-api).
| Who | Does |
|---|---|
| Plugin UI | On open/close/change draft, postPluginUiChanged (or equivalent mindlink:plugin_ui_changed); listen listenHostPluginFormFill and write back into inputs |
| Plugin invoke | Provide fill_open_form (mutates: false), return { ui_action: "fill_form", form, fields }; may resolve names to ids, but do not write the DB |
| Cadau shell | Puts the current dialog into conversation client_context; after ui_action=fill_form, pushes fields back to the iframe |
| Language | Ready-made symbols |
|---|---|
| TypeScript | postPluginUiChanged, listenHostPluginFormFill, fillOpenFormPassthrough, collectFillFormArgs |
| Go | FillOpenFormPassthrough, CollectFillFormArgs, FillOpenFormResult, InvokeBody |
React reference: plugins/hr/app/PluginUiSurface.tsx (copy, then change moduleId). Minimal runnable: templates/starter/ (includes a draft example).
When closing the dialog, pass dialog as an empty string. View-only dialogs set readonly: true; the assistant names the title and does not fill.
Checklist:
- [ ] Open/change/close draft all
postPluginUiChanged(close withdialog="") - [ ]
operations.jsonincludesfill_open_form(mutates: false) - [ ] invoke returns
ui_action: "fill_form"and does not write business tables - [ ]
listenHostPluginFormFillwritesfieldsinto the currently open inputs - [ ] Knowledge documents say: telling the app assistant field values writes the current draft (they need not name the form); nothing is stored until the user says save
6.2 Extra workflow steps (workflow_steps)
A plugin can declare workflow_steps in the same operations.json, hanging domain auto-nodes on the process designer (they appear in the catalog only when that plugin is enabled):
{
"module_id": "compliance",
"operations": [{ "name": "workflow_load_check_items", "mutates": false, "min_role": "member" }],
"workflow_steps": [
{
"type": "compliance.load_check_items",
"label": "Load check standards",
"description": "Read scoring criteria from compliance check items",
"color": "#0891b2",
"kind": "auto",
"operation": "workflow_load_check_items",
"config_hint": "Optional phases; check items come from the survey bound in process settings"
}
]
}
| Field | Meaning |
|---|---|
type | Step type (prefer {module_id}.{action}) |
kind | Currently only auto: on arrival InvokeOperation, then advance on always after success |
operation | Matching operation name in operations |
label / description / color | Designer display |
Auto-node agreed response:
{ "ok": true, "rubric": [ /* RubricItem[] */ ], "variables": { } }
rubric: written as instance scoring/upload criteria; elements must match the platformRubricItemcontract. Required for load-style nodes.variables: merged into instance variables (flat keys). Write-back nodes (HR “confirm staffing request”) may return onlyvariables.- On
ok: falseyou may includeerrorcopy; do not return list items with the wrong shape.
Implementation source of truth (plugin SDK): field table and response convention: [sdk/platform-plugin/contracts/API.md §3.3](/docs/sdk-platform-api); Go/TS types RubricItem / WorkflowLoadRubricResult. Product/engine summary: workflow.json-v1.md §check-item list contract.
Reference: toRubric in plugins/compliance/lib/workflowOps.ts. Other domain load nodes should output the same shape, so they can plug into core “upload evidence” and “auto score”.
Cadau: GET /workspaces/{id}/workflows/step-catalog merges the core catalog with enabled plugins’ workflow_steps.
6.3 Start an approval: write the document snapshot onto the run
When a plugin submits then starts approval (staffing request, hire/leave/transfer, expense, and similar), call POST /platform-plugins/workflows/start and put the full text the handler must see in variables.approval_doc. The engine lifts it onto the instance payload and the approval page renders it; it does not fetch the document from the plugin again. Do not send only an id / title and send people back to the app.
import { withApprovalDoc } from "@mindlink/plugin-sdk";
await client.startWorkflow({
definition_id,
title: "Submit staffing request · YR-2026-0001",
variables: withApprovalDoc(
{ staffing_req_id },
{
title: "Staffing request YR-2026-0001",
fields: [
{ label: "Applicant", value: "Chen Chen" },
{ label: "Department", value: "Corporate support" },
],
tables: [{ title: "Lines", columns: ["Department", "Position", "Headcount"], rows: [["Corporate support", "Finance specialist", "1"]] }],
},
),
});
Short documents (no line table) can use fieldListApprovalDoc("Onboarding", [["Name", "Chen Chen"], ["Employee no.", "E001"]]). Go: Client.StartWorkflow, WithApprovalDoc, FieldListApprovalDoc.
Auto-node invoke may also return top-level approval_doc (a document created mid-flow). Field table: [contracts/API.md §2.4](/docs/sdk-platform-api).
7. Knowledge documents: source in the plugin, retrieval in Cadau
Vs standards library: government/industry regulations and cross-plugin shared policy/theory live in product §3.2.2 and
Standards library. This section’s APIs only cover each plugin’s own how-to notes (plugin-{module_id}/). Do not sync a full regulation text into one plugin theme as workspace-wide source of truth.Read standards library (implemented):
GET /platform-plugins/standards,…/{id},…/{id}/content(Bearerlaunch_token, published and in-effect only); GoClient.ListStandards/ JSlistStandards.Vs asset library: shared table/form templates live in product §3.2.3 and
Asset library.Read asset library (implemented):
GET /platform-plugins/assets,…/{id},…/{id}/file(Bearerlaunch_token, published only); GoClient.ListAssets/ JSlistAssets; files are binary streams.Call the workspace model (implemented):
POST /platform-plugins/ai/json(Bearerlaunch_token) → structured JSON text from the workspace-configured model; GoClient.AIJSON/ JSclient.aiJSON; contract: [sdk/platform-plugin/contracts/API.md](/docs/sdk-platform-api) §2.2.3.
7.1 Principles
- Markdown files live in the plugin project (for example
knowledge/guide.md) and ship with the plugin. - Conversation retrieval still uses Cadau workspace knowledge (two-level
index.json+ match by question). Do not replace that with a plugin-owned vector store. - After sync, files land in runtime directory
plugin-{module_id}/, and a theme is registered in the workspace-rootindex.json. Workspace agents (including the in-plugin embed assistant) inject them automatically in conversation. - The plugin sync API syncs Markdown body only; images/short video and other rich media in workspace knowledge are managed on the Cadau product side, not uploaded via
knowledge/sync.
7.2 API (Bearer launch_token)
| Method | Path | Meaning |
|---|---|---|
| GET | /platform-plugins/knowledge/items | List synced documents |
| GET | /platform-plugins/knowledge/content?path= | Read body |
| PUT | /platform-plugins/knowledge/content | Write body and update index (owner/admin) |
| DELETE | /platform-plugins/knowledge/content?path= | Delete (owner/admin) |
| POST | /platform-plugins/knowledge/sync | Batch sync { documents: [...] } |
Go convenience:
synced, err := mindlinkplugin.SyncKnowledgeFromDir(ctx, client, "./knowledge")
7.3 Optional for local development: volume mount
Same-machine Docker can mount plugin knowledge/ onto the matching Cadau runtime path and skip sync; production and multi-machine still prefer API sync.
7.4 Workspace model (structured JSON, not conversation)
If an app-style plugin needs short-lived intelligence in its own business UI (for example generate a survey from a standard’s body, recommend staffing by department function), it should call Cadau:
POST /api/v1/platform-plugins/ai/json
Authorization: Bearer <launch_token>
- Model and keys: use the large model already configured for this workspace; the plugin does not talk to vendors or hold an API key.
- Input:
system+user(prompts); output:{ "text": "<JSON string>" }. - Vs in-plugin assistant: §8 embed is the user talking on the plugin page; this API is a one-shot structured generate on the plugin backend, with no chat conversation.
- Model not configured: returns unavailable; the plugin should fall back to rules/templates (see HR / compliance plugins).
- SDK:
const text = await client.aiJSON(
"You are……output JSON only: {\"items\":[...]}",
JSON.stringify({ context: "…" }),
);
const data = JSON.parse(text);
text, err := client.AIJSON(ctx, system, user)
Detail and length limits (Unicode characters: system ≤ 32,000, user ≤ 400,000): [sdk/platform-plugin/contracts/API.md](/docs/sdk-platform-api) §2.2.3. Business (for example compliance surveys) may set a stricter combined-body cap and ask for batches.
7.5 Skills shipped with the plugin (workspace skill center)
Besides knowledge/ (background), an app-style plugin can ship a skill pack in the repo: teach agents how to do a class of plugin-domain operations (steps, mappings, calling plugin_invoke / standards library / asset library, and similar). Skill body contract: Skill composition spec.
7.5.1 Vs knowledge and internet skills
| | Plugin knowledge (§7) | Skills shipped with the plugin (this section) | §1.1 internet skills | |--|-------------------|-------------------------|-------------------| | In user language | How-to notes, domain background | Repeatable operating handbook | Handbook for calling an external HTTP API | | In the repo | knowledge/*.md | skills/{slug}/SKILL.md (+ references/ and similar) | Anywhere; often only maintained in the skill center | | Into the workspace | knowledge/sync → plugin-{module_id}/ | Install into the skill center (idempotent by slug) | Create by hand / import / directory install | | In conversation | Retrieval injects background | Trigger-description recall / /skill | Same as left + http_request |
7.5.2 Repo directory convention
plugins/{module_id}/
knowledge/ # §7 sync
skills/
{slug}/
SKILL.md # required: frontmatter name/description + operating body
references/ # optional: long notes, column maps, sample pointers
seed-fingerprint.txt # recommended: content fingerprint for upgrade compare
samples/ # optional: sample files paired with the skill (need not go in the skill zip)
slug: stable id (lowercase hyphen); install and upgrade are idempotent on this; do not rename casually.- Author mirror:
skills/in the plugin repo is convenient for release and review; runtime source of truth may be a Cadau backend embedded pack (common for official plugins), or byte-level sync with the repo directory. - Do not put skill body only in
knowledge/and expect sync — knowledge retrieval does not replace skill-center recall.
7.5.3 Install and upgrade (required product voice)
- Scope: install target is the workspace skill center; agents in the workspace can recall by default.
- Forbidden: silently writing the skill into one agent’s “available skills” narrow list; do not guide copy as “bind to such-and-such agent” as an install step.
- First install: prefer when the user opens that plugin (enters the module from the apps desktop), after a member who can manage confirms seed; “not now” only skips the prompt, and does not block later prompts or upgrades.
- Content upgrade: compare a content fingerprint (for example
references/seed-fingerprint.txt); if installed and the fingerprint is behind, opening the plugin again can silently upgrade skill body and attachments (no browser clear, no reinstall). - Permissions: seed / upgrade require a workspace member who can manage; ordinary members can open the plugin but cannot install skills for the whole workspace.
7.5.4 Host-side APIs (generic)
User sign-in auth (same user-state as launch in §1; not launch_token):
| Method | Path | Meaning |
|---|---|---|
| GET | /workspaces/{id}/platform-plugins/{moduleId}/skills | This module’s registered shipped skills + install/upgrade status, can_manage_members |
| POST | /workspaces/{id}/platform-plugins/{moduleId}/skills/seed | Install or upgrade by fingerprint; optional body { "slug" }; omit to process all for that module |
Backend registration: official plugins in init call skillfromchat.RegisterPluginSkillBundle(...), embedding skills/{slug}/ into backend/internal/skillfromchat/bundled/. First example: module_id=compliance → practice-checklist-to-pack.
Response and fields: [sdk/platform-plugin/contracts/API.md](/docs/sdk-platform-api) §1.3; mechanism draft Compliance practice checklist to machine-readable pack.
Until a third-party plugin embeds the pack in Cadau, you can:
- Provide a downloadable skill zip and guide admins to import in the skill center; or
- Contribute embed registration to Cadau’s release side (same path as compliance).
7.5.5 Checklist
- [ ]
skills/{slug}/SKILL.mdhas clear when to use / when not trigger notes - [ ] Stable
slug; upgrades use a content fingerprint, not a slug rename - [ ] On open plugin: not installed → confirm install; installed but behind → silent upgrade
- [ ] Success copy says “skill center / agents in the workspace can recall”, not “bound to such-and-such agent”
- [ ] Do not mix duties with
knowledge/,plugin_invoke, or read-only standards/asset APIs
8. In-plugin agent Q&A
- In the workspace, create or pick a My agent, note
user_agent_id. - The plugin calls
POST /platform-plugins/embed-token(body:user_agent_id). - Frontend loads
{Cadau site}/embed/mindlink-widget.min.js, passingauth.token,workspace_id,user_agent_id(see host-embed/Embed contract).
The assistant uses workspace knowledge (including synced plugin knowledge). The plugin need not implement RAG itself.
9. Security and CSP
- Plugin responses must set
frame-ancestorsso the Cadau Web origin can iframe them (for examplehttp://localhost:8080). launch_tokenlasts about 15 minutes; about 2 minutes before expiry the Cadau shell silently re-issues andpostMessages the iframe{ type: "mindlink:launch_token", launch_token, expires_at }(also refreshes the gateway cookie). The plugin must writesessionStorage(see JS SDKlistenHostLaunchToken). The user need not go back to the apps desktop.- If host sign-in has expired or renew failed, plugin APIs 401; then open again from the apps desktop.
- Knowledge writes are limited to workspace owner/admin (same as the plugin business “can manage” role).
- Agent writes go through
plugin_invokeJWT +min_role/dangerousconfirmation, and are written to the audit table.
9.1 Follow host theme
When Cadau Web opens a platform plugin:
- Append
?theme=light|darkon the entry URL (the effective theme after resolving “system”). - When the host theme changes,
postMessagethe iframe:
{ "source": "mindlink", "type": "mindlink:theme", "theme": "dark" }
The plugin should set document.documentElement.dataset.theme and use the same CSS variables as the host (see client/web --bg / --card / --primary and similar). Official example: plugins/hr/app/HostThemeSync.tsx.
The host also pushes when the launch token is about to expire:
{ "source": "mindlink", "type": "mindlink:launch_token", "launch_token": "…", "expires_at": "…" }
The plugin must update the locally stored launch token (listenHostLaunchToken / sessionStorage), or requests with the old Bearer are rejected before the new cookie.
On hot reload or API 401, the plugin can ask for a renew (source must be mindlink-plugin):
{ "source": "mindlink-plugin", "type": "mindlink:request_launch_token" }
JS SDK: requestHostLaunchToken(). The host also pushes:
type | Meaning |
|---|---|
mindlink:plugin_tab | { tab } — help deep-links and similar switch plugin tabs (listenHostPluginTab) |
mindlink:plugin_data_changed | { module_id?, operation? } — suggest refreshing lists (listenHostPluginDataChanged) |
mindlink:plugin_form_fill | { form, fields } — write fields the assistant parsed back into the current draft (listenHostPluginFormFill) |
Plugin → host (fill dialog, §6.1):
{ "source": "mindlink-plugin", "type": "mindlink:plugin_ui_changed", "module_id": "my-plugin", "dialog": "draft", "dialog_title": "Example draft", "form": {}, "field_hints": "Name", "readonly": false }
Do not mix cookies / storage: gateway cookie ml_plugin_gw, plugin-origin cookie ml_plugin_launch, frontend sessionStorage key ml_plugin_launch_token (see [sdk/platform-plugin/contracts/API.md](../contracts/API.md) §3.4).
10. Local testing
See deploy/plugin-dev-platform/README.md (Cadau Docker 8080/8082) and plugins/hr/README.md.
Typical steps:
- Start the Cadau Docker stack.
- Configure
plugins/hr.env(optionalMINDLINK_USER_AGENT_ID,MINDLINK_DATABASE_URL/MINDLINK_JWT_SECRET). run.cmdstarts the plugin (local 3011, reverse-proxied via Cadau/p/hr/).- Sign in on 8080 → workspace → Apps → open Human Resources → sync knowledge → use the in-plugin assistant or
plugin_invokein conversation.
Plugin gateway (recommended)
| Config | Meaning |
|---|---|
entry_base_url | Browser iframe entry; prefer /p/{module_id}/ |
upstream_url | Plugin internal URL (for example http://127.0.0.1:3011); do not expose the plugin port on the public internet |
operations_url | Optional; default {upstream}/operations.json |
| Implementation | backend/internal/platformplugin/proxy.go; Web Nginx location /p/ → backend |
Public auth (C+D):
| Path | Gateway requirement |
|---|---|
| Static assets / entry page | Valid launch_token: URL query (first screen only), gateway cookie ml_plugin_gw, or Authorization: Bearer |
/p/{module_id}/api/* | Must cookie or Bearer; query alone is forbidden (log leak) |
/p/hr/take/*, /p/hr/api/exam-public/* | Exception (HR only): candidate answering; launch credential not required |
| Launch | POST …/launch response writes an HttpOnly cookie with Path=/p/{module_id}/ |
Plugin frontend calls to its own APIs must use a relative path or JS SDK resolvePluginAPI() + createAuthorizedFetch() (Bearer and credentials: "include" automatically).
11. Implementation map
| In user language | Implementation |
|---|---|
| Launch token | JWT plugin_launch, authx/plugin_launch.go |
| Agent-call token | JWT plugin_invoke, authx/plugin_invoke.go; tool plugin_invoke |
| Workspace data namespace | workspacens.Ensure; table workspace_data_namespaces |
| Plugin entry gateway | /p/{module_id}/ → upstream_url; gateway cookie ml_plugin_gw + API requires Bearer/Cookie (platformplugin/proxy.go, gateway_auth.go) |
| Plugin knowledge directory | {RuntimeDir}/workspaces/{id}/knowledge/plugin-{module_id}/ |
| Index maintenance | platformplugin/knowledge.go → UpsertPluginKnowledgeDocument |
| Embed token | Same registration logic as POST /user-agents/{id}/embed-token, issued via platform-plugins/embed-token |
| Official HR plugin | plugins/hr/ (README + knowledge/; user help help/product-features/platform-hr*.md) |
| Official email plugin | plugins/email/ (IMAP receive / SMTP send; user help help/product-features/platform-email.md) |
| Official camera plugin | plugins/camera/ (face-recognition cameras: access, attendance, security, recording playback; user help help/product-features/platform-camera.md) |
| Skills shipped with the plugin | plugins/{module}/skills/{slug}/ → workspace skill center; example plugins/compliance/skills/practice-checklist-to-pack/ (§7.5) |