Define document types and control how they are processed during ingestion
Overview
Content types define the categories of documents your system processes and how the AI should classify and extract information from them. Each content type includes instructions for the AI on what entities and relationships to look for.Navigate to Admin > Model & Define > Artifact Types.
Viewing Content Types
The content types page lists all configured types with:
Content type name
Number of entity types associated
Number of relationship types associated
Compatibility status — valid, stale, invalid, or pending review against the current ontology
revision (see Ontology Compatibility)
Created and last modified dates
Creating a Content Type
Click Add Artifact Type to open the editor on a new content type. Creating and editing use the
same editor; the older form editor, and its New Editor toggle, have been removed. Switch between
its Multiple View, Json and Canvas views in the header. The Multiple View has two tabs:
Basic Information — the Name, a descriptive name for the document category (e.g.,
“Contracts”, “Proposals”, “Meeting Notes”); a Description; the Classification Instructions,
guidance for the AI on how to identify documents of this type; and the Ingestion extraction
settings (below)
Entities & Relationships — which entity types to extract from these documents, with their
attributes, and which relationships to identify between them
To get a first draft instead of an empty editor, ask the copilot from the
editor: attach a few sample documents and it proposes the details, entity types, attributes and
relationships as a card that you apply and save yourself.
Ingestion extraction policy
On the Basic Information tab, the Ingestion extraction section controls how deeply ingestion
uses LLMs for this content type:
Default mode — full, metadata_and_snippet, or metadata_only
Primary model tier — large, medium, or small for primary extraction
Validation pass — optional secondary LLM pass (off by default for metadata-only Excel)
Excel overrides — separate mode for spreadsheets
See Extraction Policy for mode behavior, system limits, and filter
overrides.
Entity and relationship attributes
Entity attributes are chosen from the ontology per entity type. You select which attributes apply,
edit extraction instructions (defaults come from the ontology unless you override them), and set
whether an attribute is required.Relationship attributes follow the same idea:
Attributes available on a relationship come from the ontology definition for that triple
(source entity type, relationship type, target entity type).
You pick attributes from a dropdown — you do not type arbitrary names; types come from the
ontology (shown read-only).
Extraction instructions default from the ontology and can be overridden per content type for
document-specific wording.
Relationship attributes are included in extraction prompts so the model can fill an attributes
object on each extracted edge when the document supports values.See also: Relationship attributes (architecture).To preview which ontology nodes, relationships, and attributes a content type uses, open
Ontology and select that type from the toolbar dropdown. Unused nodes and
relationships are hidden; unused attributes are greyed out. That filter is view-only and does not
change the content type or the ontology.
Test Ingestion
Test Ingestion (dry run): try a file before you ingest. To test an ingestion by uploading a file, open Admin > Model & Define > Artifact Types and click Test Ingestion at the top right of the list, to the left of Add Artifact Type. Test Ingestion is a button on the list, not on a single artifact type. A window titled Test Ingestion (Dry Run) opens: upload a file there and it shows how Experio classifies the file and which entities and relationships it extracts. A test writes nothing to the knowledge graph, so you can try as many files as you like before you ingest real data. The short version has a page of its own: Test Ingestion.Everyone who can open the list sees the button. Running a test needs write access to Graph Managers (a super-admin account has it too); with read access only, the run is refused.
Click Test Ingestion at the top right of the list.
Choose the Mode:
Classify & extract — full processing: classification, then entity extraction
Only classify — test classification without extraction
Only extract — test entity extraction for one artifact type, without classification
Under Allowed Content Types, tick the artifact types the file may be classified as. Only extract needs exactly one.
Optionally set Max Pages, the number of pages used to classify the file (empty: 3 pages; -1: the whole document).
Choose the file and click Run Test. Cancel stops a run.
Review the results:
Test Results
The test results display:
Classification Scores — Confidence scores for each content type, with the selected type highlighted
Entities Table — Extracted entities showing Type, Name, and Attributes
Relationships Table — Extracted relationships showing Source, Type, Target, and Attributes
(key/value pairs returned by extraction when present)
Raw JSON — Full raw output for debugging
A sample that is a zip inside is refused unread if it expands to more than 200 MB when unzipped,
whatever its extension: a Word, PowerPoint or Excel file (.docx, .pptx, .xlsx, .xlsm) is one,
and so is a zip under any other name. The test then fails with the file expands to … MB when
unzipped, more than the 200 MB limit. The fallback parser is never given a sample with a single
part over 100 MB either, whether it runs after the main parser or first (one part of the file
expands to …).A sample that passes is read first on the API server, outside the server’s own process, with no OCR:
by the main parser, then by the fallback parser if the main one reads nothing. Each runs in a child
process the server watches (the main parser runs on Kreuzberg’s own server instead when
KREUZBERG_MODE is api). A picture (.png, .jpg, .tif and the other image formats) is the
exception: only OCR can read one, so it is read by OCR in the same kind of child process, whatever its
size, and it is never handed to the background parser (which reads without OCR and would find no words in
it). Because nothing else can read it, its child process may use at least 1,024 MB and 300 seconds, more
than the limits below, and a picture that needs more fails with this file is too large to read here.A sample the API server should not read, or cannot read, goes to the
background parser instead of failing:
A file over ASYNC_PARSE_PRECHECK_MAX_FILE_MB (1 MB by default), or a spreadsheet over
ASYNC_PARSE_PRECHECK_MAX_SPREADSHEET_MB (0 by default, so every spreadsheet), is not read on the
server at all (a picture, above, is never judged by its size).
A reading in a child process is stopped, and its file handed over, when it needs more memory than
UPLOAD_EXTRACTION_MAX_MEMORY_MB (512 MB by default), takes longer than
UPLOAD_EXTRACTION_TIMEOUT_SECONDS (60 seconds by default, for each of the two parsers), or finds the
server’s container or machine with less than 768 MB of memory left.
A PDF whose pages are pictures (fewer than 60 letters and digits a page on average) is a scan. The
background parser reads it by OCR, without asking.
While the background parser has the sample, the Run Test button reads Waiting for the parser…, and a
line under the buttons says where the file is: queued for the parser (which reads large files and scans in
the background and can take a few minutes), being read, queued for OCR, or being read with OCR. Click
Cancel, or close the window, to stop the test: the file the parser was reading for it is cancelled too.
The test waits as long as the server does, up to the queue wait plus the parser’s reading and OCR limits
(about two hours with the default settings), and then fails with The parser did not finish reading this file
within N minutes. Try again later, or test with a smaller file. A sample counts against the limit on
background files that every person has (ASYNC_PARSE_MAX_QUEUED_PER_USER, 10 by default). Over it, the test
fails with N of your files are already waiting to be read (at most 10 at a time); wait for some of them to
finish (Jobs list), then run the test again. The run shows in
Jobs & Monitoring as an Async parse job whose source
is Test ingestion.A picture that needs more memory or time than the limits above still fails with this file is too large to
read here … or reading this file took too long …, and a zip that expands too far is refused, as above.
After a reading on the server is stopped, no other parser on the server tries the sample. Only the first
10,000,000 characters of a sample’s text are kept for the test.
Run test ingestion with representative documents before activating a content type in production. This helps fine-tune classification instructions and entity extraction rules.
Editing Content Types
Click any content type to open its editor. Changes to a content type affect how future documents are processed — previously processed documents are not retroactively re-processed.The editor shows a compatibility panel when this type drifted from the ontology. Fix the entities,
attributes, or relationships so they match the current schema, then Re-validate. After an ontology
rename that already looks correct, Mark as reviewed returns the type to valid. You can also ask
the copilot to do either (see Asking the copilot).In the editor, a Save re-validates the type for you when its status was not valid before the
Save (invalid, stale or pending review): a fix stops blocking scans as soon as it is saved, and a type
the fix did not repair shows its issues again. A Save of a valid type is not re-checked.
An invalid content type blocks scans for every data source that uses it. Stale types warn in the
admin UI but do not block ingestion.
The admin sidebar labels this page Artifact Types; this guide uses Content Types for the same
feature.
Asking the copilot
The Admin Copilot has a page pack for these pages. Open it with the
Copilot button or ⌘J. It knows the saved ontology, the other content types and the files you
attach in the chat, and it can check what ingestion wrote to the graph (see
The knowledge-model copilot). For a saved
content type it is also given the issue codes behind its status, from the last check against the
saved ontology (for example ATTRIBUTE_NOT_IN_ONTOLOGY StatusReport.percent_x), and is told to
explain an invalid or stale status only from those codes or its own check, never from a guess.In the editor it reads the content type as drawn, including your unsaved edits, and it can
propose changes to it as a card:
Details: the description and the classification instructions. On the create page it can also
set the name: the new content type isn’t saved yet, so the copilot sets the name you ask for like
any other detail (Save’s own check still refuses a name another content type has).
Entity types: add one, change its processing type, whether it attaches the document, or its
description, or remove it. Removing one also removes the relationships that touch it, unless
another entity type on the content type has the same name (see below). Whether an entity type
attaches the document decides what the Ingested list of the parsed-document picker holds (see
The picker).
Attributes: add one, change its extraction instructions or whether it is required, or remove it.
Relationships: add, change or remove one.
It never renames anything else: names come from the ontology, and a saved content type keeps its name.
It never changes the extraction policy, never runs Test Ingestion and never generates
embeddings (you do those on the page), and it never saves or creates a content type. It can tell you
where Test Ingestion is (the button at the top right of the list) and take you there. To re-validate,
mark reviewed or delete a saved one, it makes a page-action card that you confirm (see
Re-validating, reviewing and deleting a content type).
Everything it adds must already be in the saved ontology.
When something is missing, it proposes the ontology change first; you apply it and click Save on
the Ontology page, and then it proposes the content-type change.An edit can only change an entity type or attribute the content type already extracts. When the
copilot tries to change one the content type doesn’t extract yet but the saved ontology defines (for
example industry on Project), the server refuses it with the fix, an add in the ontology’s
spelling carrying the instructions the copilot wrote, and the copilot sends that in the same turn.
One the saved ontology doesn’t define either is refused without that fix.
What the server checks first
Every card is checked on the server before you see it. A proposal that fails goes back to the copilot
to fix, with every problem at once (the size cap, the checks below, and the ontology change it needs
first when there is one), so a large change doesn’t use up its retries one problem at a time:
Classification instructions must be plain sentences, never JSON. When the editor loads a content
type whose instructions are JSON, it reads them as a set of instructions for the whole type and can
replace the entity list with what it finds there. JSON behind an invisible character, such as a
byte-order mark, counts too: the editor ignores the character.
At most one entity type may attach the document, and it has to be Create Only. Create or Match
and Match Only cannot attach. The Ingested list in the parsed-document
picker depends on it: a file is listed there only when its content type has an entity type that
attaches the document (see
The Ingested list is empty after an ingestion).
The name, description and classification instructions can’t be empty, and names can’t repeat.
A name two rows share is ambiguous. An older content type can hold
two entity types with the same name (ignoring case), or two attributes of one entity type with the
same name. A card that names such a row is refused, because the name doesn’t say which one. The
refusal lists each copy’s id: for an entity type, with how many attributes it has and how many of
them have extraction instructions; for an attribute, with the start of its instructions. The copilot is told to remove one copy by its id, the one that holds none of your
instructions, or to ask you which to keep. Removing one copy keeps the other, and the relationships
that name it, and the card says which copy it removes (Remove the copy of entity “StatusReport”
with id …; the other “StatusReport” stays). The first such refusal spends no retry when the
duplicate was already there and it is the card’s only problem.
The result must pass Save’s own checks against the saved ontology.
A card must change something. A card whose result is the content type as it already is (each
edit sets a value it already has, or one edit undoes another) is refused. The copilot is told there
is nothing to apply, to tell you so if you asked for exactly that, and never to propose some other
change in its place.
A change that would put the content type out of step with the saved ontology is refused, and the
copilot is pointed to the ontology change it needs first.
A removal Save would undo is refused. Save puts back the required-upstream chain of an entity
type that matches by similarity (its required upstream parent, that parent’s, and so on, until the
walk reaches an entity type listed on the content type before the one it started from), whatever
the processing type of the entity types in between, and every attribute that an entity type’s
vector index reads (see Save will also add), with the ontology’s default
instructions instead of yours. The copilot is told why, with each chain that pulls the parent in.
To remove a parent, each entity type the refusal names as pulling it in must stop matching by
similarity in the same card; the others need no change. To remove an attribute that a vector index
reads, the ontology’s vector index has to change first.
A problem the content type already had does not block the card. The card lists it separately and says
the change neither causes nor fixes it. The exception is a problem the checks above count as an
error: one Save refuses (such as empty classification instructions), JSON-shaped classification
instructions, or a name two rows share. It blocks every card until a card fixes it (for a shared
name, by removing one copy by its id). The copilot is told
about it without spending a retry, and puts the fix in the same card. When every other problem was
already there, a name another saved content type already has is still named, and spends a retry, if
the change causes it. A new warning, such as a
relationship whose end is not one of the entity types or an attribute with no extraction
instructions, needs your acknowledgement before Apply.
Save will also add
When you click Save, the server adds what the ontology requires on top of what you drew: the
required upstream parent entity types of an entity that matches by similarity, and their parents up
the chain (the walk stops at an entity type listed before the one it started from), with their
relationships, and the attributes its vector index reads. The card lists these
under Save will also add, so they are not a surprise after you save. The copilot can also tell
you what Save will add to the content type as it is now.
Applying a card
The copilot makes one card per content type per turn. A card holds the whole content type as it
would be after the change, made from the editor as it was when you asked. A second card made from
the same editor would undo the first when applied after it. A big change comes as one card, up to
the edits one card carries (150 by default); only a larger one comes over several turns, the next
part once you have applied (and saved) the one before. See
Big changes.
Apply puts the proposed details, entity types and relationships into the editor. Nothing is
saved until you click Save.
Apply replaces the details, entity types and relationships with the card’s version. If the editor
no longer holds what the card was made from — you edited or saved since, another card was applied,
or the page was reloaded onto a changed content type — Apply asks first, because those newer
changes would be replaced too. A card made from exactly what the editor holds applies straight
away, even after you left the page and came back. The exception is an older content type whose
entity types are stored only in its classification instructions: until its first Save in the
editor, every card from an earlier visit asks first.
Undo on the card puts back what was there before, until you edit on top of the applied change.
A card made for another content type can’t be applied here. A card the copilot made for it from
another page has an Open link to that content type’s editor.
Cards for another content type
The copilot can change a content type without its editor being open. On the list page, in another
content type’s editor, on the Ontology page, and on the Taxonomies, Data Mapping, Enrichment Rules
and Matching Strategies pages, it checks the content type you name as saved and makes a card
for it:
The card reads Made for “SOW” (Artifact Types) and has an Open “SOW” link. The link opens
that content type in its editor, with the card ready to apply there.
You apply it in the editor and click Save. It was checked against the content type as saved,
so it is refused once that content type has been saved again since (This artifact type was saved
since this was proposed — ask the copilot again). Any Save counts, even one that only moved things
on the canvas. If the editor has unsaved edits, Apply asks first, because the card replaces them.
It passes the same server checks as a card made in the editor, against the saved content type and
the saved ontology.
From every one of these pages it can also check a saved content type and tell you what Save will add
to it. See
Knowledge-model pages share their tools.Reading and checking need the Graph Managers role (read); proposing needs write access too.
Re-validating, reviewing and deleting a content type
Ask the copilot to re-validate a content type, mark it reviewed or delete it, and it makes a
page-action card for the Artifact Types list, from the editor or from any knowledge-model page.
The copilot never does it: Apply on the list opens a confirmation, and only your own click on its
confirm button performs the action, under your account (see
Page-action cards). It needs Graph Managers write
access. Cancel leaves the card open, and once you confirm, the card reads Saved.
Re-validate is offered when the status is not valid. The confirmation shows what the check
finds now against the saved ontology: that the type becomes valid and ingestion can use it again,
how many issues remain (with the first one), or that it stays stale. A content type that a
re-check would leave as it is, with the same status and issues, gets no card: fix it first.
Mark reviewed is offered when the status is stale or pending review and the ontology has a
saved revision. It is the panel’s own Mark as reviewed: it re-runs the same check and saves the
result.
Delete is destructive. The confirmation lists what goes with the content type, counted when the
card was made: the matching strategies bound to it. The data sources and data-source filters that
list it only lose it and stay. It names those data sources, filters and strategies only to someone
who can read them (Data Source Managers for the first two, Process Managers for strategies);
everyone else gets the counts and a line saying why they are not named. Nothing in the graph is
removed: what was ingested as this type stays.
The card is refused if the content type was saved or its status changed since it was made, and,
for a review card, if the ontology was saved since.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/schema.json","name":"Experio Documentation","colors":{"primary":"#5A338A","light":"#9575CD","dark":"#5A338A"},"logo":{"light":"https://mintcdn.com/experiolabs/tI7TL1-DN6v_muWO/logo/experio-large-transparent.svg?fit=max\u0026auto=format\u0026n=tI7TL1-DN6v_muWO\u0026q=85\u0026s=14d019caed8ec6ef0c3c2a22ce2747d9","dark":"https://mintcdn.com/experiolabs/tI7TL1-DN6v_muWO/logo/experio-large-transparent-dark.svg?fit=max\u0026auto=format\u0026n=tI7TL1-DN6v_muWO\u0026q=85\u0026s=df606419df3dda0416eb836267be5d62","href":"https://www.experiolabs.ai"},"favicon":"https://mintcdn.com/experiolabs/tI7TL1-DN6v_muWO/favicon.svg?fit=max\u0026auto=format\u0026n=tI7TL1-DN6v_muWO\u0026q=85\u0026s=4d4f9001b699709ede118026fe316f7d","background":{"decoration":"grid"},"fonts":{"family":"Lato"},"styling":{"latex":true},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"experiolabs","hasAudioNarration":false,"actualSubdomain":"experiolabs","customDomains":["docs.experio.cloud"],"gitSource":{"type":"github","owner":"experio-ai","repo":"experio","deployBranch":"main","contentDirectory":"docs","isPrivate":true,"mountPath":"","label":""},"entitlements":{},"buildId":"6af7a21821f70eaf9e5b07e1","clientVersion":"0.0.4131","searchFilterCounts":[{"language":"default","tag":"Admin Guide","count":40},{"language":"default","tag":"Implementation Guide","count":22},{"language":"default","tag":"Knowledge Graph","count":12},{"language":"default","tag":"User Guide","count":12},{"language":"default","tag":"Data Sources","count":11},{"language":"default","tag":"Workshops","count":11},{"language":"default","tag":"Using Experio","count":10},{"language":"default","tag":"Settings","count":7},{"language":"default","tag":"Monitoring","count":5},{"language":"default","tag":"Getting Started","count":5}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":true},"customCss":[{"filePath":"Experio Dashboard Mockups/_ds/nocturne-75e4003d-2137-43aa-af77-e87cf9181b02/styles.css","content":"/* cyrillic-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');\n unicode-range: U+1F00-1FFF;\n}\n/* greek */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');\n unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;\n}\n/* vietnamese */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');\n unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');\n unicode-range: U+1F00-1FFF;\n}\n/* greek */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');\n unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;\n}\n/* vietnamese */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');\n unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');\n unicode-range: U+1F00-1FFF;\n}\n/* greek */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');\n unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;\n}\n/* vietnamese */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');\n unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 700;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 700;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 700;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');\n unicode-range: U+1F00-1FFF;\n}\n/* greek */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 700;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');\n unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;\n}\n/* vietnamese */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 700;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');\n unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 700;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 700;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n:root{--color-bg: #161826;--color-surface: #232532;--color-text: #e9e9ed;--color-accent: #9184d9;--color-accent-2: #a7a1db;--color-divider: color-mix(in srgb, #e9e9ed 16%, transparent);--color-neutral-100: #f3f5fe;--color-neutral-200: #e4e7f5;--color-neutral-300: #cfd3e5;--color-neutral-400: #b2b6ca;--color-neutral-500: #9397ab;--color-neutral-600: #75798c;--color-neutral-700: #595d6c;--color-neutral-800: #3f424d;--color-neutral-900: #292b31;--color-accent-100: #f5f4ff;--color-accent-200: #e7e5fe;--color-accent-300: #d2cefd;--color-accent-400: #b5abfc;--color-accent-500: #968ae0;--color-accent-600: #796cbf;--color-accent-700: #5d5294;--color-accent-800: #423a6a;--color-accent-900: #2b2741;--color-accent-2-100: #f5f4ff;--color-accent-2-200: #e7e5fe;--color-accent-2-300: #d2cefd;--color-accent-2-400: #b5afe8;--color-accent-2-500: #9690c9;--color-accent-2-600: #7972a9;--color-accent-2-700: #5c5783;--color-accent-2-800: #423e5d;--color-accent-2-900: #2b293a;--color-section: #262a60;--color-section-glow: #353b80;--color-section-ghost: #4c5397;--font-heading: \"Inter\", system-ui, sans-serif;--font-heading-weight: 500;--font-body: \"Inter\", system-ui, sans-serif;--space-1: 2.8px;--space-2: 5.6px;--space-3: 8.4px;--space-4: 11.2px;--space-6: 16.8px;--space-8: 22.4px;--radius-sm: 4px;--radius-md: 8px;--radius-lg: 14px;--shadow-sm: 0 0 0 1px #3f424d;--shadow-md: 0 0 0 1px #595d6c, 0 6px 18px rgba(0,0,0,0.55);--shadow-lg: 0 0 0 1px #9397ab, 0 16px 40px rgba(0,0,0,0.65)}body{background:var(--color-bg);color:var(--color-text);font-family:var(--font-body)}h1,h2,h3,h4{font-family:var(--font-heading);font-weight:var(--font-heading-weight)}.lighten{mix-blend-mode:lighten;background-color:transparent}*,*::before,*::after{box-sizing:border-box}body{margin:0;font-size:15px;line-height:1.55;font-weight:400}h1,h2,h3,h4,h5,h6{font-family:var(--font-heading);font-weight:var(--font-heading-weight);line-height:1.12;letter-spacing:-0.015em;margin:0 0 var(--space-2)}h1{font-size:42px}h2{font-size:32px}h3{font-size:25px}h4{font-size:20px}h5{font-size:16px}h6{font-size:13px}h6{letter-spacing:0.08em;text-transform:uppercase}p{margin:0 0 var(--space-3)}a{color:var(--color-accent);text-underline-offset:3px}img{display:block;max-width:100%}figure{margin:0}figcaption{font-size:11px;margin-top:var(--space-1);color:color-mix(in srgb, var(--color-text) 55%, transparent)}.text-muted{color:color-mix(in srgb, var(--color-text) 55%, transparent)}:focus{outline:none}:focus-visible{outline:2px solid var(--color-accent);outline-offset:2px}::selection{background:color-mix(in srgb, var(--color-accent) 30%, transparent)}.hr{height:1px;border:0;margin:var(--space-4) 0;background:linear-gradient(to right,\n transparent, var(--color-divider) 48px,\n var(--color-divider) calc(100% - 48px), transparent)}.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;cursor:pointer;text-decoration:none;font-family:var(--font-heading);font-weight:var(--font-heading-weight);font-size:14px;line-height:1.2;color:var(--color-text);background:transparent;border:1px solid transparent;padding:var(--space-2) calc(var(--space-3) * 1.2);border-radius:var(--radius-md)}.btn svg{display:block}.btn:disabled{opacity:0.45;cursor:not-allowed}.btn-primary{color:var(--color-accent);border-color:var(--color-accent)}.btn-primary:hover{background:color-mix(in srgb, var(--color-accent) 12%, transparent)}.btn-primary:active{background:color-mix(in srgb, var(--color-accent) 22%, transparent)}.btn-secondary{border-color:var(--color-divider)}.btn-secondary:hover{background:color-mix(in srgb, var(--color-text) 7%, transparent)}.btn-secondary:active{background:color-mix(in srgb, var(--color-text) 14%, transparent)}.btn-ghost{color:var(--color-accent);padding-inline:var(--space-1)}.btn-ghost:hover{background:color-mix(in srgb, var(--color-accent) 10%, transparent)}.btn-ghost:active{background:color-mix(in srgb, var(--color-accent) 18%, transparent)}.btn-icon{width:36px;height:36px;padding:0}.btn-block{width:100%;margin-top:var(--space-2)}.field>label{display:block;font-size:12px;margin-bottom:5px;color:color-mix(in srgb, var(--color-text) 70%, transparent)}.input{width:100%;min-height:36px;padding:6px 10px;font:inherit;font-size:14px;color:var(--color-text);caret-color:var(--color-accent);background:var(--color-surface);border:1px solid var(--color-divider);border-radius:var(--radius-md)}.input:hover{border-color:color-mix(in srgb, var(--color-text) 45%, transparent)}.input:focus-visible{border-color:var(--color-accent);outline-offset:0}textarea.input{min-height:90px;resize:vertical}.radio{display:inline-flex;align-items:center;gap:8px;cursor:pointer;font-size:14px}.radio input,.seg-opt input{position:absolute;opacity:0;width:0;height:0;pointer-events:none}.radio .dot{width:16px;height:16px;flex:none;border-radius:50%;border:1.5px solid var(--color-divider)}.radio:hover .dot{border-color:var(--color-accent)}.radio input:checked+.dot{border-color:var(--color-accent);background:var(--color-accent);box-shadow:inset 0 0 0 4px var(--color-bg)}.radio input:focus-visible+.dot{outline:2px solid var(--color-accent);outline-offset:2px}.seg{display:inline-flex;overflow:hidden;border:1px solid var(--color-divider);border-radius:var(--radius-md)}.seg-opt{display:inline-flex;align-items:center;gap:6px;padding:7px 12px;font-size:13px;cursor:pointer}.seg-opt+.seg-opt{border-left:1px solid var(--color-divider)}.seg-opt:has(input:checked){color:var(--color-accent);box-shadow:inset 0 0 0 1px var(--color-accent)}.seg-opt:not(:has(input:checked)):hover{background:color-mix(in srgb, var(--color-text) 7%, transparent)}.seg-opt:has(input:focus-visible){outline:2px solid var(--color-accent);outline-offset:-2px}.card{display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-3);border-radius:var(--radius-md);background:var(--color-surface)}.card-kicker{font-size:10px;letter-spacing:0.1em;text-transform:uppercase;color:var(--color-accent)}.card-title{font-family:var(--font-heading);font-weight:var(--font-heading-weight);font-size:17px;line-height:1.2}.card-body{margin:0;font-size:13px;opacity:0.8;flex:1}.card-meta{display:flex;align-items:center;gap:6px;font-size:11px;color:color-mix(in srgb, var(--color-text) 50%, transparent)}.elev-sm{box-shadow:var(--shadow-sm)}.elev-md{box-shadow:var(--shadow-md)}.elev-lg{box-shadow:var(--shadow-lg)}.tag{display:inline-flex;align-items:center;font-size:11px;letter-spacing:0.02em;padding:3px 10px;border-radius:calc(var(--radius-md) * 0.75)}.tag-accent{background:var(--color-accent-800);color:var(--color-accent-100)}.tag-accent-2{background:var(--color-accent-2-800);color:var(--color-accent-2-100)}.tag-neutral{background:var(--color-neutral-800);color:var(--color-neutral-100)}.tag-outline{border:1px solid var(--color-accent);color:var(--color-accent)}.nav{display:flex;align-items:center;gap:var(--space-4);padding:var(--space-3) var(--space-4);border-bottom:none}.nav-brand{font-family:var(--font-heading);font-weight:var(--font-heading-weight);font-size:18px;margin-right:auto}.nav a{color:inherit;text-decoration:none;font-size:14px}.nav a:hover,.nav a[aria-current=\"page\"]{color:var(--color-accent)}.table{width:100%;border-collapse:collapse;font-size:14px}.table th{text-align:left;font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:color-mix(in srgb, var(--color-text) 60%, transparent);padding:var(--space-2);border-bottom:1px solid transparent}.table td{padding:var(--space-2);border-bottom:1px solid transparent}.table thead tr{background:linear-gradient(to right,\n transparent, var(--color-divider) 48px,\n var(--color-divider) calc(100% - 48px), transparent) no-repeat bottom / 100% 1px}.table tbody tr{background:linear-gradient(to right,\n transparent, color-mix(in srgb, var(--color-text) 8%, transparent) 48px,\n color-mix(in srgb, var(--color-text) 8%, transparent) calc(100% - 48px), transparent) no-repeat bottom / 100% 1px}.table tbody tr:hover{background:linear-gradient(color-mix(in srgb, var(--color-text) 4%, transparent),\n color-mix(in srgb, var(--color-text) 4%, transparent)) no-repeat 0 0 / 100% 100%,\n linear-gradient(to right,\n transparent, color-mix(in srgb, var(--color-text) 8%, transparent) 48px,\n color-mix(in srgb, var(--color-text) 8%, transparent) calc(100% - 48px), transparent) no-repeat bottom / 100% 1px}.dialog-backdrop{position:fixed;inset:0;display:grid;place-items:center;padding:var(--space-4);background:color-mix(in srgb, var(--color-neutral-900) 50%, transparent)}.dialog{width:min(440px, 100%);display:flex;flex-direction:column;gap:var(--space-3);padding:var(--space-4);border-radius:var(--radius-lg);background:var(--color-surface);box-shadow:var(--shadow-lg)}.dialog-title{font-family:var(--font-heading);font-weight:var(--font-heading-weight);font-size:20px}.dialog-body{font-size:14px;opacity:0.85}.dialog-actions{display:flex;justify-content:flex-end;gap:var(--space-2);margin-top:var(--space-2)}"}],"page":{"pagePath":"admin-guide/content-types","slug":"/admin-guide/content-types","pageMetadata":{"title":"Content Types","description":"Define document types and control how they are processed during ingestion","href":"/admin-guide/content-types"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Define document types and control how they are processed during ingestion\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,em:`em`,li:`li`,ol:`ol`,p:`p`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{Heading,Tip,Warning}=_components;if(!Heading)_missingMdxReference(`Heading`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(Heading,{level:`2`,id:`overview`,children:`Overview`}),`\n`,_jsx(_components.p,{children:`Content types define the categories of documents your system processes and how the AI should classify and extract information from them. Each content type includes instructions for the AI on what entities and relationships to look for.`}),`\n`,_jsxs(_components.p,{children:[`Navigate to `,_jsx(_components.strong,{children:`Admin > Model \u0026 Define > Artifact Types`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`viewing-content-types`,children:`Viewing Content Types`}),`\n`,_jsx(_components.p,{children:`The content types page lists all configured types with:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Content type name`}),`\n`,_jsx(_components.li,{children:`Number of entity types associated`}),`\n`,_jsx(_components.li,{children:`Number of relationship types associated`}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Compatibility status`}),` — valid, stale, invalid, or pending review against the current ontology\nrevision (see `,_jsx(_components.a,{href:`/admin-guide/ontology-compatibility`,children:`Ontology Compatibility`}),`)`]}),`\n`,_jsx(_components.li,{children:`Created and last modified dates`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`creating-a-content-type`,children:`Creating a Content Type`}),`\n`,_jsxs(_components.p,{children:[`Click `,_jsx(_components.strong,{children:`Add Artifact Type`}),` to open the editor on a new content type. Creating and editing use the\nsame editor; the older form editor, and its `,_jsx(_components.strong,{children:`New Editor`}),` toggle, have been removed. Switch between\nits `,_jsx(_components.strong,{children:`Multiple View`}),`, `,_jsx(_components.strong,{children:`Json`}),` and `,_jsx(_components.strong,{children:`Canvas`}),` views in the header. The `,_jsx(_components.strong,{children:`Multiple View`}),` has two tabs:`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Basic Information`}),` — the `,_jsx(_components.strong,{children:`Name`}),`, a descriptive name for the document category (e.g.,\n“Contracts”, “Proposals”, “Meeting Notes”); a `,_jsx(_components.strong,{children:`Description`}),`; the `,_jsx(_components.strong,{children:`Classification Instructions`}),`,\nguidance for the AI on how to identify documents of this type; and the `,_jsx(_components.strong,{children:`Ingestion extraction`}),`\nsettings (below)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Entities \u0026 Relationships`}),` — which entity types to extract from these documents, with their\nattributes, and which relationships to identify between them`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`To get a first draft instead of an empty editor, ask the `,_jsx(_components.a,{href:`#asking-the-copilot`,children:`copilot`}),` from the\neditor: attach a few sample documents and it proposes the details, entity types, attributes and\nrelationships as a card that you apply and save yourself.`]}),`\n`,_jsx(Heading,{level:`3`,id:`ingestion-extraction-policy`,children:`Ingestion extraction policy`}),`\n`,_jsxs(_components.p,{children:[`On the `,_jsx(_components.strong,{children:`Basic Information`}),` tab, the `,_jsx(_components.strong,{children:`Ingestion extraction`}),` section controls how deeply ingestion\nuses LLMs for this content type:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Default mode`}),` — `,_jsx(_components.code,{children:`full`}),`, `,_jsx(_components.code,{children:`metadata_and_snippet`}),`, or `,_jsx(_components.code,{children:`metadata_only`})]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Primary model tier`}),` — `,_jsx(_components.code,{children:`large`}),`, `,_jsx(_components.code,{children:`medium`}),`, or `,_jsx(_components.code,{children:`small`}),` for primary extraction`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Validation pass`}),` — optional secondary LLM pass (off by default for metadata-only Excel)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Excel overrides`}),` — separate mode for spreadsheets`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See `,_jsx(_components.a,{href:`/admin-guide/extraction-policy`,children:`Extraction Policy`}),` for mode behavior, system limits, and filter\noverrides.`]}),`\n`,_jsx(Heading,{level:`3`,id:`entity-and-relationship-attributes`,children:`Entity and relationship attributes`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Entity attributes`}),` are chosen from the ontology per entity type. You select which attributes apply,\nedit extraction instructions (defaults come from the ontology unless you override them), and set\nwhether an attribute is required.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Relationship attributes`}),` follow the same idea:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Attributes available on a relationship come from the `,_jsx(_components.strong,{children:`ontology definition for that triple`}),`\n(source entity type, relationship type, target entity type).`]}),`\n`,_jsxs(_components.li,{children:[`You pick attributes from a dropdown — you do `,_jsx(_components.strong,{children:`not`}),` type arbitrary names; `,_jsx(_components.strong,{children:`types`}),` come from the\nontology (shown read-only).`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Extraction instructions`}),` default from the ontology and can be overridden per content type for\ndocument-specific wording.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Relationship attributes are included in extraction prompts so the model can fill an `,_jsx(_components.code,{children:`attributes`}),`\nobject on each extracted edge when the document supports values.`]}),`\n`,_jsxs(_components.p,{children:[`See also: `,_jsx(_components.a,{href:`/architecture/relationship-attributes`,children:`Relationship attributes (architecture)`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`To preview which ontology nodes, relationships, and attributes a content type uses, open\n`,_jsx(_components.a,{href:`/admin-guide/ontology`,children:`Ontology`}),` and select that type from the toolbar dropdown. Unused nodes and\nrelationships are hidden; unused attributes are greyed out. That filter is view-only and does not\nchange the content type or the ontology.`]}),`\n`,_jsx(Heading,{level:`2`,id:`test-ingestion`,children:`Test Ingestion`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Test Ingestion (dry run): try a file before you ingest.`}),` To test an ingestion by uploading a file, open `,_jsx(_components.strong,{children:`Admin > Model \u0026 Define > Artifact Types`}),` and click `,_jsx(_components.strong,{children:`Test Ingestion`}),` at the top right of the list, to the left of `,_jsx(_components.strong,{children:`Add Artifact Type`}),`. Test Ingestion is a button on the list, not on a single artifact type. A window titled `,_jsx(_components.strong,{children:`Test Ingestion (Dry Run)`}),` opens: upload a file there and it shows how Experio classifies the file and which entities and relationships it extracts. A test writes nothing to the knowledge graph, so you can try as many files as you like before you ingest real data. The short version has a page of its own: `,_jsx(_components.a,{href:`/admin-guide/test-ingestion`,children:`Test Ingestion`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`Everyone who can open the list sees the button. Running a test needs write access to `,_jsx(_components.strong,{children:`Graph Managers`}),` (a super-admin account has it too); with read access only, the run is refused.`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`Test Ingestion`}),` at the top right of the list.`]}),`\n`,_jsxs(_components.li,{children:[`Choose the `,_jsx(_components.strong,{children:`Mode`}),`:`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Classify \u0026 extract`}),` — full processing: classification, then entity extraction`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Only classify`}),` — test classification without extraction`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Only extract`}),` — test entity extraction for one artifact type, without classification`]}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Under `,_jsx(_components.strong,{children:`Allowed Content Types`}),`, tick the artifact types the file may be classified as. `,_jsx(_components.strong,{children:`Only extract`}),` needs exactly one.`]}),`\n`,_jsxs(_components.li,{children:[`Optionally set `,_jsx(_components.strong,{children:`Max Pages`}),`, the number of pages used to classify the file (empty: 3 pages; `,_jsx(_components.code,{children:`-1`}),`: the whole document).`]}),`\n`,_jsxs(_components.li,{children:[`Choose the file and click `,_jsx(_components.strong,{children:`Run Test`}),`. `,_jsx(_components.strong,{children:`Cancel`}),` stops a run.`]}),`\n`,_jsx(_components.li,{children:`Review the results:`}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`test-results`,children:`Test Results`}),`\n`,_jsx(_components.p,{children:`The test results display:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Classification Scores`}),` — Confidence scores for each content type, with the selected type highlighted`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Entities Table`}),` — Extracted entities showing Type, Name, and Attributes`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Relationships Table`}),` — Extracted relationships showing Source, Type, Target, and `,_jsx(_components.strong,{children:`Attributes`}),`\n(key/value pairs returned by extraction when present)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Raw JSON`}),` — Full raw output for debugging`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`A sample that is a zip inside is refused unread if it expands to more than 200 MB when unzipped,\nwhatever its extension: a Word, PowerPoint or Excel file (`,_jsx(_components.code,{children:`.docx`}),`, `,_jsx(_components.code,{children:`.pptx`}),`, `,_jsx(_components.code,{children:`.xlsx`}),`, `,_jsx(_components.code,{children:`.xlsm`}),`) is one,\nand so is a zip under any other name. The test then fails with `,_jsx(_components.em,{children:`the file expands to … MB when\nunzipped, more than the 200 MB limit`}),`. The fallback parser is never given a sample with a single\npart over 100 MB either, whether it runs after the main parser or first (`,_jsx(_components.em,{children:`one part of the file\nexpands to …`}),`).`]}),`\n`,_jsxs(_components.p,{children:[`A sample that passes is read first on the API server, outside the server’s own process, with no OCR:\nby the main parser, then by the fallback parser if the main one reads nothing. Each runs in a child\nprocess the server watches (the main parser runs on Kreuzberg’s own server instead when\n`,_jsx(_components.code,{children:`KREUZBERG_MODE`}),` is `,_jsx(_components.code,{children:`api`}),`). A picture (`,_jsx(_components.code,{children:`.png`}),`, `,_jsx(_components.code,{children:`.jpg`}),`, `,_jsx(_components.code,{children:`.tif`}),` and the other image formats) is the\nexception: only OCR can read one, so it is read by OCR in the same kind of child process, whatever its\nsize, and it is never handed to the background parser (which reads without OCR and would find no words in\nit). Because nothing else can read it, its child process may use at least 1,024 MB and 300 seconds, more\nthan the limits below, and a picture that needs more fails with `,_jsx(_components.em,{children:`this file is too large to read here`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`A sample the API server should not read, or cannot read, goes to the\n`,_jsx(_components.a,{href:`/admin-guide/async-document-parsing`,children:`background parser`}),` instead of failing:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`A file over `,_jsx(_components.code,{children:`ASYNC_PARSE_PRECHECK_MAX_FILE_MB`}),` (1 MB by default), or a spreadsheet over\n`,_jsx(_components.code,{children:`ASYNC_PARSE_PRECHECK_MAX_SPREADSHEET_MB`}),` (0 by default, so every spreadsheet), is not read on the\nserver at all (a picture, above, is never judged by its size).`]}),`\n`,_jsxs(_components.li,{children:[`A reading in a child process is stopped, and its file handed over, when it needs more memory than\n`,_jsx(_components.code,{children:`UPLOAD_EXTRACTION_MAX_MEMORY_MB`}),` (512 MB by default), takes longer than\n`,_jsx(_components.code,{children:`UPLOAD_EXTRACTION_TIMEOUT_SECONDS`}),` (60 seconds by default, for each of the two parsers), or finds the\nserver’s container or machine with less than 768 MB of memory left.`]}),`\n`,_jsx(_components.li,{children:`A PDF whose pages are pictures (fewer than 60 letters and digits a page on average) is a scan. The\nbackground parser reads it by OCR, without asking.`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`While the background parser has the sample, the `,_jsx(_components.strong,{children:`Run Test`}),` button reads `,_jsx(_components.em,{children:`Waiting for the parser…`}),`, and a\nline under the buttons says where the file is: queued for the parser (which reads large files and scans in\nthe background and can take a few minutes), being read, queued for OCR, or being read with OCR. Click\n`,_jsx(_components.strong,{children:`Cancel`}),`, or close the window, to stop the test: the file the parser was reading for it is cancelled too.\nThe test waits as long as the server does, up to the queue wait plus the parser’s reading and OCR limits\n(about two hours with the default settings), and then fails with `,_jsx(_components.em,{children:`The parser did not finish reading this file\nwithin N minutes. Try again later, or test with a smaller file.`}),` A sample counts against the limit on\nbackground files that every person has (`,_jsx(_components.code,{children:`ASYNC_PARSE_MAX_QUEUED_PER_USER`}),`, 10 by default). Over it, the test\nfails with `,_jsx(_components.em,{children:`N of your files are already waiting to be read (at most 10 at a time); wait for some of them to\nfinish (Jobs list), then run the test again.`}),` The run shows in\n`,_jsx(_components.a,{href:`/admin-guide/jobs-monitoring#async-parse-jobs`,children:`Jobs \u0026 Monitoring`}),` as an `,_jsx(_components.strong,{children:`Async parse`}),` job whose source\nis `,_jsx(_components.em,{children:`Test ingestion`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`A picture that needs more memory or time than the limits above still fails with `,_jsx(_components.em,{children:`this file is too large to\nread here …`}),` or `,_jsx(_components.em,{children:`reading this file took too long …`}),`, and a zip that expands too far is refused, as above.\nAfter a reading on the server is stopped, no other parser on the server tries the sample. Only the first\n10,000,000 characters of a sample’s text are kept for the test.`]}),`\n`,_jsx(Tip,{children:_jsx(_components.p,{children:`Run test ingestion with representative documents before activating a content type in production. This helps fine-tune classification instructions and entity extraction rules.`})}),`\n`,_jsx(Heading,{level:`2`,id:`editing-content-types`,children:`Editing Content Types`}),`\n`,_jsx(_components.p,{children:`Click any content type to open its editor. Changes to a content type affect how future documents are processed — previously processed documents are not retroactively re-processed.`}),`\n`,_jsxs(_components.p,{children:[`The editor shows a `,_jsx(_components.strong,{children:`compatibility`}),` panel when this type drifted from the ontology. Fix the entities,\nattributes, or relationships so they match the current schema, then `,_jsx(_components.strong,{children:`Re-validate`}),`. After an ontology\nrename that already looks correct, `,_jsx(_components.strong,{children:`Mark as reviewed`}),` returns the type to valid. You can also ask\nthe copilot to do either (see `,_jsx(_components.a,{href:`#asking-the-copilot`,children:`Asking the copilot`}),`).`]}),`\n`,_jsxs(_components.p,{children:[`In the editor, a `,_jsx(_components.strong,{children:`Save`}),` re-validates the type for you when its status was not valid before the\nSave (invalid, stale or pending review): a fix stops blocking scans as soon as it is saved, and a type\nthe fix did not repair shows its issues again. A Save of a valid type is not re-checked.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`An `,_jsx(_components.strong,{children:`invalid`}),` content type blocks scans for every data source that uses it. Stale types warn in the\nadmin UI but do not block ingestion.`]})}),`\n`,_jsxs(_components.p,{children:[`The admin sidebar labels this page `,_jsx(_components.strong,{children:`Artifact Types`}),`; this guide uses `,_jsx(_components.strong,{children:`Content Types`}),` for the same\nfeature.`]}),`\n`,_jsx(Heading,{level:`2`,id:`asking-the-copilot`,children:`Asking the copilot`}),`\n`,_jsxs(_components.p,{children:[`The `,_jsx(_components.a,{href:`/admin-guide/admin-copilot`,children:`Admin Copilot`}),` has a page pack for these pages. Open it with the\n`,_jsx(_components.strong,{children:`Copilot`}),` button or `,_jsx(_components.strong,{children:`⌘J`}),`. It knows the saved ontology, the other content types and the files you\nattach in the chat, and it can check what ingestion wrote to the graph (see\n`,_jsx(_components.a,{href:`/admin-guide/admin-copilot#the-knowledge-model-copilot`,children:`The knowledge-model copilot`}),`). For a saved\ncontent type it is also given the issue codes behind its status, from the last check against the\nsaved ontology (for example `,_jsx(_components.code,{children:`ATTRIBUTE_NOT_IN_ONTOLOGY StatusReport.percent_x`}),`), and is told to\nexplain an invalid or stale status only from those codes or its own check, never from a guess.`]}),`\n`,_jsx(_components.p,{children:`In the editor it reads the content type as drawn, including your unsaved edits, and it can\npropose changes to it as a card:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Details:`}),` the description and the classification instructions. On the create page it can also\nset the name: the new content type isn’t saved yet, so the copilot sets the name you ask for like\nany other detail (Save’s own check still refuses a name another content type has).`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Entity types:`}),` add one, change its processing type, whether it attaches the document, or its\ndescription, or remove it. Removing one also removes the relationships that touch it, unless\nanother entity type on the content type has the same name (see below). Whether an entity type\nattaches the document decides what the `,_jsx(_components.strong,{children:`Ingested`}),` list of the parsed-document picker holds (see\n`,_jsx(_components.a,{href:`/admin-guide/async-document-parsing#the-picker`,children:`The picker`}),`).`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Attributes:`}),` add one, change its extraction instructions or whether it is required, or remove it.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Relationships:`}),` add, change or remove one.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`It never renames anything else: names come from the ontology, and a saved content type keeps its name.\nIt never changes the extraction policy, never runs `,_jsx(_components.strong,{children:`Test Ingestion`}),` and never generates\nembeddings (you do those on the page), and it never saves or creates a content type. It can tell you\nwhere `,_jsx(_components.strong,{children:`Test Ingestion`}),` is (the button at the top right of the list) and take you there. To re-validate,\nmark reviewed or delete a saved one, it makes a page-action card that you confirm (see\n`,_jsx(_components.a,{href:`#re-validating-reviewing-and-deleting-a-content-type`,children:`Re-validating, reviewing and deleting a content type`}),`).\nEverything it adds must already be in the `,_jsx(_components.strong,{children:`saved`}),` ontology.\nWhen something is missing, it proposes the ontology change first; you apply it and click `,_jsx(_components.strong,{children:`Save`}),` on\nthe Ontology page, and then it proposes the content-type change.`]}),`\n`,_jsxs(_components.p,{children:[`An edit can only `,_jsx(_components.strong,{children:`change`}),` an entity type or attribute the content type already extracts. When the\ncopilot tries to change one the content type doesn’t extract yet but the saved ontology defines (for\nexample `,_jsx(_components.code,{children:`industry`}),` on `,_jsx(_components.code,{children:`Project`}),`), the server refuses it with the fix, an add in the ontology’s\nspelling carrying the instructions the copilot wrote, and the copilot sends that in the same turn.\nOne the saved ontology doesn’t define either is refused without that fix.`]}),`\n`,_jsx(Heading,{level:`3`,id:`what-the-server-checks-first`,children:`What the server checks first`}),`\n`,_jsx(_components.p,{children:`Every card is checked on the server before you see it. A proposal that fails goes back to the copilot\nto fix, with every problem at once (the size cap, the checks below, and the ontology change it needs\nfirst when there is one), so a large change doesn’t use up its retries one problem at a time:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Classification instructions must be plain sentences, never JSON.`}),` When the editor loads a content\ntype whose instructions are JSON, it reads them as a set of instructions for the whole type and can\nreplace the entity list with what it finds there. JSON behind an invisible character, such as a\nbyte-order mark, counts too: the editor ignores the character.`]}),`\n`,_jsxs(_components.li,{children:[`At most one entity type may attach the document, and it has to be `,_jsx(_components.strong,{children:`Create Only`}),`. Create or Match\nand Match Only cannot attach. The `,_jsx(_components.strong,{children:`Ingested`}),` list in the parsed-document\npicker depends on it: a file is listed there only when its content type has an entity type that\nattaches the document (see\n`,_jsx(_components.a,{href:`/admin-guide/async-document-parsing#troubleshooting`,children:`The Ingested list is empty after an ingestion`}),`).`]}),`\n`,_jsx(_components.li,{children:`The name, description and classification instructions can’t be empty, and names can’t repeat.`}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`A name two rows share is ambiguous.`}),` An older content type can hold\ntwo entity types with the same name (ignoring case), or two attributes of one entity type with the\nsame name. A card that names such a row is refused, because the name doesn’t say which one. The\nrefusal lists each copy’s id: for an entity type, with how many attributes it has and how many of\nthem have extraction instructions; for an attribute, with the start of its instructions. The copilot is told to remove one copy by its id, the one that holds none of your\ninstructions, or to ask you which to keep. Removing one copy keeps the other, and the relationships\nthat name it, and the card says which copy it removes (`,_jsx(_components.em,{children:`Remove the copy of entity “StatusReport”\nwith id …; the other “StatusReport” stays`}),`). The first such refusal spends no retry when the\nduplicate was already there and it is the card’s only problem.`]}),`\n`,_jsx(_components.li,{children:`The result must pass Save’s own checks against the saved ontology.`}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`A card must change something.`}),` A card whose result is the content type as it already is (each\nedit sets a value it already has, or one edit undoes another) is refused. The copilot is told there\nis nothing to apply, to tell you so if you asked for exactly that, and never to propose some other\nchange in its place.`]}),`\n`,_jsx(_components.li,{children:`A change that would put the content type out of step with the saved ontology is refused, and the\ncopilot is pointed to the ontology change it needs first.`}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`A removal Save would undo is refused.`}),` Save puts back the required-upstream chain of an entity\ntype that matches by similarity (its required upstream parent, that parent’s, and so on, until the\nwalk reaches an entity type listed on the content type before the one it started from), whatever\nthe processing type of the entity types in between, and every attribute that an entity type’s\nvector index reads (see `,_jsx(_components.a,{href:`#save-will-also-add`,children:`Save will also add`}),`), with the ontology’s default\ninstructions instead of yours. The copilot is told why, with each chain that pulls the parent in.\nTo remove a parent, each entity type the refusal names as pulling it in must stop matching by\nsimilarity in the same card; the others need no change. To remove an attribute that a vector index\nreads, the ontology’s vector index has to change first.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`A problem the content type already had does not block the card. The card lists it separately and says\nthe change neither causes nor fixes it. The exception is a problem the checks above count as an\nerror: one Save refuses (such as empty classification instructions), JSON-shaped classification\ninstructions, or a name two rows share. It blocks every card until a card fixes it (for a shared\nname, by removing one copy by its id). The copilot is told\nabout it without spending a retry, and puts the fix in the same card. When every other problem was\nalready there, a name another saved content type already has is still named, and spends a retry, if\nthe change causes it. A new warning, such as a\nrelationship whose end is not one of the entity types or an attribute with no extraction\ninstructions, needs your acknowledgement before Apply.`}),`\n`,_jsx(Heading,{level:`3`,id:`save-will-also-add`,children:`Save will also add`}),`\n`,_jsxs(_components.p,{children:[`When you click `,_jsx(_components.strong,{children:`Save`}),`, the server adds what the ontology requires on top of what you drew: the\nrequired upstream parent entity types of an entity that matches by similarity, and their parents up\nthe chain (the walk stops at an entity type listed before the one it started from), with their\nrelationships, and the attributes its vector index reads. The card lists these\nunder `,_jsx(_components.strong,{children:`Save will also add`}),`, so they are not a surprise after you save. The copilot can also tell\nyou what Save will add to the content type as it is now.`]}),`\n`,_jsx(Heading,{level:`3`,id:`applying-a-card`,children:`Applying a card`}),`\n`,_jsxs(_components.p,{children:[`The copilot makes `,_jsx(_components.strong,{children:`one card per content type per turn`}),`. A card holds the whole content type as it\nwould be after the change, made from the editor as it was when you asked. A second card made from\nthe same editor would undo the first when applied after it. A big change comes as one card, up to\nthe edits one card carries (150 by default); only a larger one comes over several turns, the next\npart once you have applied (and saved) the one before. See\n`,_jsx(_components.a,{href:`/admin-guide/admin-copilot#ontology-first-then-save-then-the-artifact-type`,children:`Big changes`}),`.`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Apply`}),` puts the proposed details, entity types and relationships into the editor. Nothing is\nsaved until you click `,_jsx(_components.strong,{children:`Save`}),`.`]}),`\n`,_jsx(_components.li,{children:`Apply replaces the details, entity types and relationships with the card’s version. If the editor\nno longer holds what the card was made from — you edited or saved since, another card was applied,\nor the page was reloaded onto a changed content type — Apply asks first, because those newer\nchanges would be replaced too. A card made from exactly what the editor holds applies straight\naway, even after you left the page and came back. The exception is an older content type whose\nentity types are stored only in its classification instructions: until its first Save in the\neditor, every card from an earlier visit asks first.`}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Undo`}),` on the card puts back what was there before, until you edit on top of the applied change.`]}),`\n`,_jsxs(_components.li,{children:[`A card made for another content type can’t be applied here. A card the copilot made for it from\nanother page has an `,_jsx(_components.strong,{children:`Open`}),` link to that content type’s editor.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`cards-for-another-content-type`,children:`Cards for another content type`}),`\n`,_jsxs(_components.p,{children:[`The copilot can change a content type without its editor being open. On the list page, in another\ncontent type’s editor, on the Ontology page, and on the Taxonomies, Data Mapping, Enrichment Rules\nand Matching Strategies pages, it checks the content type you name `,_jsx(_components.strong,{children:`as saved`}),` and makes a card\n`,_jsx(_components.strong,{children:`for`}),` it:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`The card reads `,_jsx(_components.strong,{children:`Made for “SOW” (Artifact Types)`}),` and has an `,_jsx(_components.strong,{children:`Open “SOW”`}),` link. The link opens\nthat content type in its editor, with the card ready to apply there.`]}),`\n`,_jsxs(_components.li,{children:[`You apply it in the editor and click `,_jsx(_components.strong,{children:`Save`}),`. It was checked against the content type as saved,\nso it is refused once that content type has been saved again since (`,_jsx(_components.em,{children:`This artifact type was saved\nsince this was proposed — ask the copilot again`}),`). Any Save counts, even one that only moved things\non the canvas. If the editor has unsaved edits, Apply asks first, because the card replaces them.`]}),`\n`,_jsx(_components.li,{children:`It passes the same server checks as a card made in the editor, against the saved content type and\nthe saved ontology.`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`From every one of these pages it can also check a saved content type and tell you what Save will add\nto it. See\n`,_jsx(_components.a,{href:`/admin-guide/admin-copilot#knowledge-model-pages-share-their-tools`,children:`Knowledge-model pages share their tools`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`Reading and checking need the `,_jsx(_components.strong,{children:`Graph Managers`}),` role (read); proposing needs write access too.`]}),`\n`,_jsx(Heading,{level:`3`,id:`re-validating-reviewing-and-deleting-a-content-type`,children:`Re-validating, reviewing and deleting a content type`}),`\n`,_jsxs(_components.p,{children:[`Ask the copilot to re-validate a content type, mark it reviewed or delete it, and it makes a\n`,_jsx(_components.strong,{children:`page-action card`}),` for the Artifact Types list, from the editor or from any knowledge-model page.\nThe copilot never does it: `,_jsx(_components.strong,{children:`Apply`}),` on the list opens a confirmation, and only your own click on its\nconfirm button performs the action, under your account (see\n`,_jsx(_components.a,{href:`/admin-guide/admin-copilot#page-action-cards`,children:`Page-action cards`}),`). It needs `,_jsx(_components.strong,{children:`Graph Managers`}),` write\naccess. `,_jsx(_components.strong,{children:`Cancel`}),` leaves the card open, and once you confirm, the card reads `,_jsx(_components.strong,{children:`Saved`}),`.`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Re-validate`}),` is offered when the status is not valid. The confirmation shows what the check\nfinds now against the saved ontology: that the type becomes valid and ingestion can use it again,\nhow many issues remain (with the first one), or that it stays stale. A content type that a\nre-check would leave as it is, with the same status and issues, gets no card: fix it first.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Mark reviewed`}),` is offered when the status is stale or pending review and the ontology has a\nsaved revision. It is the panel’s own `,_jsx(_components.strong,{children:`Mark as reviewed`}),`: it re-runs the same check and saves the\nresult.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Delete`}),` is destructive. The confirmation lists what goes with the content type, counted when the\ncard was made: the matching strategies bound to it. The data sources and data-source filters that\nlist it only lose it and stay. It names those data sources, filters and strategies only to someone\nwho can read them (`,_jsx(_components.strong,{children:`Data Source Managers`}),` for the first two, `,_jsx(_components.strong,{children:`Process Managers`}),` for strategies);\neveryone else gets the counts and a line saying why they are not named. Nothing in the graph is\nremoved: what was ingested as this type stays.`]}),`\n`,_jsx(_components.li,{children:`The card is refused if the content type was saved or its status changed since it was made, and,\nfor a review card, if the ontology was saved since.`}),`\n`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Content Types","description":"Define document types and control how they are processed during ingestion","href":"/admin-guide/content-types"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Overview","slug":"overview","depth":2,"children":[]},{"title":"Viewing Content Types","slug":"viewing-content-types","depth":2,"children":[]},{"title":"Creating a Content Type","slug":"creating-a-content-type","depth":2,"children":[{"title":"Ingestion extraction policy","slug":"ingestion-extraction-policy","depth":3,"children":[]},{"title":"Entity and relationship attributes","slug":"entity-and-relationship-attributes","depth":3,"children":[]}]},{"title":"Test Ingestion","slug":"test-ingestion","depth":2,"children":[{"title":"Test Results","slug":"test-results","depth":3,"children":[]}]},{"title":"Editing Content Types","slug":"editing-content-types","depth":2,"children":[]},{"title":"Asking the copilot","slug":"asking-the-copilot","depth":2,"children":[{"title":"What the server checks first","slug":"what-the-server-checks-first","depth":3,"children":[]},{"title":"Save will also add","slug":"save-will-also-add","depth":3,"children":[]},{"title":"Applying a card","slug":"applying-a-card","depth":3,"children":[]},{"title":"Cards for another content type","slug":"cards-for-another-content-type","depth":3,"children":[]},{"title":"Re-validating, reviewing and deleting a content type","slug":"re-validating-reviewing-and-deleting-a-content-type","depth":3,"children":[]}]}],"codeExamples":{}},"jsLinks":["/_mintlify/custom/experiolabs/aceb66bfea8c86f6/Experio%20Dashboard%20Mockups/_ds/nocturne-75e4003d-2137-43aa-af77-e87cf9181b02/_ds_bundle.js","/_mintlify/custom/experiolabs/f3d3d0a662c08eef/Experio%20Dashboard%20Mockups/deck-stage.js","/_mintlify/custom/experiolabs/8fe7df74405f3c55/Experio%20Dashboard%20Mockups/support.js"],"subdomain":"experiolabs","siteName":"Experio Documentation","title":"Content Types - Experio Documentation","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-29T13:08:00.222Z","originalFileLocation":"admin-guide/content-types.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Define document types and control how they are processed during ingestion\">\u003cmeta data-mint-head name=\"application-name\" content=\"Experio Documentation\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/experiolabs/v9mlvTBAlFi1i483/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/experiolabs/v9mlvTBAlFi1i483/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/experiolabs/v9mlvTBAlFi1i483/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/experiolabs/v9mlvTBAlFi1i483/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/experiolabs/v9mlvTBAlFi1i483/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/experiolabs/v9mlvTBAlFi1i483/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/experiolabs/v9mlvTBAlFi1i483/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/experiolabs/v9mlvTBAlFi1i483/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/experiolabs/v9mlvTBAlFi1i483/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Content Types - Experio Documentation\">\u003cmeta data-mint-head property=\"og:description\" content=\"Define document types and control how they are processed during ingestion\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Experio Documentation\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.experio.cloud/admin-guide/content-types\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://experiolabs.mintlify.site/_mintlify/api/og/v2?division=Data+Sources\u0026amp;title=Content+Types\u0026amp;description=Define+document+types+and+control+how+they+are+processed+during+ingestion\u0026amp;theme=b509f6af7bc7583297b4911a\u0026amp;signature=b76d0e7c5b8ab603558002afb35b77095de740b4d3e6f1007e89c7f49da5e15c\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Content Types - Experio Documentation\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Define document types and control how they are processed during ingestion\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://experiolabs.mintlify.site/_mintlify/api/og/v2?division=Data+Sources\u0026amp;title=Content+Types\u0026amp;description=Define+document+types+and+control+how+they+are+processed+during+ingestion\u0026amp;theme=b509f6af7bc7583297b4911a\u0026amp;signature=b76d0e7c5b8ab603558002afb35b77095de740b4d3e6f1007e89c7f49da5e15c\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/experiolabs/v9mlvTBAlFi1i483/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Experio Documentation\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#5A338A\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.experio.cloud/admin-guide/content-types\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/admin-guide/content-types.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.experio.cloud/#organization\",\"name\":\"Experio Documentation\",\"url\":\"https://docs.experio.cloud\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/experiolabs/tI7TL1-DN6v_muWO/logo/experio-large-transparent.svg?fit=max\u0026auto=format\u0026n=tI7TL1-DN6v_muWO\u0026q=85\u0026s=14d019caed8ec6ef0c3c2a22ce2747d9\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.experio.cloud#website\",\"name\":\"Experio Documentation\",\"url\":\"https://docs.experio.cloud\",\"publisher\":{\"@id\":\"https://docs.experio.cloud/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.experio.cloud/admin-guide/content-types#webpage\",\"url\":\"https://docs.experio.cloud/admin-guide/content-types\",\"name\":\"Content Types\",\"description\":\"Define document types and control how they are processed during ingestion\",\"dateModified\":\"2026-10-29T13:08:00.222Z\",\"isPartOf\":{\"@id\":\"https://docs.experio.cloud#website\"},\"breadcrumb\":{\"@id\":\"https://docs.experio.cloud/admin-guide/content-types#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.experio.cloud/admin-guide/content-types#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Data Sources\",\"item\":\"https://docs.experio.cloud/admin-guide/connectors\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Content Types\",\"item\":\"https://docs.experio.cloud/admin-guide/content-types\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.experio.cloud/admin-guide/content-types#article\",\"headline\":\"Content Types\",\"name\":\"Content Types\",\"description\":\"Define document types and control how they are processed during ingestion\",\"url\":\"https://docs.experio.cloud/admin-guide/content-types\",\"mainEntityOfPage\":{\"@id\":\"https://docs.experio.cloud/admin-guide/content-types#webpage\"},\"dateModified\":\"2026-10-29T13:08:00.222Z\",\"publisher\":{\"@id\":\"https://docs.experio.cloud/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.experio.cloud#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Experio Documentation\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Experio Documentation\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/admin-guide/content-types.md","siteName":"Experio Documentation","nav":{"global":null,"tabs":[{"tab":"User Guide","pages":[{"title":"User Guide","href":"/introduction"}]},{"tab":"Admin Guide","groups":[{"group":"Getting Started","pages":[{"title":"Admin Overview","href":"/admin-guide/overview"},{"title":"Implementation Playbook","href":"/admin-guide/implementation-playbook"},{"title":"Onboarding Checklist","href":"/admin-guide/onboarding-checklist"}]},{"group":"Data Sources","pages":[{"title":"Connectors","href":"/admin-guide/connectors"},{"title":"Data Sources","href":"/admin-guide/data-sources"},{"title":"Data Mapping","description":"Map external data fields to your knowledge graph ontology","href":"/admin-guide/data-mapping"},{"title":"Content Types","href":"/admin-guide/content-types"},{"title":"Test Ingestion","description":"Upload one file and see how it would be classified and read before you add a data source","href":"/admin-guide/test-ingestion"},{"title":"Extraction Policy","href":"/admin-guide/extraction-policy"},{"title":"Flows","href":"/admin-guide/flows"},{"title":"Agent Flows","href":"/admin-guide/agent-flows"},{"title":"Flow Nodes Reference","href":"/admin-guide/agent-flows-blocks"},{"title":"Agent Flows Cookbook","href":"/admin-guide/agent-flows-cookbook"},{"title":"Admin Copilot","href":"/admin-guide/admin-copilot"}]},{"group":"Knowledge Graph","pages":[{"title":"Client Configuration","href":"/admin-guide/client-configuration"},{"title":"Graph backend (Neo4j \u0026 FalkorDB)","href":"/admin-guide/graph-backend"},{"title":"Graph Lineage","href":"/admin-guide/graph-lineage"},{"title":"Graph Evaluation","href":"/admin-guide/graph-evaluation"},{"title":"Ontology","href":"/admin-guide/ontology"},{"title":"Ontology Compatibility","href":"/admin-guide/ontology-compatibility"},{"title":"Relationship attributes","href":"/architecture/relationship-attributes"},{"title":"Taxonomies","href":"/admin-guide/taxonomies"},{"title":"Enrichment Rules","href":"/admin-guide/enrichment-rules"},{"title":"Matching Strategies","href":"/admin-guide/matching-strategies"},{"title":"Conflict Resolution","href":"/admin-guide/conflict-resolution"},{"title":"Graph Access Control","href":"/admin-guide/graph-access-control"},{"title":"Falkordb to neo4j migration research","href":"/graph-migration/falkordb-to-neo4j-migration-research"}]},{"group":"User Management","pages":[{"title":"SSO Configuration","href":"/admin-guide/sso-configuration"}]},{"group":"Integrations","pages":[{"title":"Integrations","href":"/admin-guide/integrations"}]},{"group":"Settings","pages":[{"title":"Assistants","href":"/admin-guide/assistants"},{"title":"Personas","href":"/admin-guide/personas"},{"title":"Model Configurations","href":"/admin-guide/model-configurations"},{"title":"MCP Servers","href":"/admin-guide/mcp-servers"},{"title":"AI Instructions","href":"/admin-guide/ai-instructions"},{"title":"Document Templates","href":"/admin-guide/document-templates"},{"title":"System Settings","href":"/admin-guide/system-settings"}]},{"group":"Monitoring","pages":[{"title":"Jobs \u0026 Monitoring","href":"/admin-guide/jobs-monitoring"},{"title":"Async Document Parsing","href":"/admin-guide/async-document-parsing"},{"title":"Service Scaling","href":"/admin-guide/service-scaling"},{"title":"Startup Health","href":"/admin-guide/startup-health"},{"title":"Graph Health","href":"/admin-guide/graph-health"}]}]},{"tab":"Implementation Guide","pages":[{"title":"Implementation Guide","href":"/implementation/overview"}]},{"tab":"Developers","pages":[{"title":"Developers","href":"/local-development/falkordb-browser"}]}]},"basePath":"","title":"Content Types - Experio Documentation","buildId":"dpl_5joLUXmnJgwqjrHAS4dxZrQTdxgh","deploymentId":"dpl_5joLUXmnJgwqjrHAS4dxZrQTdxgh","dynamics":[],"chunks":[]}