Overview
The Admin Copilot is a chat panel available across the admin, aware of the page you’re on. It’s built on the same agent harness (deepagents) as the rest of Experio’s AI. On every admin page it knows where you are, can explain the page from this guide, and can take you to another page. Page packs give it deeper tools on specific pages: the Agent Flows list and editor (explain a flow, validate it, investigate why a run failed, build or edit flow definitions from plain text); the Ontology editor and its revision history (explain the schema, check what a change would break, propose entity types, attributes and relationships); the Artifact Types pages (explain an artifact type, check it against the saved ontology, propose entity types, attributes and relationships for it); the Data Mapping, Enrichment Rules, Matching Strategies and Taxonomies pages (explain and check a mapping, a rule, a strategy or a taxonomy, propose changes to it, and propose actions such as re-validating or deleting it as a card you confirm); and the Settings pages — the copilot’s own settings and System Settings — where it explains each setting and proposes values. On every page connected to the ontology the copilot also has the tools of the other connected pages (see Knowledge-model pages share their tools).
The six packs of the pages connected to the ontology (Ontology, Artifact Types, Data Mapping, Enrichment Rules, Matching Strategies and Taxonomies) share one brain, the knowledge-model copilot: on each of these pages it knows all of them, reads files you attach in the chat, and checks what ingestion actually wrote to the graph. See The knowledge-model copilot.
The copilot proposes, it never applies. Every change it drafts — a new flow, an edit to an existing one, a settings value — lands as a card the person reviews and applies themselves. Saving, publishing, setting a version live, starting or resuming a run, and every other mutating action stay entirely with the human; the copilot has no tool for any of them. A few actions that are not edits — re-validating a configuration, marking it reviewed, deleting a row, creating a taxonomy — come as a page-action card: Apply only opens a confirmation, and nothing happens until your own click on its confirm button (see Page-action cards).
Opening the copilot
A Copilot button sits in the admin header on every admin page — click it, or press ⌘J (Mac) / Ctrl+J (Windows/Linux) to toggle the panel from anywhere. It docks as a resizable panel; opening it moves keyboard focus in, and closing it returns focus to what you were doing. The empty panel is titled after the page you’re on (Ask about Access control, Ask about System Settings, …) and offers a few starters for that page.A screenshot of the docked panel next to the Agent Flows editor would help orient a reader here.
What it can do
Everywhere in the admin, the copilot:- Knows the page you’re on. On every turn it’s told the page and its section (“You are on: …”), so it never asks which page you mean. On a page without a dedicated pack, its opening brief names the page and offers two starters — What does this page do? and Where do I…? — answered from this admin guide with links to the relevant documentation pages. See Asking about a page.
- Lists admin pages and searches the admin guide for a passage relevant to your question, ranked by the page you’re on; the guide pages it drew on are listed under the answer as References (titled links, kept when you reopen the session) rather than pasted into the prose. If the guide’s search index is out of date, it says so before answering from the guide and offers the re-index (see Troubleshooting).
- Offers to navigate you to another admin page — it asks first, you confirm before anything moves. It can only offer pages that actually exist: the admin app tells the copilot which pages it renders, so a route that isn’t a real page is refused, and the copilot picks from the pages near it instead, those whose route or title share the most words with it first. Where a page belongs to one record rather than a list — the editor of a particular flow — it offers that record’s page, not the list you would then have to search. And when the card follows a proposal it just made, it opens the page that can actually show the proposal, so “take me back to it” lands on the flow with the change in front of you. A card made for another page works the same way: after an ontology card made on an Artifact Types page, “take me there” offers the Ontology page, where that card is applied, and carries the card’s id (
?proposal=). It does so even when the copilot names a route that doesn’t exist but names that page, such as/admin/ontology. - Answers briefly, in plain words: what matters to you, and the next step. A reply with a card is at most three short sentences (what the change does, then the next step); the card shows the details. It doesn’t explain how it works (a refused tool call, a change kept for later, how it continues after a Save). Ask when you want more detail. A gap table you ask for keeps one short row per question.
- Asks you a question as a card with a few plain-language options, when it needs information before it can act.
- Remembers for everyone, when you ask it to (“remember this for everyone”) from any page — a convention or decision the whole team should share goes into a page pack’s shared Notes memory rather than your personal notes: the pack of the page you are on by default, or the one you name (“remember for agent flows: …”). See Memory.
On Agent Flows
On an Agent Flows page (the list or the editor), it also reads the open flow’s current definition (including your unsaved edits), the flow’s validation state, and its recent runs, and can:- Explain the flow or one of its nodes, and answer “why did run X fail?” from the run’s diagnostics.
- Validate a definition — the same checks that back the canvas Validate button and the publish gate, including the hollow-pattern lints — without saving anything.
- Build a new flow from a plain-language description, starting from the built-in templates when one fits.
- Read documents in full. For a flow that must read an uploaded document whole (a scanned PDF, or anything longer than the 10,000 characters Index uploads keeps), it proposes a Parse documents (async) step: it binds the step’s files to the upload, sets OCR, the wait and what to do when a document cannot be read, and routes on the step’s
statuswhen you want the flow to handle an unreadable file. It never picks the documents the step reads from your data sources or your own parsed results: a proposal that does is refused, and you pick them in the node’s settings. See Parse documents (async). - Propose an edit to the flow already open in the editor — anything from fixing a validation error to adding a review gate — as either a whole redrafted definition or a small set of targeted changes, whichever fits the request. Asking it to “apply it”, “fix it” or “go ahead” after an explanation produces a proposal card, never a list of manual steps.
- Recall past fixes. When the page has a failed run or validation errors, the copilot is shown the Similar past fixes recorded in the Agent flows Fixes memory — what resolved the same error before, and which attempt did not — so it can steer away from a repair that already failed and reuse one that worked. See Memory.
The copilot is read-only on your MCP servers. Its Agent Flows pack has no tool that saves, publishes, sets a version live, or starts/resumes/cancels a run — those stay on the canvas. See Safety posture.
On the Ontology
On the Ontology editor (and its revision history), the copilot reads the schema as drawn on the canvas — including your unsaved edits — and can:- Explain the schema — what it models, what an entity type is for, which attributes it carries and how it relates to the others.
- Read a large schema in pages. The copilot lists every relationship on one line (source, name, target, its attributes and its id), and for one entity type it reads the relationships before the attribute list. The schema readers return whole rows a page at a time: while rows remain, a reply says so and names the exact call for the next page, so nothing is cut off without saying so.
- Say what a change would break before you make it. It reads the content types, data mappings, enrichment rules and matching strategies that depend on the ontology, and which of them extract which entity types and attributes.
- Find problems the save does not catch. Duplicate entity-type or attribute names, the same relationship (same source, name and target) defined twice, an
enumattribute with no options, a vector index built from an attribute that has been deleted, a relationship pointing at an entity type that no longer exists, and two shapes that make ingestion quietly attach fewer parents than the schema asks for (an entity type with more than one required-upstream parent, and a cycle in that chain). Nothing else checks a schema against itself — the API validates its shape, and the compatibility engine validates what depends on it. - Propose typed edits — add, rename or remove an entity type, an attribute or a relationship, and add, change or remove an attribute of a relationship that already exists — as a card you apply to the canvas and save yourself. Removing an entity type also removes every relationship that touches it, because a relationship can’t outlive either end: the card’s line names them (the first 12, then how many more). A card that would change nothing (each edit sets a value the schema already has, or one edit undoes another) is refused, and the copilot is told not to propose some other change in its place. When the save would refuse the result, the refusal names every problem at once, not one per try. A relationship name that several pairs of entity types share is picked out by the relationship’s id or by its source and target; a name that still matches more than one relationship is refused, not guessed. A relationship is never added a second time from the same source to the same target under the same name: that proposal is refused and names the existing relationship to edit instead, and a change that would make a second copy another way (renaming or moving one relationship onto another) is refused too. A duplicate the schema already has is flagged on the card as one this change did not cause. A name a card adds, or renames something to, must be one the graph can store and query: ASCII letters, digits and underscores, not starting with a digit (entity types like
ProjectPhase, attributes likestart_date, relationships likeSIGNED_BY). A card with any other name is refused. Names the ontology already has are left as they are. Until the ontology has loaded on the canvas, the copilot works on the saved ontology and Apply is refused (“The ontology is still loading”); once it has loaded, a card made before the load asks you before it applies, like one made for an earlier version of the canvas.
On the Artifact Types pages
On the Artifact Types list, the create page and an artifact type’s editor, the copilot can:- Explain what an artifact type extracts and how it recognises its documents, and why its saved status is invalid or stale. It is given the issue codes of the last check against the saved ontology (for example
ATTRIBUTE_NOT_IN_ONTOLOGY StatusReport.percent_x) and is told to explain the status only from those codes or from its own check, never from a guess. - Check it for anything Save would refuse or extraction would miss.
- Say what Save will add from the ontology on top of what you drew.
- Propose typed edits — the details, entity types, attributes and relationships — as a card you apply to the editor and save yourself.
On Data Mapping, Enrichment Rules, Matching Strategies and Taxonomies
On each of these pages the copilot can explain what the page holds, check it, and propose typed edits as a card you apply on the page and save yourself:- Checked like an Artifact Types card. The server applies the edits to the page’s state and runs the page’s own Save validation on the result, without saving. Except for a taxonomy, which doesn’t depend on the ontology, it also checks the result against the saved ontology before and after the change. A problem the change causes goes back to the copilot, which fixes it in the same turn. A problem that was already there usually rides the card as a note instead of blocking it (some, such as one the page’s Save would refuse, still block). The card also lists what the page’s Save will do on top of the change (for example, a data mapping’s edit Save recreates every row with new ids).
- Never saved by the copilot. Apply writes the card to the page’s editor, form or strategy, and nothing is saved until you click the page’s Save. Undo on the card puts back what was there. On Taxonomies, Apply stages the changes as a draft, which Save changes writes in one go (see Draft mode).
- Ontology first. Everything a card names must be in the saved ontology. When something is missing, the copilot proposes the ontology card first and keeps the change for after your Save (see Ontology first, then Save, then the artifact type).
- Nothing runs. The copilot itself never runs, previews or tests anything on these pages: no rule run or preview, no scan, no Test Ingestion, no sample fetched from a data source. An edit card can remove a part (a node mapping, a term), which takes effect only when you save. Deleting a whole mapping, rule, strategy or taxonomy is a different kind of card, which you confirm in a dialog and which the copilot never performs itself (see Page-action cards). See Safety posture.
On the Settings pages
On Admin > AI & Agents > Copilot (the copilot’s own settings) and on System Settings, the copilot:- Explains a setting in plain words — what it controls, what a value means in practice, and its current value on the page (with the default, on the copilot’s own settings). On System Settings it reads the words of the System Settings reference for that key and cites the page; on its own settings page it also sees a short digest of your recent sessions (model in use, turns that ended in error or on the budget, denied tool calls) so it can recommend from evidence — for example, raising the model-call timeout when turns keep stalling.
- Checks that the guide is indexed before answering a settings question from it. When the index is empty or out of date, it tells you and offers the re-index instead of answering from memory.
- Proposes a change when you ask it to (“set it to enforce”, “tune it for me”, “is this right?”) as a card listing each change as setting · current → proposed · reason. Apply patches the page’s own form — nothing is saved yet — and you press the page’s Save to persist it, with the page’s usual validation and permissions. A proposed value is validated on the server against the settings schema before you ever see the card.
- Never touches a secret. Encrypted values show as set / not set, are never shown to the copilot or to you through it, and cannot be proposed — a person types those. A secret you type into the chat itself (“set OPENAI_API_KEY to …”) is masked to
••••in your message and in the reply before either is stored, so type it into the setting’s field on the page instead. On its own settings page the copilot also can’t propose changes to the MCP bindings or to the write / MCP-write consent policy; those are changed by a person on the form.
The knowledge-model copilot
The Ontology and Artifact Types pages, the data mappings, enrichment rules and matching strategies built on them, and the taxonomies are parts of one knowledge model: the graph’s schema, what is extracted from each kind of document, and how that data is mapped, enriched, matched and classified. On every page connected to it the copilot knows the whole model, not just the page you’re on. Each turn it reads the saved state of every connected page and the list of files you attached to the conversation. The page you’re on is the one exception to “saved”: the Ontology canvas, the artifact-type and data-mapping editors, the rule form, the matching strategies you have open, and a taxonomy’s draft also show it your unsaved edits. On the Artifact Types pages it reads the saved ontology the way the Ontology page reads its canvas: every relationship on one line with its id, one entity type’s relationships before its attributes, and a large schema a page at a time, each page naming the call for the next, so nothing is cut off without saying so. All of this needs the Graph Managers role (read). Without it the copilot says so and reads none of it. Each page’s own rows and cards also follow that page’s permission group (the last column below): read access to read them, and write access for a card, because a card you can’t save is a dead end.Connected pages
The copilot also knows each data mapping, enrichment rule and matching strategy by name with its status, invalid first (data mappings of the default ontology; a long list is cut, with a count of the rest), and why one no longer fits the saved ontology. It is given the name of a valid one only when you can read it on its own page: valid data mappings for Data Source Managers readers, valid enrichment rules and matching strategies for Process Managers readers (a superuser reads all three). Otherwise it is told how many valid ones there are, and still gets the name of every one that isn’t valid (invalid, stale or pending review). Asked what is connected to the ontology, it is told to answer with these names and statuses, not with page categories.
The copilot works this way from every one of these pages: see Knowledge-model pages share their tools.
Knowledge-model pages share their tools
Every admin page connected to the ontology belongs to one group: the Ontology editor and its revision history, the Artifact Types list, create and edit pages, Taxonomies, Data Mapping, Enrichment Rules and Matching Strategies. Each page has tools of its own, and whichever of these pages you have open, the copilot also has the tools of every other page in the group. You don’t have to go to the Ontology page for an ontology card, or open an artifact type’s, mapping’s or rule’s editor for a card that changes it.- The other pages’ tools work on a saved row you name. For an artifact type: check it, say what its Save would add, and propose a card for it. For a data mapping, an enrichment rule, a matching strategy or a taxonomy: describe it, check it, and propose a card for it. Each such card is made for that row’s page (see Cards for another page). To re-validate, mark reviewed or delete any of these rows, it proposes a page-action card.
- Away from the Ontology page, the ontology tools read the saved ontology, never a canvas: there is none open there.
- A row is named by its name or its id (a matching strategy by its entity type or its id, a taxonomy by its name or its slug). In an editor, leaving the name out means the one that is open.
- Everything needs the Graph Managers role (read). Each page’s tools also follow that page’s own permission group, on whichever page you use them (see Connected pages): read access gives its readers, and write access its cards. So a Graph Managers member who isn’t in Data Source Managers gets no data-mapping tools on any page, the Ontology page included, and one who isn’t in Process Managers gets no rule or strategy tools. The page-action tool is offered only to someone who can write on at least one page that hosts such cards, and each action needs write access on its own page.
- Ask for a change on any of these pages (“suggest changes to the artifact types and the ontology”, “fix this mapping”, “apply the changes”), and the copilot makes the card in that turn: it is told never to hand you a list of edits to make by hand, nor to ask whether it should make the card.
- The copilot makes one card per row (per artifact type, mapping, rule, strategy or taxonomy) and cards of one kind per turn, at most five, whichever page’s tool makes them. An ontology card is alone in its turn. A page-action card counts as its row’s card: a row never gets both an edit card and a page-action card in one turn, and a turn that made an ontology card has no page-action card. A rejected card counts against one repair budget for the whole turn.
- Switching a pack off in Page packs (see Configuration) removes its tools from every page, not only its own. Data Mapping, Enrichment Rules, Matching Strategies and Taxonomies each have their own settings form and their own shared notes (see Shared notes).
Attaching files
On every knowledge-model page a paperclip sits above the message box. Attach a few sample documents of the kind you are modelling, and the copilot reads them for you. The paperclip opens a menu: Upload files, Attach from parsed documents (see below) and a Parse in the background switch, kept for each session and on by default. While the switch is on, every file you upload goes to the background parser, whatever its size. Turn it off and an ordinary small file (up to 1 MB, other than a spreadsheet) is read right away on the server instead (a file over 1 MB, any spreadsheet, a scanned PDF and any file the server cannot read itself still go to the background parser). A new session starts with the switch on again. You can also drop files anywhere on the copilot panel. While files are over it, the panel shows Drop files to attach. A dropped file goes through the paperclip’s own path, with the same limits, error messages and Parse in the background setting, and it can be dropped while the copilot is working. Where the panel has no paperclip, a drop does nothing, and the browser never opens the file in place of the admin. A chip that is ready has an eye icon (tooltip Preview parsed text) that opens the text the copilot has for the file in a window (the main chat opens it in the right panel): the first 20,000 characters, Load more, Page n dividers, search and Copy (see Previewing the text of a file). The window also shows the file’s own note under its header when it has one, for example why part of it is searched by keyword only. A chip that is still being read, waits for your OCR choice or failed has no eye; a file read by the background parser gets it once the document itself is ready. A scan that nobody read opens on the little text the first pass found, with Scan not read in amber in the header. A file a fork inherited has its eye too, and is read through the fork’s own session.-
File types: PDF, Word (
.docx,.doc), PowerPoint (.pptx,.ppt), Excel (.xlsx,.xls,.xlsm), CSV, plain text, Markdown and JSON. -
Limits: 25 MB per file and 10 files per conversation. Attaching the same file twice is refused. A new file is also refused while 10 of your files are still waiting to be read or being read, across all your conversations (you already have 10 files waiting to be read); attach it once one of them is ready or has failed. A file waiting for the background parser counts, and so does a scan waiting for your OCR choice. The parser has a limit of its own on top of this (
ASYNC_PARSE_MAX_QUEUED_PER_USER, 10 by default, over all your files in every part of Experio): a file that needs it past that limit is refused (N of your files are already waiting to be read (at most N at a time); with Parse in the background on, which is the default, that is every file), or, when the server hands it over after reading it first, fails with this file needs the background reader, and …. A file that is a zip inside is measured before anything reads it, whatever its extension: a Word, PowerPoint or Excel file (.docx,.pptx,.xlsx,.xlsm) is one, and so is a zip renamed.doc,.xls,.ppt,.txtor any other accepted type. If it expands to more than 200 MB when unzipped, it is not read, and fails saying so. The builtin parser is never given such a file with one part over 100 MB either. Test Ingestion refuses such a file the same way. A file that passes is first read by Kreuzberg, with no OCR, in a separate process that the server watches, never in the server process itself. The server process doesn’t open a PDF even to count its pages: the separate process counts them and tells it. When Kreuzberg can’t read the file, the builtin parser reads it in a separate process too. A plain-text file (.txt,.md,.csv,.json) is decoded by the server directly. If one reading needs more than 512 MB of memory, takes longer than 60 seconds, or finds the server with less than 768 MB of memory left, it is stopped and the file is handed to the background parser, which reads it with limits of its own, instead of failing. No other parser on the server tries the file after such a stop. A file over 1 MB, and every spreadsheet (.xlsx,.xls,.xlsm), are handed over without being read on the server at all. The memory and time limits are settings; the 768 MB floor is not (see Deployment). -
Text files: plain text, CSV, Markdown and JSON files that start with a byte-order mark are read in the encoding it names (UTF-8, UTF-16 or UTF-32: Excel’s Unicode Text export is UTF-16 with a mark). Without a mark, the server tries these in order and never guesses a code page:
- UTF-8, whenever the file is valid UTF-8;
- otherwise UTF-16 without a mark, but only when zero bytes on one side of the byte pairs make up at least 30% of the bytes it reads (and there are at least 4 of them), the other side has at most a quarter as many, and the file decodes to clean text (no control, private-use or unassigned characters);
- otherwise Windows-1252, exactly as before. Excel on Windows uses it for CSV in Western Europe and the Americas.
Joséstored asJosé). It also happens to exports in a Central European, Turkish, Baltic, Cyrillic, Greek, Hebrew or Arabic Windows code page (Plzeňstored asPlzeò,МоскваasÌîñêâà), Mac Roman or a DOS code page. Any of these files fails instead, as below, when it holds one of the five bytes Windows-1252 leaves undefined (0x81, 0x8D, 0x8F, 0x90 and 0x9D). UTF-8 Russian text with a stray byte usually does, because the letterсis the bytes D1 81. UTF-16 without a mark is not always recognised. Text of only ASCII, Cyrillic and Arabic characters is valid UTF-8 byte for byte, so it is read as UTF-8. ASCII comes out right that way, but Cyrillic and Arabic come out garbled, with no warning. Greek, Hebrew, Chinese, Japanese and Korean text has zero bytes only in its spaces, digits, punctuation and Latin letters, usually too few, so it falls back to Windows-1252 with the warning, or fails. A Windows-1252 file that holds zero bytes is read as Windows-1252 unless its zero bytes follow the UTF-16 pattern above, and a file misread that way carries the UTF-16 warning. A file with a byte that Windows-1252 does not define (a binary file, and many Shift-JIS, Big5 or EUC-KR files) fails with the file is not UTF-8, UTF-16 or Windows-1252 text; save it as UTF-8 and attach it again. To be sure, save text files as UTF-8 (in Excel, CSV UTF-8). - Indexing: a file the server reads itself (every small file that is not a spreadsheet, once you turn Parse in the background off) is read in the background, so the chat never waits for it. Its chip shows Indexing… until it is ready, then how much text it holds. A file waiting for its turn shows Indexing… too. By default each server process reads one file at a time, and people take turns: your next file waits for the file being read and at most one file of each other person with files waiting on that process, however many files one person has queued. Your own files are read in the order you attached them (see Deployment). A file that can’t be read shows Failed; hover the chip for the reason. Only the first 2,000,000 characters of a very long file are kept, and the chip’s tooltip says so. A file read by the background parser keeps its whole text, so this cut applies only to a file read on the server.
-
Background parsing: the server hands every file to the background parser, unless you turn the Parse in the background switch off. With the switch off, it hands over only a file over 1 MB, any spreadsheet, a PDF taken for a scan, or a file whose reading on the server hit a limit, and reads every other small file right away itself. The chip of a file the parser reads shows where it stands instead of Indexing…: Waiting for the parser (can take a few minutes) (the parser may have to start first), Parsing…, then Ready. You can keep talking meanwhile.
- The copilot continues on its own. When the file is ready, the panel shows a system note (Your document was read — continuing) and the copilot tells you in a sentence or two that the file is read and what it is. It makes no card unless you asked for changes. When the file fails (Your document could not be read), it says so in one sentence with the reason. This follows the Continue after a Save setting (see Continue after a Save): with it off, the copilot does not continue by itself, and the file is there for your next message. Like a continue after a Save, it waits until the panel is open and the copilot is free (not working, and no question or approval waiting), so a file that settled while the panel was closed is announced when you open it. It works on any knowledge-model page, and the copilot is told about each file once.
- Embedding has limits. The parser reads a copilot file in full and embeds it for search. Past
ASYNC_PARSE_MAX_EMBED_CHUNKSchunks (20,000 by default, about 1,000 characters each), orASYNC_PARSE_EMBED_BUDGET_SECONDS(600 by default) of embedding, the rest of the file is searchable by keyword only. The chip then reads Ready with keyword search only for part of the text beside it, and its tooltip says how far the embedding got.
-
Scanned PDFs: a scanned PDF’s pages are pictures of text, which only OCR can read. OCR takes a lot of memory, so it never runs on the server: a scan goes to the background parser, which reads it by OCR in its own container.
- Every attached file is first read without OCR. A PDF that then gives fewer than 60 letters and digits a page (none at all, or only a stamp or a signature line) is taken for a scan and handed to the background parser.
- A scan of at most
ASYNC_PARSE_OCR_ASK_ABOVE_PAGESpages (2 by default) is read by OCR straight away. Its chip goes from Waiting for the parser (can take a few minutes) to Parsing… to Ready, and the copilot continues on its own. - A longer scan asks first. Its chip reads Scanned PDF (8 pages) with Read with OCR (~2 min) and Skip. The estimate is the page count times
ASYNC_PARSE_OCR_SECONDS_PER_PAGE(10 seconds by default). There is no consent card in the conversation: the chip is where you answer, so a waiting question never blocks the chat. Read with OCR queues the scan (Waiting for the parser …, with OCR requested) and then shows Reading with OCR 1:10 / ~2:00, the time so far against the estimate, not a percentage. When the OCR is done the file is ready like any other and the copilot continues on its own, even if you closed the panel meanwhile. - Skip keeps the document attached as a scan nobody read, and the copilot does not answer from it. What the document shows then depends on whether the text the scan carried of its own (a signature line) was kept. If it was, the document stays ready, with an amber icon and Scan not read, and the copilot tells you in one sentence that the scan was not read and asks for a text version (a Word file, or a PDF whose text can be selected). If it was not, the file fails with Scanned PDF too large to read here (8 pages); attach a text version…, with its own page count, and the copilot tells you in one sentence that the file could not be read and why. To use the scan itself, attach a text version, or attach the scan again and choose Read with OCR. A scan whose question you leave unanswered is skipped after 24 hours (
ASYNC_PARSE_NEEDS_OCR_EXPIRY_HOURS). - A scan that OCR itself reads almost nothing from (a blank or handwritten page) ends the same way as a skipped one.
- A scan whose OCR hits its memory or time limit (
ASYNC_PARSE_OCR_MAX_MEMORY_MB, 3,072 MB by default, andASYNC_PARSE_OCR_TIMEOUT_SECONDS, 1,800 seconds by default) fails with Scanned PDF: its pages are images, and reading them with OCR needed more than 3072 MB of memory… (or took more than 1800 seconds…), naming the limit it hit. - The copilot is told the same as the amber icon with everything it reads or finds in such a file, and to tell you so in one sentence, never to answer from it.
-
Attach from parsed documents: instead of uploading a file again, pick one that is already parsed. The picker has up to three lists: My uploads (files you uploaded in the chat, in this copilot or in Test Ingestion that the parser has already read), Parse only (files from data sources set to Parse only: read and saved, but not added to the knowledge graph) and Ingested (files from data sources that were ingested into the knowledge graph and whose document is attached to an entity there). The two data-source lists need Data Source Managers read access, and an ingested document is listed only when your own graph access lets you see it. A file whose artifact type has no entity that attaches the document is ingested but is in neither list (see Async Document Parsing). Search by name, filter by file type (and, on the two data-source lists, by data source, job and, on Ingested, artifact type), tick several documents and press Attach. The copilot gets a snapshot of the document as it is when you attach it, with a badge on its chip (Upload, Parsed or Ingested) and no new reading: a document of up to 200,000 characters (
ASYNC_PARSE_INLINE_TEXT_EMBED_MAX_CHARS) is indexed on the server, a longer one by the background parser. A picked document counts toward the session’s 10 files, and one that is already attached is not added twice. Only your own pick attaches a document: no tool of the copilot takes a document id to attach one.- Documents that cannot be attached are not listed. A Parse only document whose stored text is gone is missing from the list, and so is an Ingested one while graph access control is enforcing: it is not greyed out, and a list with none says No documents available to attach. (an empty Ingested list says what puts a document there instead; see What the Ingested tab shows). Every row that is listed has an eye icon that opens the document’s text before you attach it; it does not tick the row. Changing the list, the search, a filter, the file type or the page clears the rows and shows a loading state until the new ones arrive, and a list that cannot be read shows its reason and Try again, never a count. See Picking and previewing parsed documents.
- Cannot find a document? Usual causes: you uploaded it in a chat or in the copilot, so look under My uploads, not under a data source (three uploads are not kept there: a
.txtor.mdfile in the main chat, a small copilot file that the API server read itself, and a Test Ingestion sample read the same way; attach such a file again instead of picking it); a Parse only data source never fills Ingested; it is still being read, or it failed; you lack Data Source Managers read access; or Ingested is empty because the artifact type has no entity that attaches the document (tick Attach document to this entity, Update Entity, Save, then Requeue > Ingest Phase), or because, while graph access control is enforcing, its parsed text file is gone (requeue it from the Download Phase). On a long list, use the search or the Data source, Job and (on Ingested) Artifact type filters: the picker checks only the newest 2,000 (Parse only) or 5,000 (Ingested) documents, and a filter reaches the older ones. The checklist is I can’t find my document in the picker. - Attach tries every document. The ones that went in are attached and leave the selection. If some did not, the dialog stays open and one error box, These documents could not be attached:, lists each with its reason (name: reason, for example This document is no longer available to you.). They stay ticked: press Attach again, or untick one to take its line off the list. A document that is attached to the session already counts as attached.
- During a turn: you can attach while the copilot is working; it sees the file from your next message.
- Files that become cards: an attached CSV can fill a taxonomy with terms (see Taxonomies) or give a data mapping its source columns (see Data Mapping). The server reads the file and writes the card; the copilot doesn’t retype the rows, and the card lists every row it can’t import instead of dropping it quietly. An Excel file isn’t read this way: export it as CSV.
- Search: the copilot searches your files by meaning and by keywords, reads around the passages it finds, and is told to name the file an answer comes from. You can name a file in your message whatever its spacing or case, or by a part of its name that only one of your files has; when several files fit, the copilot asks which you mean. When it has read only part of a long file, what it reads back says which parts it hasn’t read yet in this turn, and it is told not to say anything about those, and to search for where a fact is rather than guess. If the search model can’t load, or fails on that one file (see Deployment), the file is searched by keywords only, and the chip’s tooltip says so.
- Long files: asked where something is in a long file, or about a part it hasn’t read, the copilot is told to search first and read around what it finds, not to answer from the start and the end of the file (a question about the end itself can be answered from the end). It is told not to describe a part it hasn’t read: it reads that part, or tells you it hasn’t.
- Kept with the conversation: the files stay with the session, across pages and reloads, until you remove one with the × on its chip or close the session. Closing a session deletes its files and the text the copilot read from them, unless another open conversation still uses them. A reading the background parser still has under way for a deleted file is cancelled. Close session asks before it does. A new session starts with none. A fork sees the files the original conversation saw at the moment the fork was made, including files attached after the answer it was forked from, and their chips say they come from the conversation it was forked from. Such a file has an × in the fork only while no other open conversation uses it. Otherwise its chip names the open conversations that still use it (up to three, and how many more; hover the chip): close them and then remove it in the fork, or remove it in the conversation it was attached to while that one is open. A fork still open keeps these files when the original is closed, and they are deleted when the last open conversation that sees them is closed. Files are inherited through at most five forks: a fork six or more forks away from the conversation a file was attached to doesn’t see it.
- Who can see them: only you. Sessions are private, and attaching needs the Graph Managers role (read). What is kept is the text the copilot read, not the original file. The preview is yours alone as well: it opens only in your own open session, and needs the same Graph Managers read access. Someone else’s session, a closed one, or a file that session does not see is answered as a file that does not exist.
-
Data, not instructions: a file’s text reaches the model marked as data from a document you attached, not as instructions. A file that tries to instruct it can mislead an answer or a card, which you still review before Apply. What such a file can still get the copilot to write without a card to apply is small: an entry in your own User notes, which shows as an undoable card and on the Memory tab. It can add a question to this conversation’s
/km/questions.mdonly as a heading or a line ending in:, which the server writes unchecked; it refuses any other line that isn’t in what you typed in the chat (see The customer’s questions). An entry in the shared Notes or Fixes is filed only in a turn where your own message asks to keep something (for Fixes, also one that confirms a fix) or you click For everyone. In such a turn it is still the copilot that writes the entry, so a file can influence what it writes; the card shows exactly what was written, with an Undo (see Memory).
The customer’s questions
Paste the questions the knowledge graph must answer into the chat. The copilot keeps them word for word in a file of the conversation,/km/questions.md, and is told to read it before it proposes anything. Every conversation on these pages starts the file with a heading and “(none yet)”, so that first read never fails. When you give more questions later, it adds them to the file with an edit, so the earlier ones stay: the server refuses to write the file over once it holds a question.
The server also checks every line the copilot writes to the file, and tells the copilot which lines it refused. Each line must appear word for word somewhere in what you typed in this conversation or answered on a question card; the card’s own question doesn’t count. Case, spacing, curly quotes, list numbering and a closing question mark or full stop don’t matter, and the copilot may add bold to the line. Headings and any line ending in : are written without the check. So a question the copilot made up never gets in, unless it is written as a line ending in :. A shortened copy of your own text can get in, such as the first half of a question or a line of a request you made. The copilot is told to keep only whole questions, never your requests to it. If you type bold yourself (** or __ around words), that question can’t be kept whole, so type it without them. A question that is only in an attached file has to be pasted into the chat to be kept.
The file follows the conversation to every page and survives a long conversation being summarised. Ask the copilot to read the file back when you want to check it.
Ontology first, then Save, then the artifact type
An artifact-type change often needs something the ontology doesn’t have yet: an entity type, an attribute or a relationship. The artifact-type check reads the saved ontology, and leaving a page throws away its unsaved edits. So the copilot works in this order:- It proposes the ontology change.
- You apply it and click Save on the Ontology page.
- Then it proposes the artifact-type changes: by itself, right after your Save (see Continue after a Save).
> …, such as the one Quote in reply adds) never holds it back. Nor does a numbered or bulleted line sent with a question, as your customer’s questions usually are, even one about SOWs with “no change orders”. When the turn is sent back, the copilot is first told to reread your own sentences: if one says to wait, to change or do nothing yet, not to propose, that you or your team will make the edits, or that you only want a list, it is told to answer with no card, however you worded it; asking what should change doesn’t overrule that. The backstop section has more examples. A card still waiting to be applied doesn’t stop the next one: ask for another change, a delete included, and you get its own card with its cost on it (for a delete, the configurations it would invalidate).
Big changes. The copilot sizes each change to what you asked and what your documents need. A small fix is a small card. A big change — a new area an attached document calls for, a restructuring you ask for, or building the ontology from scratch — comes as one ontology card, whether the ontology is empty or already big: the copilot reads your samples and questions first and designs the change as a whole, each entity type with its attributes and the relationships between them. It never cuts a big request into small increments on its own. Only a change with more edits than one card carries (150 by default), or one whose parts are independent and worth reviewing separately, comes by area over several turns, each applied and saved before the next. Building from scratch (fewer than three entity types saved, or you ask for a design from scratch) is one example: the card is the core model. With the last card of a big change, the copilot is told to keep the artifact-type changes it needs, and after your Save it proposes them (see Continue after a Save). When it kept none, it still proposes the artifact types that should extract what the card added once you have applied it and saved; when there is no saved artifact type yet, ask for them once you have saved.
The copilot makes one card per artifact type per turn, and an ontology card is alone in its turn. A card holds the whole schema or artifact type as it would be after the change, made from where you were when you asked. A second card for the same thing, made from the same starting point, would undo the first when applied after it — so the copilot never makes two cards for the same artifact type (or two ontology cards) in one turn, and a change with more edits than one card carries comes over several turns: the first part now, the next once you have applied (and saved) it. Cards for different artifact types don’t collide (each is applied in its own editor), so one turn can fix several artifact types, one card each, up to five. An artifact-type card is never made in the same turn as an ontology card: it would be built on the ontology your Save is about to replace. When a new card was made without a pending card’s edits, the copilot is told to say so: applying both would undo the first, whatever each one changes. Data mappings, enrichment rules, matching strategies and taxonomies follow the same rules: one card per mapping, rule, strategy or taxonomy, cards of one kind per turn (up to five), and never in the same turn as an ontology card.
Cards for another page
From any knowledge-model page other than the Ontology page, the copilot can make that ontology card without you leaving the page. The card is made for the Ontology page:- It lists its edits wherever you see it. Anywhere else than the Ontology page it has no Apply. Its footer reads Made for the Ontology page (later Applied on or Undone on the Ontology page), with an Open Ontology link.
- If the page you’re on has unsaved edits, the link asks before it leaves, because leaving loses them. Save first to keep them.
- On the Ontology page you apply it like any other card, then click Save. It was checked against the saved ontology, so it is refused once the ontology has been saved again since (“The ontology was saved since this was proposed — ask the copilot again”). If the canvas has unsaved edits, Apply asks first, because the card replaces them.
- It passes the same checks as a card made on the Ontology page, run against the saved ontology. A relationship the ontology already has is never added a second time: an attribute goes on the existing one, and a change that would leave two identical relationships is refused. Renaming or removing an attribute of a relationship says on the card that Save does not update the artifact types that name it, and when they are marked invalid (see On the Ontology).
- Edits on the page it was made on never mark it stale.
- Its footer reads Made for “SOW” (Artifact Types) (later Applied on or Undone on “SOW” (Artifact Types)), with an Open “SOW” link. The link opens that artifact type in its editor, with the card ready to apply there. The link is hidden only on that artifact type’s own page.
- In the editor you apply it and click Save. It was checked against the artifact type as saved, so it is refused once that artifact 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; ask again and you get a fresh card. If the editor has unsaved edits, Apply asks first, because the card replaces them.
- It passes the same checks as a card made in the editor, against the saved artifact type and the saved ontology: a change that needs something the saved ontology lacks is refused and points the copilot to the ontology card first.
- Its footer reads Made for “Accounts” (Data Mapping) (later Applied on, Saved on or Undone on “Accounts” (Data Mapping)), with an Open “Accounts” button. A matching strategy is named after its entity type. The button opens the mapping’s or the rule’s editor, the Matching Strategies page, or the taxonomy’s page, with the card ready to apply there.
- Away from that page the card shows its title, summary and reasons, but not its list of changes: open the page to see them.
- On that page you apply it and click the page’s Save. It was checked against the row as saved, so it is refused once that row has been saved again since (This data mapping was saved since this was proposed — ask the copilot again), or once the ontology has (The ontology was saved since this was proposed — ask the copilot again). A taxonomy card is checked against the taxonomy only. If the page has unsaved edits, or a taxonomy a draft, Apply asks first, because the card replaces them.
- It passes the same checks as a card made on that page, against the saved row and (except for a taxonomy) the saved ontology.
Page-action cards
Some changes are not edits of what a page holds: re-validating a configuration against the saved ontology, marking it reviewed, deleting a row, creating a taxonomy. When you ask for one, the copilot makes a page-action card. The copilot never performs the action. You do, by confirming it.- Made for a list page. The card is made for the list that owns the row (Artifact Types, Data Mapping, Enrichment Rules, Matching Strategies or Taxonomies), from whichever knowledge-model page you are on. Away from that list, its footer reads Made for the Data Mapping page (later Saved on the Data Mapping page), with an Open Data Mapping button, and it has no Apply. The Ontology page only displays these cards.
- Apply opens a confirmation. On the list, Apply reads the row again and opens a dialog with the headline (the action and the row), the row’s status now, and what the action will do. Nothing has happened yet. Only your own click on the dialog’s confirm button performs it, with your own account and permissions. The button carries the action’s name: Re-validate, Mark reviewed, Delete, Delete strategy, Delete taxonomy. Cancel closes the dialog and leaves the card open. After you confirm, the card reads Saved.
- The facts are the server’s. The headline, the status, the lines saying what the action does and, for a delete, what else goes with the row are computed by the server from the saved rows when the card is made. The copilot’s own sentence shows last, labelled Copilot’s note, and can’t change them.
- A delete is marked destructive. The card and the dialog show a warning (Destructive: once confirmed, it cannot be undone here.), an Also affected list of what goes with the row, with counts and names, and a red confirm button. The counts are those of the moment the card was made: a row linked to it since is not in the lines. Where a line would name rows you may not read, it gives the count only and says so (see below). These deletes remove nothing from the graph: what ingestion or a rule already wrote stays.
- Refused when the row changed. Apply refuses, and tells you to ask the copilot again, when the row was saved since the card was made or its status moved. A review card is also refused when the ontology was saved since. A taxonomy delete is also refused when a term was added, edited or removed since.
- Only when you ask. The copilot is told to propose a delete only when you asked for it, never as a fix of its own. After a Save it still only notes that a row needs Re-validate; ask, and it makes the card (see Continue after a Save).
Graph Managers read is needed on top, as for everything the knowledge-model copilot does. Someone who cannot write on a page that hosts these cards gets no page-action tool at all. Asked for an action on a page they cannot write on, the copilot names the group that can do it there. A card also needs the hosting page’s pack switched on in Page packs (see Configuration); with it off, the copilot tells you to do the action on the page yourself.
When a card is offered:
- Re-validate: the row’s status is not valid, and re-checking would change the status or the issues. A valid row, or one a re-check would leave as it is, gets no card: the copilot says so in a line.
- Mark reviewed: the status is stale or pending review, the row’s ontology has a saved revision, and the check would change something. It is the page’s own Mark as reviewed, which re-runs the same check.
- Delete: an artifact type, a data mapping, an enrichment rule, a matching strategy or a taxonomy. The global default matching strategy gets no delete card, and the Matching Strategies page refuses one while that strategy is open with unsaved edits.
- Create a taxonomy: the confirm button reads Open Add New Taxonomy. It opens the page’s own Add New Taxonomy dialog with the name and description filled in, still editable; only Create there creates the taxonomy. Closing the dialog creates nothing, and the card stays open. A name a taxonomy already has, or one that gives no usable slug (empty or over 64 characters), gets no card.
- An artifact type: the matching strategies bound to it. The data sources and data-source filters that list it only lose it and stay.
- A data mapping: the data sources that use it, with everything under them (filters, scan orders and their records, graph evaluation runs, the steps of any flow that scans them), and the mapping’s own source fields, node mappings and relation mappings. The flows that lose a step are named.
- An enrichment rule: its jobs, with their results and processed-node records. A job running now is said. The flows with an Enrichment step on the rule are named: the step then names a rule that does not exist, and the flow’s check reports it.
- A matching strategy: its own settings. Its entity type is then matched with the next strategy in line from the next ingestion on (a strategy for that type bound to no artifact type, else the global default, else the built-in values). Nodes already in the graph are not re-matched.
- A taxonomy: every term in it, and the places where
@Taxonomyis used (the saved ontology, artifact types and, if you can read rules, enrichment rules) then expand to nothing. Someone who cannot read enrichment rules is told they were not checked.
Continue after a Save
When you Save on the Ontology page, or save an artifact type, a data mapping, an enrichment rule, a matching strategy or a taxonomy the copilot made a card for, the copilot continues by itself. It is never the one that saves: every card still needs your Apply and Save. Replies around cards are short: what the change does, in plain words, and the next step (Next: apply and save it on the Ontology page, then I’ll update the SOW artifact type.). The copilot does not narrate how it waits for your Save; when you Save, it picks up the next step by itself.- After an ontology Save the panel shows a system note (You saved the ontology as revision 7 — continuing with what it affects) and the copilot works out what your Save affected, from the database: which artifact types are now invalid, which were carried through a rename, and which data mappings, enrichment rules and matching strategies need a change. It makes one card per invalid artifact type, each with an Open “NDA” to apply button, and the first one comes with a navigate card to its editor. An artifact type whose attribute or relationship was renamed is already updated by the Save and shows as stale: it gets no card, only a note to open it and click Re-validate in its Compatibility panel (or Mark reviewed), or to ask the copilot for a page-action card that does it. A renamed relationship attribute is the exception: the Save does not carry it, so that artifact type gets a card.
- One kind at a time. A turn makes cards of one kind only, so the cards come one kind per turn, in this order: artifact types, then data mappings, then enrichment rules, starting with the first kind that has something broken. When you have saved one kind’s cards, the copilot continues with the next: one card per broken data mapping, each opening that mapping’s editor, then one card per broken enrichment rule, each opening that rule’s editor. A mapping, rule or strategy that the Save carried through a rename gets no card, only a note to review it and click Re-validate, as for an artifact type. Some rows are left to you, with a line on what to change on their page: a matching strategy (a card can’t change a strategy’s entity type, so the fix is a new strategy for the right type, which the copilot can stage when you ask; ask it to delete the old one and it proposes a delete card that you confirm), a rule whose neighborhood names a relationship the ontology no longer has, and any row on a page you can’t Save on or whose pack is switched off.
- Changes waiting for the ontology. When you ask for a change to an artifact type, or to a saved data mapping, enrichment rule or matching strategy, that needs something the saved ontology lacks, the copilot makes the ontology card first and keeps the change. The ontology card says what it unblocks. After you save the ontology, the copilot proposes the kept change as a card; until then there is no card for it. If you don’t want it, it’s dropped after two ontology Saves.
- A Save that only adds (new entity types, attributes or relationships) leaves no artifact type invalid. The copilot continues with the artifact-type changes it kept with the ontology card, as above. With none kept, it still continues when the Save carried a copilot ontology card you applied and it added entity types or attributes: the system note says what was added (You saved the ontology as revision 7 (added Contract.effective_date) — continuing with the artifact types), and the copilot proposes one card per artifact type that should extract the additions (up to five), or says in one line that none needs them. It continues only after that card was applied and the Save went through; a failed Save never continues this way. A Save you make by hand, with no copilot card in it, doesn’t continue for additions, and neither does one that only adds relationships: when the Save carried a copilot card, the panel notes Revision 7 is saved; nothing built on the ontology needs a change. Ask the copilot for the artifact-type changes that should extract the additions.
- After an artifact-type Save in the editor, the page re-validates the artifact type when its status wasn’t valid before the Save, so a fixed artifact type stops blocking ingestion. The copilot then checks it again. If it’s still broken, you get one more card. If it’s fixed and other cards are still open, you get a short note that points to the next card, with no model call. When nothing is left, the copilot reports what’s valid now, what still needs you and where, and anything it couldn’t fix.
- After a data-mapping, enrichment-rule or matching-strategy Save, with or without a copilot card in it, it is reported to the copilot, and the server first re-validates the row you saved, as Re-validate would (only its compatibility status changes), so a fixed row stops blocking ingestion. When the Save continues the copilot’s work on that row (a copilot card for it was in the Save, or the copilot made a card for it or listed it to fix during this chain of Saves), the copilot then checks it again, as after an artifact-type Save: still broken, one more card; fixed with other cards still open, a short note that points to the next card, with no model call; fixed with another kind still broken, the cards for that kind; nothing left, the report. Any other Save ends with the re-validation, with no model call.
- After a taxonomy Save of a draft that holds a copilot card, the copilot points you to the next taxonomy card still open, with no model call, or does nothing. A taxonomy has no compatibility status to check.
- When a Save or an Apply fails on a page with a copilot card in it, the copilot reads the error and the current state itself and proposes the fix, or, when no card can fix it, says in one sentence what blocks the Save and what you do. It never asks you to explain an error it can read. For a failed Save with no copilot card in it, an Ask the copilot to fix this action lets you ask. On the Data Mapping, Enrichment Rules, Matching Strategies and Taxonomies pages the action is offered even after a reload with the panel closed, as long as you have a copilot session, and it opens the panel. On the Ontology and Artifact Types pages, after a reload with the panel closed, it is offered only once you have opened the panel.
Adding an attribute the saved ontology already has
A card can only update an attribute or entity the artifact type already extracts. When the copilot tries to update one the artifact type doesn’t extract yet but the saved ontology defines (for exampleindustry on Project), the card is refused with the fix: add it with an add operation, spelled as the ontology spells it, with the instructions the copilot gave. The copilot repairs the card in the same turn. An attribute or entity the saved ontology doesn’t define either is still refused, without that fix: the ontology change comes first. Removing one the artifact type doesn’t extract is refused as having nothing to remove.
Graph facts
The copilot can check what ingestion actually wrote to the graph, for any entity type of the saved ontology. It only reads the graph, never writes to it.- Counts: how many nodes the type has, how full each attribute is (over the first 20,000 nodes the graph returns, in no set order), properties the nodes carry that the ontology doesn’t declare (an old name left behind by a rename, for example), and the relationships in and out. These are numbers and names, never a value, and they are not limited by your own graph access.
- Samples: up to five nodes, the first the graph returns in no set order (not the newest), with up to 12 properties each and values cut at 200 characters. Samples show only what your graph access lets you read, even for a superuser. A few properties are withheld from everyone, such as a document’s stored text and ingestion’s bookkeeping; the copilot is told they are withheld, so it doesn’t read them as empty.
- Never-filled report (
list_unfilled_attributes): every entity type of the saved ontology at once (up to 50): the attributes ingestion never wrote on the nodes counted (optionally also those filled below a percentage you name), and the entity types with no node at all (defined but never ingested). The same counts-only read as Counts.
Shared notes
The Ontology and Artifact Types packs also read each other’s shared Notes (see Memory), so a convention agreed on one page holds on the other. Each keeps its own Fixes. Both are for Graph Managers readers only: someone outside Graph Managers gets neither page’s Notes or Fixes, in the copilot or on the Memory tab. The Data Mapping, Enrichment Rules, Matching Strategies and Taxonomies packs each keep their own Notes and Fixes, and also read the Ontology and Artifact Types pages’ Notes. Their own files are for people who can read both the knowledge model and the page: Graph Managers read, plus Data Source Managers read for Data Mapping, or Process Managers read for Enrichment Rules and Matching Strategies (Taxonomies needs Graph Managers read only).Proposals
A proposal renders as a card in the transcript: a one-line brief, a short summary, and a diff of what changed — per-node before/after with inline text diffs, a count of added/removed edges, and any input port the proposal leaves unwired. Each change carries a rationale citing the rule or lint id it rests on (and a run id, when the reason comes from a run you asked about). Occasionally the model sends the edits without a brief or summary; the card is then described from the edits themselves and marked Auto-described so you know those words are generated, not the model’s own reasoning. The diff, validation and Apply gate are unaffected.- Apply copies the proposal onto the canvas through the same path as a hand edit — the flow is not saved for you, so it still shows as unsaved and you can Undo it like anything else you typed. A proposal never renames the flow: the name you gave it (in the header, or in the New flow dialog a list-page proposal opens) stays, whatever name the copilot wrote into its draft.
- Apply is gated on the proposal’s own validation: a card with errors can’t be applied until they’re fixed, and a card with warnings needs an explicit acknowledgement first.
- A card that is now behind the canvas — you edited or applied something else since it was made — is marked stale; applying it still works but warns you first (warn, don’t block).
- Every applied change is chained together into the flow’s provenance, which the publish dialog reads back the next time you publish.
propose.rewrite_existing, off by default) is on in the pack’s settings.
Checked on the server
A proposal of typed edits is not sent to you as the model wrote it. The server first applies the edits to its own copy of the flow and runs the full publish validation on the result — the same structural checks and hollow-pattern lints as the canvas, including the binding-type mismatch check that catches a list-typed input wired from a text port. A result that fails is rejected back to the copilot with the errors, and the copilot corrects its own attempt within the same turn, up to the pack’s repair limit (see Proposals in the Agent Flows settings); when it runs out of attempts it stops and tells you, in plain words, what still blocks the change. When the rejection already carries a repair recipe that itself validates clean, the server accepts that recipe as the card (Fold a clean repair, on by default) and the card names the folded repair — a placeholder the copilot still has to fill is never folded, and neither is a repair that would undo or rewrite a setting the edits themselves make (one that only adds to it, such as the reviewer-feedback lines appended to a prompt the edits rewrote, still folds). Asking to switch Require a result off on an exit that binds a producer is refused with the reason and never quietly switched back on, whether or not the exit had the setting before: the repair that would switch it back on is not even offered to the copilot, and only you can turn it back on, from the canvas. A condition the edits put on an edge is kept the same way: a repair that would put the canvas’s own condition back over it is neither folded nor offered, while one that only drops a condition the edits added (the fix for an edge gated on a step that has not run yet) still folds. A problem that was already on the canvas before the change, on a step the edits do not touch — a hollow-pattern warning you chose to leave, say, or a node you are still wiring — does not block an unrelated card and is never folded away: it rides the card as a warning, marked already on the canvas — not introduced by this change, and Apply waits for your acknowledgement as it does for any warning. A problem the edits introduce, or one on a step they do touch, is still a rejection the copilot has to fix (or a fold, when its repair validates clean). A card that passed arrives marked Checked on the server, and you’re never asked to apply a card and then wire the rest by hand. When the rejection comes with a complete repair recipe that already validates, the server folds it in instead of sending it back: the card arrives with a Folded in by the copilot: line naming the repair (with its rule chips), the summary gains a short clause, and the copilot’s repair budget is untouched. Turn it off with Fold a clean repair in the pack’s settings if you would rather see the model’s own corrected attempt. When a new proposal builds on an earlier card you haven’t applied yet — the copilot adds to the nodes that card introduced — the two are composed into one replacing card. The older card is marked Replaced by a newer proposal, with a link to the card that replaced it; it loses its Apply button, while cards you already applied keep their Undo. Settings proposals are simpler cards — one row per change, setting · current → proposed · reason — and follow the Apply-then-Save path described under On the Settings pages. Artifact-type cards list one line per change, then what Save will also add from the ontology, then any problem the artifact type already had, which the change neither causes nor fixes. Apply writes to the editor and Save persists, as on the Ontology page; see Content Types. An ontology card made on another knowledge-model page opens on the Ontology page, and an artifact-type card made anywhere but in that artifact type’s own editor opens there; see Cards for another page. Re-validate, mark reviewed, delete and create-a-taxonomy cards are the exception: they write nothing to an editor, and Apply opens a confirmation instead (see Page-action cards). Data-mapping, enrichment-rule, matching-strategy and taxonomy cards follow the same pattern: one line per change, then what the page’s Save will also do, then any problem the row already had, which the change neither causes nor fixes. Apply writes to the mapping’s editor, the rule form, the strategy or the taxonomy’s draft, and the page’s own Save persists it. See Data Mapping, Enrichment Rules, Matching Strategies and Taxonomies.Settings — Admin > AI & Agents > Copilot
Three tabs, gated by the same AI Managers permission group as the rest of the AI settings (read-only without write access).Configuration
Below the base settings, each active page pack gets its own collapsible form. The Agent Flows pack exposes:
The Ontology pack exposes:
The Artifact Types pack exposes:
An ontology card made on an Artifact Types page follows the Ontology pack’s edit cap and Downstream impact settings, wherever it is made.
The Data Mapping, Enrichment Rules, Matching Strategies and Taxonomies packs each expose the same two settings:
The act-intent backstop
When a message such as “apply it”, “fix it” or “apply the changes”, a question asking what should change, or a request to suggest changes (“suggest changes to the artifact types”), gets a prose answer with no card, the backstop sends the turn back to the model once. It does this only on a page where you can get a card, and never on a question about what a change would do. What it sends is marked as an automatic check, not your words. After a request to act, it tells the model to answer and make no card if you asked it to wait, not to change or propose anything, or only to explain, and to let a reply stand that declined, or found the change unsafe, impossible or not needed. After a question asking what should change, it first tells the model to reread your own sentences: if one says to wait, to change or do nothing yet, not to propose, that you or your team will make the edits, or that you only want a list, it is told to answer with no card, however you worded it. A turn in which the copilot tried a card is left alone, whether the card was made or refused. So is a turn in which any tool refused something: the refusal’s own hint says what to do next. For an artifact-type card that needs something the saved ontology lacks, the hint points to the ontology card and tells the copilot to make none when you said not to change the ontology or asked for this artifact type only. The backstop stays silent when your own words hold the copilot back. Some examples:- “don’t”, “do not” or “no need to” where an instruction starts, about acting, changes or cards: “No, don’t go ahead”, “do not change anything yet”, “don’t propose anything”, “don’t create any cards”, “don’t add it yet”, “don’t touch the ontology yet”;
- the same with the copilot as its subject, or said again: “I’d rather you don’t touch it”, “I said do not fix it”, “Sorry, I meant don’t go ahead”;
- “Please never fix it”, “There’s no need to change anything”;
- “I don’t want you to” followed by a change or an act (“I don’t want you to fix it”), and “I don’t want cards”;
- an act phrase you put off or disown: “I’ll tell you when to go ahead”, “wait until I say go ahead”, “I didn’t say go ahead”;
- “no changes” or “no cards” on its own or opening a clause: “No cards, I only want your view”;
- “Not yet” or “Not now” opening a sentence, or “not yet” followed by punctuation: “Thanks, but not yet — I’ll tell you when to go ahead”;
- “hold off”, “just tell me”.
- a sentence about how your business works: “we don’t update SOWs after signing”, “we never apply a discount”, “signed SOWs get no changes”, “signing happens later, not now”;
- a negation about something else: “don’t make it required”, “don’t change anything else”, “don’t worry about the tests yet”, “I don’t want you to wait”;
- a question;
- a quoted line (
> …), such as the copilot’s own line that Quote in reply puts in the composer: ”> Not yet: the ontology needs saving first” followed by “Done. Go ahead” is a go-ahead; - a numbered or bulleted line sent with a question, as your customer’s questions usually are.
- A card claimed after a refusal. When every card the copilot tried in the turn was refused and its answer still says a card was made (“I’ve prepared a proposal… apply the card”, “the card I’ve prepared will fix it”), the turn goes back once. The copilot is told that no card was made, to say plainly what was refused and why, and not to say that a card exists. When a refusal kept its change for after an ontology Save, it is told instead that the change will be proposed after that Save, and to answer without saying or implying that a card exists: only the next step, or what the ontology lacks. This check still runs when the backstop above already sent the turn back. It reads words, so an answer that points to a card from an earlier turn (“apply the ontology card above”) after this turn’s card was refused can trip it too.
- “Are we covered now?” On every knowledge-model page, when you ask whether the questions are covered (“are we covered?”, “is everything covered?”, “can we answer these now?”) and the answer called no tool at all, the turn goes back once. The copilot is told to re-read
/km/questions.md, the saved artifact type and the ontology, then answer question by question with what covers each. This check needs no card tool, so it applies to read-only people too. An answer that called any tool stands, even one that only read a skill file.
Skills
A skill is a Markdown playbook (SKILL.md: a frontmatter block with name, description, allowed-tools and a version, then instructions) that shapes how the copilot approaches a page. The page packs ship their own: agentflow-author for Agent Flows (the authoring loop, the grammar, an interview checklist and the anti-patterns to avoid); ontology-author for the Ontology (it leads with the rename-versus-delete rule and the near-duplicate entity types this page is most prone to); artifact-types-author for Artifact Types (writing extraction instructions, and choosing how each entity is matched); data-mapping-author for Data Mapping (mapping source columns onto the saved ontology, choosing the operation and match property, a stable record-id column); enrichment-rule-author for Enrichment Rules (prompts whose placeholders match the input, @Taxonomy tags that exist, a precise instruction for every output); matching-strategy-author for Matching Strategies (which methods run and how much each weighs, thresholds in order, filters that name only what the saved ontology defines); and taxonomy-author for Taxonomies (a clean tree with unique sibling names, and @Taxonomy expanding to the active leaves only). Every knowledge-model page also loads knowledge-model, the shared routine: the questions file, the attachments, graph facts in the first answer, the gap table, ontology first, and a fresh check with the tools when you ask whether the questions are covered.
The Skills tab lists every skill, seeded and admin-authored side by side. You can import a SKILL.md file, edit one in the drawer, and reseed to re-materialize every seeded skill from the shipped source. Every deployment does the same on its own: a new shipped skill appears, and a seeded skill whose shipped file changed takes the new text — replacing any edit made to it here (whether it is enabled, and its order, are kept). To keep a customised version across upgrades, import it as your own skill under a different name and disable the seeded one. A seeded skill can’t be deleted — disable it instead; an admin-authored one can be deleted freely.
Memory
With memory on, the copilot keeps short note files across sessions — the same kind of running notes a person keeps — so it doesn’t re-ask what it has already been told and doesn’t repeat a fix that didn’t work. Memory is modular: one file is yours, and each page pack keeps two files shared by every admin.
A page pack’s shared files follow the access its page needs: the Ontology, Artifact Types and Taxonomies packs’ files are for Graph Managers readers, and the Data Mapping, Enrichment Rules and Matching Strategies packs’ files for Graph Managers readers who can also read that page (see Shared notes). The Settings pack’s files follow the settings page you’re on: in the copilot on the copilot’s own settings pages (its Skills and Memory tabs included) they are for AI Managers readers, and on System Settings for Graph Managers readers, the same access the page’s values need. The Memory tab’s list, and a settings note filed from another page, are for readers of either page. Someone without that access doesn’t get them in the copilot’s prompt, can’t open them with a file read, doesn’t see their cards or their Memory tab sections, and can’t add to them with “remember this for everyone”.
How a fix is recorded. No model is involved. When a run of a flow completes after an earlier run of the same flow had failed, and a copilot proposal was applied between the two, the server writes a fix entry to the Agent flows Fixes file: the error, the node it failed at, the applied proposal’s brief, and the run and proposal ids as evidence. If instead the next run fails with the same error, it records that the attempt did not fix it. On later diagnose-or-fix turns the copilot is shown the Similar past fixes for the error in front of it and is instructed to do something different when an entry says an attempt didn’t work. Only the error’s headline is recorded — never a value a node produced or the run’s content.
“Remember this for everyone.” Ask the copilot to remember something for everyone and it appends one dated line to a page pack’s shared Notes (or Fixes) file, signed with your email. The entry is filed under the area it is about: the pack of the page you are on, unless you name another one (“remember for agent flows: every review step needs a closed loop”, said on the Settings page, lands in Agent flows · Notes). The copilot can’t pick another area on its own: an area other than the page’s is taken only when your message names it (“agent flows”, “Settings”…) or when you pick it on the question card. Otherwise the copilot is told to ask. On a page no pack owns (Admin Home, for instance), the copilot asks which area you mean with a question card, in the same turn, and files the entry under the one you pick. Where Ask the user is set to
deny (see Risk policy under Configuration), there are no question cards: the tool’s refusal tells the copilot to name the areas in its reply and ask you to answer “remember for agent flows: …” (or whichever area you mean), and that answer files the entry. The copilot’s standing memory instructions still mention the question card, so the refusal is what steers it.
It files a shared entry only when a sentence of your own that turn asks for one. For example:
- a keep-ask such as “remember…”, “make a note…”, “record this”, “keep this in mind”, “don’t forget…”, “share this with the team” or “add it to the agent-flows memory”;
- a sentence that opens “For the team: …”, “For everyone: …”, “Our convention is that …” (or “Our convention: …”, “Our rules are that …”) or “For agent flows: …” (an area it can file under);
- for Fixes, also a fix you confirmed (“the retry fixed it”, “that solved the problem”, “it works now”).
- a question, such as “can you remember this for everyone?”: the copilot is told to ask Just for me or For everyone on a card instead (where Ask the user is
deny, to ask in its reply for an answer “remember for everyone: …”); - a line pasted as a list item or a quote (one starting with
-,*,•,1.,1)or>), or text in double quotes. Other pasted text, and text in single quotes, reads as your own words: “Summarise this email: Hi team, remember for everyone: …” asks to keep something; - a negated ask: “I don’t remember what Contract means”;
- something you relay, with “says”, “said”, “claims”, “thinks”, “thought” or “according to” just before it (at most two words between, with no comma): “the log says the retry fixed it”. The same rule means “I think the retry fixed it” doesn’t confirm a fix;
- a framing in the middle of a sentence: “summarise this for the team: keep it short”.
deny, the tool’s refusal tells it to ask in its reply, and only an answer of yours that asks to keep it (“remember for everyone: …”) files the entry there. Pick Just for me and it goes to your User notes; the copilot is told not to ask again.
What you see. Every write to memory — by the copilot, by the server, or by you — shows up as a card in the transcript: Remembered for you for your own notes, Remembered for everyone — Agent flows · Fixes (naming the file) for a shared one, marked recorded from a run when the server wrote it, each with a one-click Undo. The copilot’s own cards stay with the conversation: come back to the session after navigating away — or fork it — and each is still there under the step that wrote it, with its Undo, or reading Forgotten when that write was undone in the meantime, from the card or from the Memory tab. A fix the server recorded while you weren’t looking is announced as a card at the start of your next turn in that session (an announcement, not part of the conversation — it isn’t kept on reload); a session you open later sees it on the Memory tab instead. When the Memory tab is the page the panel is docked on, it refreshes as the copilot writes.
The Memory tab is the durable record of it all, one section per module: User first, then each page pack’s Fixes and Notes. Each section shows the file’s current content and a History of every revision — who made it (model, you, another admin’s email, or recorded from a run), when, the run and proposal ids behind a recorded fix, and an Undo on every row (an already-undone row says so). Undo puts the whole file back as it was before that change, so undoing an older row also removes every change made to the file after it, and an undo can’t itself be undone. Forget clears one module’s file entirely; it’s undoable from the history, because forgetting overwrites the file rather than deleting the record. Forgetting or undoing a shared file follows the Shared writes setting.
Each module is capped at the Max characters per module setting: your User notes are truncated with a marker when they outgrow it, while the shared Fixes and Notes files drop their oldest entries first. A module switched off in Configuration is no longer given to the copilot but stays readable on the Memory tab.
Sessions
Each session is private to the user who started it, titled automatically from the first message (or renamed by hand from the session menu). Opening the panel resumes your most recent open session (a fresh one is created only when you have none, so the opening brief always shows); the + in the panel header or New session in the menu starts a new one, and the menu’s search box finds an older session by title. Closing a session doesn’t delete it — it just stops appearing as active, and it can’t be reopened, not even from the Django admin (/staff/), where its status is read-only — but it does delete the files it sees (those attached to it, and those it inherited from the conversation it was forked from) that no other open conversation still uses, with the text the copilot read from them (see Attaching files). Close session in the session menu asks first and says this. A session whose turn is still running cannot be closed until it finishes. Deleting a session in /staff/ is different: it is a hard delete. It deletes every file attached to that session, with the text the copilot read from it, even files that open forks still use, and those forks no longer see them (nor anything the deleted session inherited). The confirmation page lists the files and chunks it deletes but doesn’t mention the forks.
A long conversation is summarised so it can go on. When the conversation reaches a trigger size, the copilot replaces the older part with a summary, keeps the newest messages word for word (about a tenth of the window), and saves the full older text in a file it can read back. The trigger counts the conversation together with the copilot’s instructions and tools. It is the smaller of two sizes: 80% of the Context window, and what the window leaves after the page context, the memory notes, and room for the reply. That is about 56,000 tokens for a 128,000-token window you enter, 128,000 tokens for a 200,000-token window, and 800,000 tokens for a 1,000,000-token window. An empty setting counts as at least a 200,000-token window, so a normal session is not summarised. A model that really stops at 128,000 tokens can then be sent more than it accepts. When the model rejects a request as too long, the copilot summarises and sends it again. A summary waits until it frees at least as much as it keeps, so a small window is not summarised again straight away. While the summary is being written, the progress row reads Compacting the conversation so I can continue…. After that, the transcript shows Earlier conversation was summarised to save context., once for each summary.
Every message in the transcript has a small row of actions under it (shown on hover, always reachable from the keyboard). Copy puts the message’s words on your clipboard — never a tool’s parameters or results, the copilot’s reasoning, or a card. The notes the copilot writes just before it calls a tool count as reasoning: the panel folds them into a reasoning line (Thinking… while the copilot writes, then Thought for N seconds) that you can open, and Copy skips them. On the copilot’s answers, Fork from here starts a new session — titled Fork of … — whose conversation is a copy of this one up to and including that answer: the same plan and proposals as at that moment, nothing that came after. Files are the exception: the fork sees the files this conversation sees when you fork, including any attached after that answer (see Attaching files). The original session is untouched, and the panel switches to the fork. The fork also inherits the original’s token usage, so forking never resets the per-session token ceiling (see Budget). An answer that is still streaming, or one whose turn is waiting on a consent card, can’t be forked yet — answer or finish it first.
The same row also lets you change course without starting over. On your own messages, Edit takes the conversation back to just before that message and puts its words in the composer for you to rewrite — everything after it is gone, because it will be answered again — and Retry does the same but sends the same words straight away. On the copilot’s answers, Regenerate asks the same question again, Delete turn removes that exchange (your message and its answer) and sends nothing, and Quote in reply drops the first line of the answer into the composer as a > … quote for you to reply under. Rewinding removes later turns too, so when there are any, one inline “This removes N later messages. Continue?” asks first; on the last exchange nothing later is at stake and the action runs at once. None of these are available while the copilot is working, while a question or approval card is waiting, or while another such action is still under way (a message sent from another tab while a rewind is landing is refused with a note to send it again) — and none of them touch what the copilot remembers — memory files written during a removed turn stay, and can be undone from the Memory tab as usual — nor the session’s token count: a removed turn’s tokens were spent, so rewinding never resets the per-session ceiling either.
Prompt caching
Each model call sends the whole conversation again, so the copilot keeps the start of every request the same and lets the provider reuse it at a lower price. The copilot’s instructions, the page’s rules, the skills list and the tools come first, and they do not change from turn to turn on the same page. What changes each turn (the page context and the copilot’s memory notes) is sent in front of the turn’s first message. It stays the same for every model call in that turn, and it is never saved in the conversation.- OpenAI and Azure OpenAI cache automatically, from 1,024 tokens. The copilot also sends one cache key per session, so a session’s calls reach the same cache.
- Claude through the Anthropic API: the copilot marks the tools, the instructions and the conversation so far for caching.
- Gemini caches automatically.
- Claude through Vertex AI is not cached yet.
cache_read, the input tokens read from the cache, and the session’s usage adds them up.
Safety posture
- Proposes only. No tool in the Agent Flows pack saves, publishes, sets a version live, deletes a flow, toggles sub-agent access, or starts/resumes/cancels a run — every one of those stays a human action on the canvas. No tool in the Ontology pack saves the schema, rolls back a revision, resets to the default, changes which ontology is default, or rebuilds a vector index. No tool in the Artifact Types pack saves or creates an artifact type, renames a saved one, or changes its extraction policy. No tool in the Data Mapping pack saves, creates or duplicates a mapping, fetches samples from a data source, or starts a scan. No tool in the Enrichment Rules pack saves, runs, previews or schedules a rule. No tool in the Matching Strategies pack saves or creates a strategy, or changes its entity type. No tool in the Taxonomies pack saves a draft or renames a taxonomy type. No knowledge-model tool writes: the graph and your attachments are read-only to the copilot. The one tool for actions that are not edits,
propose_page_action, performs none of them. It reads the row, dry-runs the compatibility check and makes a card; Apply opens a confirmation, and only your own click on its confirm button calls the page’s own endpoint, with your own account and permissions (re-validate, mark reviewed, delete an artifact type, a data mapping, a rule, a strategy or a taxonomy; creating a taxonomy opens the page’s Add New Taxonomy dialog, where you click Create). See Page-action cards. Never available, on any page: running or previewing a rule, running Test Ingestion, generating embeddings (for rules, artifact types or the ontology), cancelling or resuming jobs, rolling back or resetting the ontology, setting an extraction policy, and importing columns from an API data source. A person does these on the page. The one write that follows your Save of a data mapping, a rule or a strategy is the server’s re-validation of that row (see Continue after a Save), the same as clicking Re-validate. On the Settings pages, a proposal only patches the form; the page’s own Save, under the page’s own permissions, is what persists it. - Secrets stay with people. Encrypted system settings are masked as set / not set before anything reaches the model, and the copilot refuses to propose a value for one. The copilot’s own MCP bindings and write-consent policy can’t be proposed either.
- No MCP writes. MCP bindings are user-credential only (v1); a write-capable tool anywhere is gated by the risk policy’s
confirm/denychoice, never auto-approved. - Navigation is limited to real pages. The copilot can only offer routes the admin app has told it it renders. Anything else is refused, or, when it names the page a card of this conversation was made for, replaced by that page.
- A pack carries the permission of what it wraps, not the copilot’s own. Being able to open the copilot is not enough: the Ontology and Artifact Types packs’ tools, the knowledge-model tools and file attachments are gated on the same Graph Managers read access as those pages themselves, and are not offered at all to a user without it. Such a user is not shown the ontology or the artifact types either: the page context, the opening summary and the files the copilot reads say only that they are not available to them. Proposing there additionally needs write access, cards for the Ontology page made from another page included, because a card a person cannot save is a dead end. The Data Mapping, Enrichment Rules and Matching Strategies packs also need their own page’s group (Data Source Managers, Process Managers), on every page their tools reach: a Graph Managers member outside that group gets none of their tools or notes, and nothing of their rows beyond what the Compatibility page already shows them (the name and issue of a row that isn’t valid), the Ontology page included. The Settings pack follows the same rule: the copilot’s settings for AI Managers readers, System Settings for Graph Managers readers, and a note that the page isn’t available for anyone else. The copilot’s System prompt extension is the exception: it is part of the copilot’s instructions for everyone who can open it.
- Attached files are data. Their text is handed to the model marked as data from a document the person attached, never as instructions, and only the person who attached them, in their own session, can list, search or remove them.
- Raw run content never reaches the model at the default tier. Tier 0 diagnostics are built to be content-free by construction — status, error shape, timings, token counts, never a value a node produced. A step or tool call that failed shows up as its error class, a shape word and the length of its text, not the text. One kind of content does ride along at Tier 0: the values of the parameters the flow declares (what you typed when you started the run — a topic, a title, a date), secret-scrubbed and cut at 200 characters each, because a run’s diagnosis usually starts with what it was asked to do. Nothing a node produced is among them. Turning run access up to Tier 1 allows a small, allow-listed set of fields (a reviewer’s comment, the run’s error message, one failed step’s error text, the error bodies one step’s tool calls returned, one named node output, a DOCX’s headings) to be read in capped excerpts, only when you ask for the words; every such read is wrapped as untrusted data and recorded in an audit log, one row per read.
- Memory is data, not instructions. Every memory module is handed to the model fenced as notes it may not treat as instructions, and the shared files are append-only for the model, size-capped, written only through the gate above, and undoable — so one admin’s session can’t quietly re-instruct every other admin’s copilot.
- A hidden system file, and the skills directory, are write-denied to every proposal — the copilot cannot rewrite its own instructions or context.
- Run text is never pasted into a proposal. A proposal that echoes text verbatim from a run excerpt you read this turn is refused outright.
Troubleshooting
- A turn stops with a budget message. The turn hit its per-turn model-call, tool-call, token, or wall-clock limit (see Budget). A turn that ran out of model or tool calls ends with a short notice line in the transcript, which is still there after a reload. Nothing is lost — send another message to continue, or raise the relevant limit in Configuration if this happens often.
- A session seems stuck or is answering oddly. Start a New session — the old one and its transcript are still there if you need to look back at it.
- Apply on a page-action card refuses, or the confirmation never opens. Apply refuses with a message when the card’s row changed since it was made (ask the copilot again), when you lack write access in the page’s group, when the card belongs to another page (open its list with the card’s Open button), or while another action is still being checked or waiting for your confirmation (finish or cancel that one first). A failed confirm leaves the card open and nothing applied. See Page-action cards.
- The copilot says the admin guide index is out of date. The guide is re-indexed automatically at server start when a page changed on disk, so this usually means a page changed since the server last started. Admin > Monitoring > Startup Health shows the Admin Help doc index check as READY or DEGRADED with an Ensure action that re-indexes the changed pages;
python manage.py index_admin_docsfrom the server directory does the same. Until then the copilot answers page and settings questions with that caveat rather than from memory. - The panel doesn’t appear, or a turn always fails immediately. Check Admin > Monitoring > Startup Health for the copilot’s checks: whether its model resolves, whether the stored profile still validates, whether sessions can checkpoint, and whether every enabled skill is synced to the store. A failing check here explains most panel-wide issues before you need to look further.
- An attached file shows Failed. Hover the chip for the reason. No text could be extracted usually means a scanned PDF that OCR read nothing from, and an error that starts Scanned PDF always means a scan nobody read: you chose Skip, the OCR read almost nothing, or the OCR hit its memory or time limit (see Scanned PDFs under Attaching files). Attach a text version (a Word file, or a PDF whose text can be selected). Reading this file stopped means the server reading it stopped responding, usually because it restarted: a file whose reading shows no progress for five minutes is marked this way. Remove it and attach it again. A file a fork inherited has no × while another open conversation still uses it, and its chip names those conversations (up to three, and how many more): close them and remove it in the fork, or remove it in the conversation it was attached to while that one is open. Not UTF-8, UTF-16 or Windows-1252 text: save the file as UTF-8 (in Excel, CSV UTF-8) and attach it again; see Text files under Attaching files. The same fix applies when a ready file’s chip shows an amber warning icon (it was read as Windows-1252, or as UTF-16 without a byte-order mark) and its letters look wrong in the copilot’s answers. An amber icon whose tooltip starts Scanned PDF means almost no text could be read from the file: attach a text version. Expands to … MB when unzipped (or one part of the file expands to …): the file is a zip inside (an Office file, or a zip under any other name) and is too large to read safely; split it, or export the part you need. This file is too large to read here (reading it needed more than 3072 MB of memory): even the background parser’s limit,
ASYNC_PARSE_MAX_MEMORY_MB(3,072 MB by default), was not enough. A small spreadsheet with very many cells that all repeat one long text (hundreds of millions of characters once read) can do this. Attach a smaller file or a text version, or export the part you need. If the file is one you need whole, raise the setting (in/staff/, Configuration Settings) only on a parser with that much memory to spare (see Deployment). A file that the server’s own reading cannot finish (past its 512 MB or 60 seconds) is handed to the background parser instead of failing, so this message names the parser’s limit, not the server’s. The server ran short of memory while reading this file: the container or machine reading it (the parser’s, once the background parser has the file) had less than 768 MB of memory left, or the system stopped the reading for lack of memory. On the API server the file is handed to the background parser instead. The parser tries it again up to three times, and only then fails with this message: attach it later, or a smaller file. If this happens often, the parser (or the server) needs more memory (see Deployment). Reading this file took too long: one reading took longer than the background parser’s limit,ASYNC_PARSE_TIMEOUT_SECONDS(1,800 seconds by default; Kreuzberg’s own timeout,KREUZBERG_REQUEST_TIMEOUT_SECONDS, applies inside it). Split the file, export the part you need, or raise the setting (in/staff/, Configuration Settings). Parsing is unavailable right now; try again later: the file waited for the background parser longer thanASYNC_PARSE_QUEUE_WAIT_SECONDS(60 minutes by default), usually because the parser could not start. Remove the file and attach it again later (see Async Document Parsing). Reading this file failed after N attempts: the parser stopped under the file each time (ASYNC_PARSE_MAX_ATTEMPTS, 3 by default). This file needs the background reader, and N of your files are already waiting to be read …: you are at the limit on background files; remove the file and attach it again once one of the others is ready or has failed. Reading this file was cancelled; remove it and attach it again: something cancelled its reading before it finished. - A file stays on Waiting for the parser. Parse in the background is on by default, so every file you attach waits for the parser, even a small one; turn the switch off to have small files (1 MB or less, spreadsheets apart) read right away on the server. The background parser may be starting from zero replicas, which takes several minutes, or it is busy: each parser replica reads one file at a time, and people take turns. A scan that waits for your Read with OCR or Skip shows Scanned PDF (N pages), not this. A file still waiting after 60 minutes fails (see the previous item). See Async Document Parsing.
- The eye says it cannot open a file, or a document is missing from the picker. You can no longer open this document (it was removed, or you lost access to its source) means your open session no longer holds the file: the file was removed or the session was closed. This document is still being read. and This document is waiting for your OCR choice (Read with OCR, or Skip). mean the document is not ready yet. A Parse only document whose stored text is gone is not listed in the picker, and neither is an Ingested one while graph access control is enforcing: re-ingest the document (requeue it from the Download Phase), or upload the file. For every other reason, go through I can’t find my document in the picker. See also Picking and previewing parsed documents.
- A file’s tooltip says it is searched by keywords only. The search model could not load on that server, usually because it could not be downloaded (see Deployment), or it failed on that one file. The file is still read and searched, just not by meaning. When the model works for other files, remove this one and attach it again to have it searched by meaning.
- There’s no paperclip, or attaching is refused. The paperclip (and dropping files on the panel) works only on the knowledge-model pages (Ontology, Artifact Types, Taxonomies, Data Mapping, Enrichment Rules and Matching Strategies), once the panel has a session. Attaching needs the Graph Managers role (read). If the session is no longer available, start a new one and attach the file again. You already have 10 files waiting to be read: wait until one of your files shows ready or failed, then attach again (a file waiting for the background parser, or for your OCR choice, counts too). N of your files are already waiting to be read (at most N at a time) is the parser’s own limit on background files across every part of Experio (
ASYNC_PARSE_MAX_QUEUED_PER_USER): the same advice applies. A file you have just removed can still count for about 30 seconds.
Deployment
The copilot runs inside the API process: a turn is an in-process task streaming to the socket that started it, and a REST rewind holds that session’s busy slot for the length of its request (a close is refused while it is held). Two things follow for anyone running more than one API process (several Daphne workers, or several replicas behind one ingress).- A session’s socket must reach the process running its turn. A turn’s stream can only be delivered by the process that runs it. A panel whose socket lands on a different process after a reconnect sees no turn on connect, and its next message is refused with a turn is running on this session on another worker until that turn ends — the turn itself finishes normally, and the transcript catches up on reload, but nothing streams. Route the copilot’s WebSocket path (
/ws/admin-copilot/) to one API process, or turn on session affinity (sticky sessions) on the ingress for it, so a reconnect goes back to the process it came from. - The busy claim is shared; nothing else needs configuring. Whether a session is busy — a turn running, a rewind under way — is recorded in the default cache (Redis, the same
REDIS_URLthe channel layer uses), so a message, rewind or close served by any process while another runs the turn is refused with a 409 or the socket error above rather than racing it. A process that dies mid-turn stops holding its sessions within a minute. If Redis is unreachable, each process falls back to its own view and logs a warning: the copilot keeps working on a single process, and only the cross-process guard is off for the outage. - Startup Health says whether that claim is actually shared. Admin > Monitoring > Startup Health carries an Admin copilot shared busy claim check. It reads the configured default cache backend and reports READY when it is Redis; when
REDIS_URLis unset the default cache is Django’s in-memory one, the claim is per-process, and the check reports MISSING naming the backend it found and telling you to setREDIS_URL. A deployment running one API process is unaffected — the per-process half of the slot is the whole slot there — so the check is a warning about scaling out, not about the copilot being broken today.
-
Files are read in turns, each in a child process. Each API process reads attached files on its own background threads, one by default. The other files wait in its queue and take turns between the people who attached them: the next file read is the oldest waiting file of whoever has the fewest files being read, then of whoever’s last file started longest ago (someone with no file read yet goes first). With one reader, a person’s next file therefore waits for the file being read and at most one file of each other person with files waiting, however many files one person has queued. A file that is already being read is never interrupted to give someone else a turn. One person’s own files are read in the order they were attached, so a small file still waits behind that person’s own earlier files. The turns are kept per API process: several API processes each keep their own queue. With more readers (
COPILOT_DOCUMENT_WORKERS, below), nobody gets a second reader while someone with no file being read has one waiting. The parsing itself (Kreuzberg, then the builtin parser when Kreuzberg reads nothing) runs in a child process: the API process starts one for each attempt and watches it. The API process never opens the file, not even a PDF’s page list: before a child reads a PDF, it writes down the page count and whether the PDF has a text layer, so the API process still has them when the child is then stopped. A child stopped at a limit hands its file to the background parser (see below), whether or not it got that far. A child is stopped when its memory passesUPLOAD_EXTRACTION_MAX_MEMORY_MB(512 MB by default, checked every 0.1 seconds) or when it runs longer thanUPLOAD_EXTRACTION_TIMEOUT_SECONDS(60 seconds by default). Both are Configuration Settings in the Django admin (/staff/), JOBS category. They are not listed on Admin > System Settings, and the Settings copilot doesn’t see them (see System Settings). The time limit applies to each attempt, so a file that Kreuzberg can’t read and the builtin parser then reads can take up to twice as long. The child hands back at most about 2,200,000 characters. The API process keeps the first 2,000,000, then splits them into chunks and embeds them itself, which takes memory and CPU there too. A file the background parser reads keeps its whole text and is chunked and embedded by the parser, not here. A plain-text file (.txt,.md,.csv,.json) is decoded in the API process. WithKREUZBERG_MODEset toapi(a deprecated rollback path), Kreuzberg reads on its own server, and only the builtin parser runs in a child process, with one more short child process that counts a PDF’s pages. -
OCR never runs on the server. The first reading of an attached file never uses OCR, so a scan costs almost nothing there (a 3-page scan: about 45 MB instead of 1.7 GB). A scan goes to the background parser, which reads it by OCR in its own container, within
ASYNC_PARSE_OCR_MAX_MEMORY_MB(3,072 MB by default) andASYNC_PARSE_OCR_TIMEOUT_SECONDS(1,800 seconds by default). The threeCOPILOT_ATTACHMENT_OCR_*settings, which used to limit an OCR reading on the server, are no longer used. Test Ingestion reads a picture by OCR in place (see Content Types). WithKREUZBERG_MODEset toapi, Kreuzberg’s server reads with its own OCR, and nothing is read again with OCR in the API process. -
Big files go to the background parser.
UPLOAD_EXTRACTION_MAX_MEMORY_MBis 512 MB by default (it was 1,024 MB, and 3,072 MB before), so a reading on the server is stopped at about half a gigabyte. The first upgrade moves a setting that still holds its old default (3072, or 1024) to 512, and keeps any other value, as well as a 3072 or a 1024 you save after that. A file stopped there, in the copilot, the main chat or Test Ingestion, is handed to the background parser instead of failing, and a file overASYNC_PARSE_PRECHECK_MAX_FILE_MB(1 MB) or a spreadsheet overASYNC_PARSE_PRECHECK_MAX_SPREADSHEET_MB(0 MB, so every spreadsheet) is handed over before the server reads it. In tests on a fast laptop at the earlier, higher limits, ordinary files under them needed about 140 to 365 MB and finished within about 25 seconds. That is not a maximum: a file that needs more (for example a spreadsheet with a very large sparse table, or a Word file with one enormous table) is stopped at the limit and read by the background parser instead, so nothing fails, and a server slower than the test machine stops some text-heavy PDFs at the 60-second limit and hands them over too. A very dense spreadsheet near the 25 MB upload limit takes about 2 GB, which only the parser can give. A Test Ingestion picture is the one reading that is not held to this limit (it keeps at least 1,024 MB), because only OCR on the server can read it. Size the parser’s memory forASYNC_PARSE_MAX_MEMORY_MBandASYNC_PARSE_OCR_MAX_MEMORY_MB(3,072 MB each by default) and for embedding (see Async Document Parsing). -
Size the server’s memory for the readings. The memory limit applies to each reading, not to the server. Readings run side by side when
COPILOT_DOCUMENT_WORKERSis above 1, and each Test Ingestion run reads in a child process of its own (nothing limits how many of those run at once), so readings together can use that many times the limit. The main chat reads its small uploads in a pool of two reads at a time per API process, in child processes with the same limits. A reading that grows fast can pass the limit by a few hundred MB before the next check stops it. Give each server at least the limit for every reading it may run at once, plus what the API process itself uses. This is also why files are not read side by side unless you ask for it: theCOPILOT_DOCUMENT_WORKERSsetting (a Configuration Setting in/staff/, LLM category, 1 to 4) applies when the server restarts. Raise it only on servers with memory to spare. -
A reading is stopped before the server runs out of memory. At every check (every 0.1 seconds) the API process also measures how much memory its container or machine has left. It takes the smallest of:
- the cgroup v2 or v1 memory limit, less what the container holds that the kernel can’t drop (its usage less the page cache on the active and inactive file lists);
- the machine’s
MemAvailable.
-
Removing a file stops its reading, but not at once. This holds for removing a file and for closing the last open conversation that sees it. A file still waiting for its turn is dropped: the server holding it deletes its upload within about 30 seconds, and it is never read. Once the server has dropped it, it costs its owner no turn. Before that, a reader that frees up can still take it in its turn: it stops at the first check, before anything is extracted, but the turn is spent. A file being read stops at its next check: before its text is extracted, once the text has been extracted, and before each batch of 32 chunks is embedded. The step under way finishes first, so a large file that is being extracted (for up to
UPLOAD_EXTRACTION_TIMEOUT_SECONDSper attempt) or split into chunks runs to the end of that step. Nothing is stored for it either way. A file the background parser holds is cancelled the same way: a file still waiting is never read and its upload at the parser is deleted, and a reading in progress stops within about half a minute. A person’s new file is refused while 10 of theirs are waiting or being read, across all their conversations (a file waiting for the background parser counts, and so does a scan waiting for the person’s OCR choice); this keeps one person from growing a server’s queue and its temporary upload files (up to 25 MB each) without limit. The limit is fixed; it is not a setting. The parser keeps a limit of its own over all of a person’s files,ASYNC_PARSE_MAX_QUEUED_PER_USER(see System Settings). - A file whose server stops is marked failed. While a file waits or is read, the process holding it records its progress every 30 seconds. A file with no progress for five minutes (its process restarted, was redeployed, or ran out of memory) is marked failed the next time its conversation lists its files (see Troubleshooting). A queued file is lost with its process the same way. A file waiting for the background parser is not marked failed like this: it has timeouts of its own (see Async Document Parsing).
-
The default search model ships in the server image. Files are searched by meaning with an embedding model that Kreuzberg runs locally: no API key, and no network call per search. The server image holds the default preset’s model (
balanced) in Kreuzberg’s cache (KREUZBERG_CACHE_DIR,/opt/kreuzberg-cache), so a server needs no outbound access for it. Any other preset is downloaded from Hugging Face into that cache the first time a server needs it; the cache is not on a persistent volume, so that happens once per container start. A server run outside the image downloads even the default model on first use, into~/.cache/kreuzberg/embeddings/of the user it runs as. If the model can’t load (a download fails, for example), files are still read and searched by keywords only, and that server does not try the model again for five minutes. Once the model has loaded on a server, a later failure affects only that file (kept for keyword search only) or that search: the next file and the next search use the model again. The parser image ships the same default model, for the files the background parser embeds. -
Which model is the
COPILOT_DOCUMENT_EMBEDDING_PRESETsetting (a Configuration Setting in/staff/, LLM category):fast,balanced(the default),qualityormultilingual. Changing it applies to files attached afterwards; files already indexed keep the model they were indexed with and stay searchable. A file the background parser reads is always embedded withbalanced, whatever this setting says. - Search memory. File searches run on threads of their own, so a slow one never holds up the database calls of other open chats and panels on the same process. Each API process keeps the vectors of recently searched files in memory, up to 128 MB, so a search does not decode them again.