# systemHUB Docs — full corpus
> Every page of https://systemhub.com/docs/ in one file, for AI agents. Curated index: https://systemhub.com/llms.txt · Each page is also served individually as markdown (append .md to its URL). Generated with the site build.
---
# systemHUB Docs (https://systemhub.com/docs/)
> Part of systemHUB Docs · Connect: Settings → AI Gateway in systemHUB · Auth: OAuth (scoping is workspace-level today — see Getting started) · MCP tools: 48 · Full corpus: https://systemhub.com/llms-full.txt
> Machine-readable documentation for connecting AI agents and technical users to systemHUB.
systemHUB is a platform for documenting, organising, and training teams on business systems — **Systems** (procedures/SOPs), **Policies** (compliance documents), and **Trainings** (learning modules). This documentation set describes how an AI agent (via the systemHUB MCP server) or a developer can connect to systemHUB, read a company's content, and author or maintain it programmatically.
This is the **AI-facing** surface. If you're a human looking for friendly, task-oriented help, use [help.systemhub.com](https://help.systemhub.com) instead. The two layer together — they don't replace each other.
## Who this is for
- **A prospect's or customer's AI assistant** connecting to systemHUB via MCP, so it can find and use the company's systems with no friction.
- **Technical users / developers** integrating with, or building on top of, the systemHUB MCP server.
## Start here
1. **[Getting started](/docs/getting-started)** — connect the systemHUB MCP server and make your first call.
2. **[Quick wins](/docs/quick-wins)** — verified copy-paste prompts for a newly connected agent.
3. **[Teach your AI](/docs/teach-your-ai)** — make it stick: the first-session prompt and the briefing your AI saves into its standing context.
4. **[Document lifecycle](/docs/concepts/document-lifecycle)** — how documents, states, and publishing work.
5. **[Roles & seats](/docs/concepts/roles-and-seats)** — how access is granted and counted.
6. **[Sharing & links](/docs/concepts/sharing-and-links)** — app links (login required) vs public share links (no login, machine-readable).
7. **[Authoring content](/docs/concepts/authoring-content)** — the formatting contract: what survives the editor and what gets stripped.
8. **[Errors & limits](/docs/concepts/errors-and-limits)** — known failure modes and validation limits, stated up front.
9. **[Tool reference](/docs/tool-reference)** — every MCP tool, its inputs, and what it returns, generated from the live schema.
## Guides (worked examples)
Task-oriented walkthroughs with request→response examples:
- **[Draft an SOP into systemHUB](/docs/guides/drafting-sops)** — orient, dedupe, create to the house format, attach templates/media, version.
- **[Audit access, sign-off & training](/docs/guides/auditing-access)** — who can see what, who's agreed, who's completed training, what a person owns.
- **[Organise & maintain the library](/docs/guides/organising-content)** — folders, moves, states, tags, learning tracks, master templates.
## What you can do through the MCP today
- **Discover & read** — browse the folder tree; search systems, policies, and trainings by name; read full document content, owners, tags, media, and attachments.
- **Audit** — see who a document is assigned to (members & roles), agreement/sign-off status, and training completion progress.
- **Author & maintain** — create, edit, move, and publish systems, policies, trainings, folders, learning tracks, tags, and media.
## Known limits
These are documented honestly so a connecting agent doesn't try what isn't there yet:
- **No seat provisioning** via the MCP — inviting people and allocating licences happens in the app UI. (Document-level member/role *assignment* IS available — see `manage_document_members`.)
- **No headless / service credential yet** — the MCP connection is per-user OAuth, designed for a person's AI client. Unattended automations (cron jobs, scheduled pipelines) have no non-expiring credential today; a long-lived API-key path is on the product roadmap.
- **No workspace-wide usage analytics** via the MCP. (Per-document activity, including views, IS readable — see `get_document_activity_log`.)
- **No deletes** — an agent can create, edit, move, and publish, but never destroy.
- **Images cannot be injected via the API** — they're uploaded through the editor. See [Authoring content](/docs/concepts/authoring-content).
Recent capability changes are tracked in the **[changelog](/docs/changelog)**.
## For AI agents reading this
Every page on this site is also servable as plain markdown — append `.md` to the page URL (e.g. [/docs/getting-started.md](/docs/getting-started.md)). A machine-readable index lives at [/llms.txt](/llms.txt).
---
# Getting started (https://systemhub.com/docs/getting-started)
> Part of systemHUB Docs · Connect: Settings → AI Gateway in systemHUB · Auth: OAuth (scoping is workspace-level today — see Getting started) · MCP tools: 48 · Full corpus: https://systemhub.com/llms-full.txt
This guide gets an AI agent or technical user connected to systemHUB through the **MCP server** and making a first read call.
## 1. What the MCP server is
The systemHUB MCP server exposes your company's systemHUB content — Systems, Policies, and Trainings — to an AI agent as a set of callable tools. An agent that speaks the [Model Context Protocol](https://modelcontextprotocol.io) can connect to it, discover the available tools, and call them to search, read, author, and audit content on your behalf.
## 2. Prerequisites
- A systemHUB account with content you want the agent to reach.
- **AI Gateway access** enabled on your plan (included with Accelerator). If you don't see **AI Gateway** under Settings, contact [support@systemology.com](mailto:support@systemology.com).
- An MCP-capable client (e.g. Claude, ChatGPT, or any agent framework that supports MCP servers).
> ⚠️ **Authentication note (important, being fixed):** a connection is currently scoped to the **identity attached to the workspace's most recently generated AI Gateway token** — *not* to each person who connects. On a workspace where several people connect, everyone's agent can therefore resolve to the same identity and visibility. Treat MCP access as **workspace-level** for now: only connect agents for people you're comfortable seeing everything the token generator can see. A fix binding each connection to the person connecting is in progress — see the [changelog](/docs/changelog).
## 3. Connect
Everything you need lives in one place in systemHUB: **Settings → AI Gateway**. Three things matter:
1. **Server URL** — `https://mcp.systemhub.com/mcp` (the same for every workspace).
2. **OAuth Client ID** — your **company alias**, which is your account subdomain (the part before `.systemhub.com`), lowercase, no spaces (e.g. `acme`, not `Acme`).
3. **Token** — click **Generate New Token** and copy it immediately; **it is shown only once**. Tokens live for **180 days** from generation (you'll get an email reminder at day 144 to rotate). ⚠️ Generating a new token **immediately revokes the existing one** and disconnects any AI agent currently connected with it — they'll need to reconnect with the new token.
Then connect from your AI client:
- **Claude (web or desktop):** **Settings → Connectors → Add custom connector** — name it `systemHUB`, enter the server URL `https://mcp.systemhub.com/mcp`, and in advanced settings set the OAuth Client ID to your company alias and paste the token. Click **Connect**, log in with your systemHUB credentials and approve access.
- **Google Gemini CLI** (verified 7 Aug 2026): `gemini mcp add -s user --transport http systemhub https://mcp.systemhub.com/mcp`, then `/mcp auth systemhub` and complete the browser flow. `/mcp` should then report `systemhub - Ready (48 tools) (OAuth)`.
- **Any other MCP client** (agent frameworks, IDEs): configure a remote MCP server with the Connector URL as the endpoint and OAuth as the auth method, then complete the browser login when prompted. The MCP Inspector is a quick way to verify the server responds before wiring it into an agent.
### Which AI clients can actually connect
The MCP protocol is open, but **not every client lets you add a custom server**, and several gate it behind a paid or admin tier. Verified 7 Aug 2026:
| Client | Custom MCP server? | Notes |
|---|---|---|
| **Claude** (web, desktop, Code) | ✅ Yes | Paid plan. Verified. |
| **Google Gemini CLI** | ✅ Yes | Free, but technical (Node install). Verified end to end against a production workspace. Needs an AI Studio API key for the CLI's own model auth — on a Workspace account that also means importing a Cloud project. |
| **ChatGPT** | ⚠️ Paid tiers only | Reported to require Plus or above with developer mode. **Not available on the free tier.** |
| **Gemini web app** | ❌ No | Connected Apps is a curated catalogue with no way to add a custom server. Custom MCP needs **Gemini Enterprise** (admin-registered) or the CLI above. |
> **Plan for this when rolling out to a team.** Someone using free ChatGPT or the Gemini web app cannot connect at all — no setting exists. They'll need a paid AI client, or the Gemini CLI if they're comfortable in a terminal.
> **One token, several clients.** You can connect more than one AI client with the same token — Claude and Gemini CLI running against the same workspace concurrently has been verified, as has Claude desktop plus Claude web. Remember that *generating* a new token disconnects all of your own connected clients at once (see above).
Step-by-step with screenshots: [Connecting systemHUB to Claude + ChatGPT (AI Gateway / MCP)](https://kb.systemology.com/help-center/connecting-systemhub-to-claude-ai-gateway-/-mcp).
### Connecting your team
The server URL, alias, and token are **company-level** — there is one token per workspace, not one per person.
> ⚠️ **Multi-user connection is being confirmed (as of 31 Jul 2026).** Field reports conflict: some workspaces have connected several team members with the same values, while in others additional members hit an error even when they are systemHUB admins. We are also confirming whether the connection carries the *token generator's* access or each member's own access — until that's answered, **don't assume an editor's AI is limited to editor permissions**. If you're rolling out to a team, connect one person first and [check with support](mailto:support@systemology.com) before wider rollout. This note will be updated when the behaviour is confirmed — see the [changelog](/docs/changelog).
**Each person generates their own token — don't pass yours around.** Sharing a token means your colleague's agent runs with *your* identity and access. Generating your own token does **not** disconnect your colleagues: tokens are per-person, and generating one only revokes your own previous token and your own sessions.
**Adding a team member (field-tested procedure):**
1. **They log into systemHUB as themselves** → Settings → Company → AI Gateway → **Generate New Token**. This is their token, separate from everyone else's.
2. **In their AI client, use the existing systemHUB connector entry** and click **Connect** — in a shared Claude Teams workspace, one person adds the connector once and everyone else connects through it.
3. **They enter the company alias, sign in as themselves, and approve.** Done.
> **Don't add a second custom connector** pointing at the same server URL — the client rejects it with *"a server with this URL already exists"*. If a connector for systemHUB is already in the workspace, connect to that one.
> ⚠️ **If they haven't generated their own token first**, the approve step fails with *"No active agent token found"*. That's the most common cause of a failed team connection — generate the token, then approve.
Also worth knowing:
- Reaching Settings → Company → AI Gateway may require elevated permissions. If a team member can't see that screen to generate their own token, they can't complete this flow — [tell us](mailto:support@systemology.com), as we're confirming which roles can self-serve.
- **Don't rely on MCP activity for audit attribution** yet — sessions can report as the token's identity rather than the person acting.
### Troubleshooting
| Symptom | Likely cause → fix |
|---|---|
| **"Invalid or expired client ID"** | Company alias format is wrong (must be lowercase, no spaces) or the token is stale → regenerate in Settings → AI Gateway. |
| **Tools don't appear in the client** | Connection added but not authorised → re-run Connect and complete the login/approval; after regenerating a token, reconnect. |
| **Agent was working, suddenly can't connect** | *You* generated a new token (which revokes your own previous one), or your token passed its 180-day lifetime → reconnect. A colleague generating their token does not affect you. |
| **"No active agent token found" on the Approve Connection screen** | You reached the consent screen signed in as yourself, but *you* don't have a token of your own — someone else's token doesn't satisfy this check → generate your own in Settings → AI Gateway, then approve again. This is the per-user path working as intended. |
| **"A server with this URL already exists"** | You're adding a *new* custom connector for a systemHUB server already configured in that workspace → don't add a second one; connect through the existing entry. |
| **"Document not found" on a document that exists** | Visibility scoping — the connected user can't see it — or it's a master template (`get_*_details` returns 404 on those by design). |
| **400 on an owner lookup** | Full name didn't match exactly → use the exact name from a tree node, or the user UUID. |
| **502 on a large edit** | Content over ~126KB → split the document or write in sections. |
| **"My formatting changed after a human edited the doc"** | You authored outside the supported set; the editor filtered it → see [Authoring content](/docs/concepts/authoring-content). |
More failure modes: [Errors & limits](/docs/concepts/errors-and-limits).
## 4. Your first call
Once connected, the agent should **orient before acting**:
1. **Map the structure** — call `get_folder_tree` (Systems), `get_policy_tree` (Policies), or `get_training_tree` (Trainings) to see folders and documents, their owners, and publication state.
2. **Find a document** — call `search_by_name` (systems), `search_policy`, or `search_training` with a title fragment.
3. **Read it** — call `get_system_details` / `get_policy_details` / `get_training_details` with the document UUID to pull full content, overview, tags, media, and comments.
A minimal "can you see my systems?" smoke test is a single `get_folder_tree` call with no arguments — it returns the top of the Systems tree.
## 5. Good-citizen rules for connecting agents
- **Read before you write.** Orient with the tree/search tools before creating or editing anything.
- **Respect master templates.** Nodes flagged `isMasterTemplate: true` are read-only reference content from the master workspace — never edit, move, publish, or delete them. `get_*_details` returns `404` on them by design.
- **Match names exactly for owner lookups.** `list_documents_by_owner` needs the person's full name exactly or their user UUID.
- **Publishing is deliberate.** Creating a document *with content* publishes it automatically so assigned users can see it. Pass `publish: false` to keep a draft. See [Document lifecycle](/docs/concepts/document-lifecycle).
- **Author within the supported formatting set.** The editor silently strips unsupported HTML on the next human save. See [Authoring content](/docs/concepts/authoring-content).
Next: **[Quick wins →](/docs/quick-wins)** — verified copy-paste prompts for your first ten minutes connected — or dive into **[Document lifecycle](/docs/concepts/document-lifecycle)**.
---
# Quick wins (https://systemhub.com/docs/quick-wins)
> Part of systemHUB Docs · Connect: Settings → AI Gateway in systemHUB · Auth: OAuth (scoping is workspace-level today — see Getting started) · MCP tools: 48 · Full corpus: https://systemhub.com/llms-full.txt
Copy-paste prompts to run with your connected AI (Claude, ChatGPT or any MCP-capable client) once systemHUB is connected. Every prompt on this page has been verified against the live systemHUB MCP server — each one maps to tools that exist today, so none of them will leave your AI apologising.
Not connected yet? Start with **[Getting started](/docs/getting-started)** or the step-by-step help article: [Connecting systemHUB to Claude + ChatGPT (AI Gateway / MCP)](https://kb.systemology.com/help-center/connecting-systemhub-to-claude-ai-gateway-/-mcp).
## Accountability
The reports that used to mean chasing people or exporting spreadsheets. Ten seconds each.
**1. Policy sign-off status**
> Check our [policy name] policy in systemHUB. Who still hasn't signed off on it? Draft me a friendly chase-up message for each person.
Returns the exact signed-off and pending lists with names and emails, from `get_document_agreement_status`.
**2. Training progress**
> How's the team going on the [training name] training? Show me who's done, who's mid-way and who hasn't started.
Returns per-person completion status and percentages, from `get_document_training_progress`.
**3. Ownership handover**
> [Name] is going on leave. List every system, policy and training they own so we can reassign them.
Returns everything they own across all three sections in one call, from `list_documents_by_owner`. Use the person's exact full name as it appears in systemHUB.
## Build and update
**4. Talk a process into a draft SOP**
> I'm going to talk you through how we [do a task]. Ask me questions until you've got it, then draft it as a system in systemHUB for my review.
The AI creates the document in systemHUB where your team can see and review it — not in a chat window that disappears. The full worked loop: [Draft an SOP](/docs/guides/drafting-sops).
**5. Keep a system current**
> Our [process] changed: [describe the change]. Find the system in systemHUB and update it to match, keeping the same format.
**6. Gap and contradiction scan**
> Search systemHUB for everything we have about [topic]. What's covered, what's missing and where do two documents contradict each other?
## Daily use
**7. Answer from your own systems**
> Using only our systemHUB, how do I [do the task]? Cite which system you're reading from.
**8. New-hire week one**
> We've got a new [role] starting Monday. Pull their relevant systems and trainings from systemHUB and build a week-one onboarding checklist.
**9. Share a system with an outsider**
> Get me a share link for our [system name] system that I can send to our new contractor — they don't have a systemHUB login.
Your AI calls `get_document_share_link`, then hands you the **human-readable** form — `https://{alias}.systemhub.com/systems/{uuid}/{shareCode}` — which opens the document in a browser with no login. (The raw `api.systemhub.com` version of the same code returns JSON, which is for programs, not people.) See [Sharing & links](/docs/concepts/sharing-and-links). Anyone with the URL can read it, so share deliberately.
**10. Who touched this document?**
> Who created our [system name] system, and who last edited it? Anything change recently?
Returns the creation and edit history from `get_document_activity_log`.
## What the MCP can't do yet
Stated plainly so your AI doesn't attempt it (see also [Known limits](/docs/#known-limits), [Errors & limits](/docs/concepts/errors-and-limits), and the [changelog](/docs/changelog)):
- **Workspace-wide "who viewed what" analytics.** Per-document activity (including views) is readable via the activity log, and sign-offs (a deliberate "I agree" click) are fully reportable — but for accountability, ask "who hasn't signed off", never "who hasn't read": a view proves nothing.
- **Inviting users or managing seats.** Assigning existing members and roles *to a document* works via the MCP; bringing new people into the workspace or changing licences is app UI only.
- **Deleting documents.** Blocked by design — your AI can create, edit, move and publish, but never destroy.
Next: **[Document lifecycle →](/docs/concepts/document-lifecycle)**
---
# Document lifecycle: states, Save vs Publish (https://systemhub.com/docs/concepts/document-lifecycle)
> Part of systemHUB Docs · Connect: Settings → AI Gateway in systemHUB · Auth: OAuth (scoping is workspace-level today — see Getting started) · MCP tools: 48 · Full corpus: https://systemhub.com/llms-full.txt
Every systemHUB document — whether a System, Policy, or Training — moves through a defined lifecycle. An AI agent must understand this before authoring, or it will create content nobody can see, or overwrite an approved document.
## Document states
A document's `state` is an integer with a fixed meaning and colour:
| `state` | Colour | Meaning |
|---|---|---|
| `0` | GREY | Draft — being written, not yet reviewed |
| `1` | ORANGE | Needs review — drafted, awaiting approval |
| `2` | RED | Overdue — past its review date |
| `3` | GREEN | Approved — current, reviewed, live |
| `4` | PURPLE | Archived — retired, kept for reference |
These values are returned on every tree node, search result, and `get_*_details` call, and are accepted by the `state` parameter on create/edit tools.
## Save vs Publish (the distinction that matters most)
**Save records your changes. Publish is what your team sees** — until you publish, assigned members keep viewing the last published version.
- **Save** — writes the current content. On its own, saving does not push a new visible version to assigned users.
- **Publish** — releases a version so that assigned members actually see it. Publishing is what makes content live.
For agents, the practical rules are:
- **Creating a document *with content* auto-publishes it** — assigned users can see it immediately. This is intentional; you do **not** need to ask the user to confirm publishing.
- **To create a draft that stays hidden**, pass `publish: false` on the create call. It's saved but not released.
- **Editing auto-publishes too.** `edit_*` releases the change to assigned members unless you pass `publish: false`. Use `publish_system` / `publish_policy` / `publish_training` when you want to cut a *named* version (e.g. `"v1.1 - Added billing steps"`), not to make an edit visible — it already is.
- **So do metadata writes.** `add_document_tags`, template, media and attachment tools all default to `publish: true` — *tagging a document publishes it*. That means a document you created with `publish: false` stops being hidden the moment you tag it. If something must stay unpublished, pass `publish: false` on **every** write to it, not just the create.
> ⚠️ **The practical consequence:** there is no "work quietly then release" mode by default. Any write to a live document — including one that only touches metadata — is visible to the whole team immediately. Before editing an approved document, be sure the user wants the change live now.
> **Canonical wording:** the summary line above is the current agreed phrasing; the app empty-state copy is being finalised from the internal content audit and will be reconciled here so the docs and the product never disagree.
## View vs Edit
Access to a document is not all-or-nothing:
- **View** — a member can read the document but not change it.
- **Edit** — a member can modify content.
What a given person can do is a function of their **role** and any **direct assignment** on the document. See [Roles & seats](/docs/concepts/roles-and-seats). An agent connected with a user's token inherits exactly that user's view/edit scope.
## How systemHUB behaves over time (the model to reason with)
The sequence an agent should hold in its head:
| You do | What happens | When |
|---|---|---|
| `create_system` with content | Document saved AND published — assigned members can see it | Immediately |
| `create_system` with `publish: false` | Document saved as a hidden draft | Visible to no one until published |
| `edit_system` | Content updated at the API layer, stored **verbatim** | Immediately; a new published version only when you cut one |
| `publish_system` | A named version released to assigned members | Immediately |
| A human opens the doc in the editor and saves | The editor **filters the stored HTML** to its supported feature set | First human save — this is when out-of-contract formatting silently changes |
That last row is the one that surprises agents: the API stores whatever HTML you send, but the *editor* is the filter, applied on the next human save — which may be days later. Author within the [supported set](/docs/concepts/authoring-content) and the document is stable forever; author outside it and the document changes under the owner's feet the first time they touch it.
## Master templates
Some content is a **master template** — read-only reference content supplied from the master workspace (`isMasterTemplate: true`). It appears in trees and search so it can be browsed and copied, but it cannot be edited, moved, published, or deleted, and `get_*_details` returns `404` for it. Treat master templates as immutable.
Next: **[Roles & seats →](/docs/concepts/roles-and-seats)**
---
# Roles, members & seats (https://systemhub.com/docs/concepts/roles-and-seats)
> Part of systemHUB Docs · Connect: Settings → AI Gateway in systemHUB · Auth: OAuth (scoping is workspace-level today — see Getting started) · MCP tools: 48 · Full corpus: https://systemhub.com/llms-full.txt
systemHUB controls who can see and do what through **roles** and **member assignments**. This page explains the model an agent needs to reason about access — and where the current MCP boundary sits.
## The access model
A document's access is the union of two mechanisms:
- **Role-based access** — a document is assigned to one or more **roles** (e.g. a department or job function). Every member holding that role gets access.
- **Direct assignment** — an individual member is assigned to the document specifically, regardless of role.
A member can therefore have access that is **direct**, **role-based**, or **both**. The `get_document_members_and_roles` tool returns exactly this: the roles on a document, plus each member's name, email, role title(s), and access type.
Present an access picture as an audit: roles first, then members grouped by how they got in (direct vs role-based vs both).
## Document owners
Separate from access, every document carries a **primary owner** (mandatory — the person accountable for it) and an optional **secondary owner** (a backup). Owners are about accountability, not permission: owning a document is not what grants access to it.
Three behaviours to know before changing owners programmatically:
> **Changing the primary owner moves the outgoing owner into an empty secondary slot.** If the secondary slot is empty, the person you just replaced is automatically recorded as secondary owner — the intent being that a handover keeps the previous owner attached as backup. If a *distinct* secondary owner already occupies the slot, it is left untouched and the outgoing owner simply drops off. This fires on every owner change and is not reported in the response, so **re-read the document after reassigning** rather than assuming the secondary slot is unchanged.
- **A secondary owner equal to the primary owner is treated as no secondary owner.** It is returned as null and displayed as empty. This is why `list_documents_by_owner` describes matching a *distinct* secondary owner, and why a document can appear to gain a secondary owner the moment its primary changes.
- **To clear a secondary owner, pass `secondaryOwner: null`** on `edit_system` / `edit_policy` / `edit_training`. Omitting the field leaves it unchanged.
**Reassigning in bulk (e.g. someone leaving):** deleting a user in the app UI is the intended path — it asks for a replacement primary *and* secondary owner and swaps the departing person out of both slots across every document in one action, without triggering the auto-fill above. Reassigning documents one at a time instead means the auto-fill applies to each, so plan on a second pass to tidy the secondary slots.
## Seats
A **seat** is a licensed member of the workspace. Seat/member management — inviting people, allocating seats, changing who holds which role — is done in the **systemHUB app UI**.
> **MCP boundary (important for connecting agents):** the MCP can **read** the full access picture (members, roles, assignment type, agreement status, training progress) and can **write document-level access** — `manage_document_members` assigns or removes members and roles on a document, with `list_company_members` / `list_roles` to resolve names to UUIDs. What it can **not** do is seat provisioning: inviting new people to the workspace, allocating licences, or changing who holds which company role. That stays in the app UI — direct the user there.
## What agents can audit today
- `get_document_members_and_roles` — who can access a document, and how.
- `get_document_agreement_status` — who has agreed/signed off on a document (e.g. a policy acknowledgement).
- `get_document_training_progress` — for trainings, each assigned user's completion percentage and status.
- `get_document_activity_log` — who created and last modified a document, plus the event feed (`includeViews: true` to include views).
- `list_documents_by_owner` — everything a given person owns across systems, policies, and trainings, in one call.
> ⚠️ **`manage_document_members` with `action: "update"` REPLACES the document's assigned roles — it does not merge.** Passing a partial list silently removes every role you left out. To add or remove without collateral damage, use `action: "add"` / `"remove"`. Always confirm the result with `get_document_members_and_roles`.
> **Paginate deliberately.** The audit tools page their results. Pass `fetchAll: true` (the default on most) when you need a complete roster — a partial page will otherwise be reported as the whole answer, which is how an agent confidently states the wrong list of who has signed off.
Together these cover "who owns / can see / has completed what" — the read side of governance. The write side (provisioning) stays in the app for now.
Next: **[Authoring content →](/docs/concepts/authoring-content)**
---
# Sharing & links (https://systemhub.com/docs/concepts/sharing-and-links)
> Part of systemHUB Docs · Connect: Settings → AI Gateway in systemHUB · Auth: OAuth (scoping is workspace-level today — see Getting started) · MCP tools: 48 · Full corpus: https://systemhub.com/llms-full.txt
systemHUB documents can be reached two ways, and an agent should know which one it's handing out. They behave very differently.
## The two link types
| | App link | Share link |
|---|---|---|
| **Who can open it** | Logged-in members with access to that document | **Anyone with the URL — no login** |
| **What it shows** | The document in the systemHUB app | The **published** version, as machine-readable JSON |
| **Respects roles/visibility** | Yes — same access model as everything else | No — the link itself is the access |
| **Best for** | Team members working inside systemHUB | External contractors, auditors, clients — or **feeding a document to an AI that isn't connected via MCP** |
## App links
A regular link to a document inside the app. Opening it requires the person to log in and have access (via role or direct assignment — see [Roles & seats](/docs/concepts/roles-and-seats)). If they can't see the document in systemHUB, the link won't show it to them.
**An agent can construct an app link** from the workspace alias and the document UUID (which every tree, search, and details response carries):
```
https://{alias}.systemhub.com/systems/{uuid} ← Systems
https://{alias}.systemhub.com/policies/{uuid} ← Policies
https://{alias}.systemhub.com/trainings/{uuid} ← Trainings
```
This also works in reverse: when a user pastes an app URL at you, the UUID in it is the same UUID the MCP tools address — extract it and call `get_system_details` (or the matching section's tool) directly. Caveats: this form **requires login** and access to the document, and the app won't error on a malformed UUID until after login — so treat a constructed link as "the right address," not proof the document exists.
> **Sending it to someone without a login?** Add the share code to make it public — see [the human-readable share link](#the-human-readable-share-link-use-this-one-for-people) below. (Both forms were surfaced by SYSTEMologists in the field.)
## Share links
A share link is a public URL for one document. Generate or retrieve one with:
```
→ get_document_share_link { "documentId": "7d4f2a90-…", "topicType": "system" }
```
Key behaviours:
- **Designed for no-login access.** The intent is that anyone holding the URL can fetch the published version as machine-readable JSON — the lightest-weight way to hand one process to an outside party or an AI without an MCP connection.
- **It reuses an existing share code** when the document already has one, and generates one if missing. Calling it twice doesn't create two links.
- ⚠️ **Share codes are not unique per document.** **Duplicating a document copies its share code**, so the copy and the original share one code (reported and reproduced across two document pairs, 4 Aug 2026). If you're building an index keyed on share codes, key on the document UUID instead — a share code can point at more than one document. Two code formats are also in circulation (longer codes on older documents, shorter on newer), so don't validate them by shape.
- **It shows the published version only** — unpublished edits stay private until published (see [Document lifecycle](/docs/concepts/document-lifecycle)).
- Generating one requires SHARE permission on that document type.
> ⚠️ **Known issue (verified 28 Jul 2026):** fetching the raw `api.systemhub.com/...` share URL from outside returns **403 "Company not found"** — that endpoint cannot resolve the workspace from the bare URL. Use the human-readable form below instead, which works.
## The human-readable share link (use this one for people)
Take the share code from `get_document_share_link` and put it on the **app host**, qualified by your workspace alias:
```
https://{alias}.systemhub.com/systems/{uuid}/{shareCode}
https://{alias}.systemhub.com/policies/{uuid}/{shareCode}
https://{alias}.systemhub.com/trainings/{uuid}/{shareCode}
```
**Verified 4 Aug 2026: this renders the published document in a browser with no login**, in a clean session — title, Overview and Details. A wrong or missing share code returns 404, so the code is doing the work, not an existing session.
- `{alias}` is your **company alias** — your systemHUB subdomain, the part before `.systemhub.com` (the same value used as the OAuth Client ID; find it in Settings → AI Gateway).
- `{uuid}` is the document ID, present on every tree, search and details response.
- `{shareCode}` is the trailing path segment of the `shareLink` returned by the share-link tool (or the `shareLink` field on `get_*_details`).
Two behaviours worth knowing when you construct or inspect these links:
- **The app rewrites to a guest route.** Opening the link lands on `/{section}/guest/{uuid}/{shareCode}?company={alias}` — the alias carried explicitly. That's expected; share the short form and let the app do the rewrite.
- **The section segment is not validated.** A system's UUID and code requested under `/policies/` still renders the system (reported 7 Aug 2026). So don't infer a document's section from the URL it was shared under — use `discriminator` on the document itself.
**This is the link to give a human.** It needs no login and no seat, which makes it the right answer for a contractor, an auditor, a client, or a team member on their phone.
> ⚠️ **Agents: you cannot fetch this form.** The share view is a client-rendered app, so a plain HTTP request (curl, an agent's fetch tool, a link unfurler, a preview bot) gets the JavaScript shell — *not* the document. It only renders in a real browser. Two consequences: don't try to read a document by fetching this URL (use `get_*_details` instead), and don't treat a 200 as proof the link is valid — **the 404 for a wrong share code is also rendered client-side**, so status codes tell you nothing here.
>
> **There is currently no share URL an external agent can fetch without a browser.** The `api.systemhub.com` form is the machine-readable one — it returns the published document as JSON — but it currently 403s externally (see the known issue above). Until that's fixed, hand share links to *people*, and give programs MCP access instead.
`get_*_details` responses include a `shareLink` field (the URL, or `null` if none exists).
## Rules for agents
- **Never hide an existing share link.** When presenting a document's details, always surface its share link if one exists — it's part of the document's identity, not metadata to trim.
- **Say which kind of link you're giving.** "Here's the share link (public, no login)" vs "here's the app link (they'll need to log in)". The difference matters to the user even when it doesn't matter to you.
- **Treat share links as public.** Before generating one, make sure the user understands anyone with the URL can read the document. Don't generate share links for sensitive documents unprompted.
Next: **[Errors & limits →](/docs/concepts/errors-and-limits)**
---
# Authoring content (https://systemhub.com/docs/concepts/authoring-content)
> Part of systemHUB Docs · Connect: Settings → AI Gateway in systemHUB · Auth: OAuth (scoping is workspace-level today — see Getting started) · MCP tools: 48 · Full corpus: https://systemhub.com/llms-full.txt
An agent that can call `create_system` is not yet an agent that produces *good* systemHUB documents. This page is the authoring contract: which HTML survives, which is silently changed, and the conventions that make a document genuinely usable. It is extracted from the live editor configuration (a custom CKEditor 5 build) and verified by round-trip audit — not guessed.
## The rule that matters most
> 🚨 **Send raw HTML, never entity-escaped HTML.** Write `
Title
`, not `<h2>Title</h2>`. The API stores escaped content verbatim and returns success — but the document renders as visible tag soup (literal `
` characters on screen). Nothing warns you. Escaping HTML while serialising into JSON is a classic agent failure mode: if your framework auto-escapes, unescape before sending, and read the document back after writing to confirm it rendered.
**The MCP/REST layer stores your HTML verbatim. The editor is the filter.** Content outside the supported set is not rejected at write time — it is silently removed or downgraded the first time a human opens the document in the editor and saves. No error is raised. So author *within* the supported set, or your content will change under the user's feet later.
## The four content fields
Every system, policy, and training document has four content areas. All except Title are rich text with the same formatting rules:
| Field | API parameter | Purpose |
|---|---|---|
| Title | `title` | Plain text, max 255 chars. |
| Overview | `description` | One or two sentences: what this is and why it matters. Not the steps. |
| Details (body) | `content` | The main content. Steps live here. |
| Notes | `note` | Internal notes for editors and reviewers. |
## Supported formatting (survives the editor)
- **Headings:** `