Skip to main content

Mindset 🧠

Mindset is the AI coaching platform behind Mindset Coach, the agent surfaced in the Hub and on Helix pages. For the agent to answer questions about a customer's own material, that material has to be pushed to Mindset first — this page covers how Hub content gets there.

Mindset organises ingested content into contexts (also called knowledge banks). A Hub has one bank of its own, and each team can have another, so content reaches only the audience entitled to it.

Which Hubs synchronise

A Hub is included in the sync when its domain is active or maintenance, is native to the region running the sync, and its config carries all three of:

Config keyMeaning
mindsetAppUidThe Mindset application this Hub belongs to
mindsetBankUidThe Hub's own knowledge bank
mindsetAutomaticIngestionMust be 'true' for the sync to run at all

Teams with a mindset_uid set get a bank of their own alongside the Hub bank.

When it runs

synchroniseHubsWithMindset() (api/modules/mindsetContent/contentSynchroniser.js) is exposed as a procedure over the buslane event bus and triggered by 5app/schedule-worker on cron 0 18,22,2,6four times a day. Hubs are processed one at a time.

Before any Hub syncs, one query sweeps them all for videos that need an MP4 rendition. Covering every Hub at once means a video shared between several of them is converted once, and no Hub waits on another Hub's sweep before its own sync starts.

Each region runs its own sync, over the Hubs it owns.

Ingestion is therefore never immediate. Content added to a Hub becomes available to the agent on the next scheduled run, not on upload.

A single Hub's sync

Banks with nothing in the report are still processed with an empty list, which is what removes content from Mindset after it stops being eligible in the Hub.

A failure in one bank is reported to Slack and does not stop the others; the Hub is still marked as failed once they have all been attempted.

What is eligible

mindsetEligibleContent (api/db/methods/reports/mindsetEligibleContent.js) is the single definition of what a Hub may send to Mindset, with no opinion about whether anything can read it. Two consumers build on it: the mindsetIngestion report adds the rendition join that decides what Mindset can actually ingest, and the video rendition sweep looks for exactly the rows that join excludes. Deriving both from one query is what stops them disagreeing about eligibility.

The report is also downloadable by admins as the Mindset ingestion report.

A piece of content is included when it is:

  • an upload (not a web link) that is not deleted, and sits in a playlist that is not deleted;
  • available in this domain, with exclude_from_ai unset on both the asset and its domain sharing record;
  • permitted by the Hub's coachAiPermissions setting — all includes everything, teamsOrEveryone narrows to content shared with teams or everyone, and otherwise the content must be shared with everyone or with a team that has its own bank;
  • backed by a file in a format Mindset can read.

That last condition is stricter than it looks. The report joins the file and its renditions with an inner join on the supported mime types, so content with no readable file does not appear as inactive — it does not appear at all.

Formats Mindset can read

MINDSET_SUPPORTED_MIME_TYPES (api/constants/mindsetContent.js) is shared between the report and the conversion pipeline, so the two cannot drift:

text/plain, text/html, application/pdf, audio/mpeg, video/mp4, .docx, .pptx, and unzipped archives.

Where an asset has several candidates — its original file plus one or more renditions — selectFileRendition() picks by the order of that array, so it is a preference list, not just a filter.

Special cases

  • SCORM packages are sent as application/zip with zipType: 'scorm' so Mindset unpacks them.
  • Text content is sent inline. Rather than a download URL, the extracted text stored on the file row is passed as documentContent; content that has no extracted text is skipped.
  • Microsites and fluidbooks cannot be ingested automatically and are skipped.
  • Names are truncated to 100 characters, which Mindset does anyway — the Hub matches it so that comparisons on later runs do not see a difference that is not there.

Reconciliation

Each run compares what the report says a bank should hold against what Mindset reports it does hold, matching on externalId (the Hub asset id).

Deletes

Deleting is also how an update to a file happens: there is no replace, so a changed file is removed and re-inserted on the same run. The content hash is the file's creation time, so a genuinely new file produces a newer hash.

An item that is neither published nor failed after two hours is treated as stuck, deleted, and retried.

Inserts and metadata changes

Anything in the report that Mindset does not hold is created. Items that survive the deletes are checked for drift in five fields — name, hideContentSegments, knownAs, externalUrl and viewOriginalSource — and patched in place if any differ. These are metadata-only changes; the file content itself is never patched.

Failure handling

Every failed or stuck ingestion writes a row to mindsetIngestionFailures recording the status and message Mindset returned.

Once an asset accumulates three failures within 48 hours it is marked exclude_from_ai, with a changelog entry attributing the change to Mindset. It then falls out of the report and stops being retried, so one broken file cannot consume every run indefinitely. Clearing the flag on the asset puts it back in the queue.

Video fallback

Video is the one format where the Hub actively produces something for Mindset rather than sending what it has. video/mp4 is the only readable format, so a video uploaded as .mov, .avi, .wmv, .mkv or similar is missing from the report entirely — silently absent from the knowledge bank rather than visibly failing.

Each sync asks for MP4 renditions of the videos it cannot read, and picks them up on a later run once conversion has finished:

  • Each run is capped at VIDEO_RENDITIONS_PER_RUN (default 50) videos across every Hub. The cap only bites while a backlog exists, so in practice it bounds a Hub arriving with a large video library rather than the day-to-day rate. Conversion is billed per Zamzar credit against one account shared by all regions, and nothing checks the remaining balance before converting.
  • A video shared from another Hub is converted once, by the region that owns the file, and the rendition then reaches every Hub and region it is shared with through ordinary content sharing. A Hub shown content another region owns asks that region to convert it rather than converting its own replica.
  • A failed conversion is harmless. The video stays playable and simply remains absent from the knowledge bank. Later runs try again, up to a fixed number of attempts.

The conversion mechanics — states, retries, and how the rendition is produced — are covered in File Conversion.