Skip to content

Cortex add-ons

A Cortex add-on is a per-workspace entitlement to a knowledge pack: a corpus Cortex can ground answers in, on top of the always-on Logrite product corpus. The first one is Worksoft Cortex, covering the Worksoft Connective Automation Platform.

An enabled add-on reaches every surface at once — Cortex chat, the chat API, the REST API and the MCP server. There is no per-surface switch, because an assistant that knows something in one place and not another is worse than one that does not know it at all.

Table workspace_addon, one row per workspace per add-on, unique on the pair. It has to be there rather than in the AI service, because the same answer gates three processes — Cortex, the REST API and the MCP server — and the backend is the one that already owns workspaces.

RouteAuth
GET /api/v1/workspaces/{id}/addonsmember, or a Logrite API keyEvery catalogue entry with its state
PUT /api/v1/workspaces/{id}/addons/{key}Admin or Owner{"enabled": true|false}

Both emit GovernanceAudit rows (workspace_addon_enabled / _disabled).

An API key is accepted on the read because the two machines that need this answer — the AI service deciding whether a question reaches the Worksoft corpus, and the MCP server deciding whether to advertise the pack as a resource — hold a key and nothing else.

enabledAddons(workspaceId, bearer) in the AI service reads the backend and caches for 15 seconds per workspace (60 s until 2026-10-14). A JWT claim would not do: a session token is issued for hours and a toggle has to take effect while the person who flipped it is still looking at the page.

A refusal re-reads first (2026-10-14). Before POST /ask answers 403 ADDON_NOT_ENABLED, or GET /packs/:key answers 404, the route calls enabledAddons(…, { fresh: true }) once — which skips the cache read and writes the fresh answer back — and refuses only if the pack is still absent. Before this, Worksoft search refused for up to a minute after the add-on was enabled (MCP test report R10): the cache was per process and invalidateAddons had no callers. GET /packs stays cached; a listing that lags 15 s costs nothing.

The same re-read covers an /ask with no packs, which is what MCP’s knowledge_search sends: when the question names a disabled add-on’s domain (the disabledAddons hint) and the entitlement came from the cache, the route re-reads once, fresh, before answering without it. The first fix covered only the explicit-packs refusal, and on dev a Certify question asked 0.6 s after enabling Worksoft Cortex was still answered “not enabled for this workspace” (ai-service 9f11f52).

An unreachable backend returns the last known list and logs [addons] stale. The failure modes are not symmetric — serving a stale “enabled” for a minute costs nothing, while an add-on that silently switches off mid-incident produces answers that are wrong in a way nobody attributes to a network blip.

packsFor(enabledKeys) then returns the Logrite pack plus any entitled pack, and retrieval scores across all of them. A pack the workspace lacks is absent, not deprioritised, so no scoring accident can ground an answer in it.

Retrieval is unchanged, and still deterministic

Section titled “Retrieval is unchanged, and still deterministic”

Same scorer: section ×5, question ×3, body ×1, +2 for a route match, floor of 5. A gated pack adds +3 when the question names one of its own nouns — “Certify”, “Execution Manager” — because such a question is unambiguously about that pack and must outrank a generic Logrite topic sharing a word like “run” or “results”.

The prompt block renders one section per contributing pack, each ending in that pack’s attribution line. Two corpora merged into one undifferentiated list would let the model answer a Logrite question with a vendor procedure and present both as ours.

77 distilled topics across 15 sections, from 59 cited pages of docs.worksoft.com (pack version 2026-10-16), plus a mined signature catalogue from the Worksoft log corpus this estate has ingested.

Sections: Platform architecture · Certify authoring · Test flows and execution · Interfaces and learn tools · Integrations · Continuous Testing Manager · Business Capture · Process Intelligence · Worksoft Impact · Automation Insights · Worksoft Portal · APIs and automation · Coding and authoring practices · Diagnostics and error signatures · Security, audit and access.

Distilled, never reproduced — and that is enforced

Section titled “Distilled, never reproduced — and that is enforced”

docs.worksoft.com reserves reproduction rights. Every answer and every step is written in our own words with the source URL beside it, and scripts/generate-worksoft-knowledge.js fails the build when any field shares more than 25 consecutive non-identifier words with the page it cites. Identifiers that cannot be paraphrased without becoming wrong — %AppData%\Worksoft, /CertifyResultsAPI/api/v1/..., Help > Show Log > Collect Logs, exception type names — are exempt.

Both gates were fired deliberately before shipping: a section minimum set beyond reach exits non-zero naming the section, and a 30-word lift from a fetched page is refused with the offending phrase quoted.

The generator also:

  • fetches every cited page and fails on a non-200 — a citation that 404s reads as “that fact is wrong”, not as “that link is stale”;
  • enforces a minimum topic count per section, because the add-on card claims to serve every Worksoft segment and an empty section is coverage the product does not have;
  • writes a per-page sha256 of the page’s text into worksoft.manifest.json, so a later run reports which pages moved rather than “something changed”. The text, not the HTML (since 2026-10-16): a site-wide template or footer change rewrites every page’s HTML and would flag all of them at once;
  • crawls one request at a time with a 500 ms gap, a named User-Agent, and a hard stop after three consecutive non-200s — a docs site that starts refusing must not silently produce a shrunken pack.

scripts/mine-worksoft-signatures.js reads the ingested Worksoft indexes and emits, per distinct normalised message template: service, level, template, first and last seen, and count. likelyCause and whatToCheck are hand-written or empty. A generated diagnosis presented beside a real count is an invention wearing a citation, and the citation is what makes it believed. An un-annotated template is still useful — it lets Cortex say “this is one of the forty most common Scheduler messages and is routine”, which is a different and honest claim.

Log analysis. When a finding’s evidence lines match a mined template, the finding carries a knowledge block with the service, the likely cause, what to check and the source URL. That is the difference between “here are 29 errors” and “here are 29 errors, this is what that service does, and this is what to check” — and it has to be reachable from a partner-key request, not only from a browser session, which is why the AI service can hold its own LOGRITE_ADDONS_TOKEN.

Route
GET {ai}/api/v1/knowledge/packsEvery pack with enabled for this workspace
GET {ai}/api/v1/knowledge/packs/:keyOne entitled pack’s topic index: {key, name, addonKey, topics: [{section, question, source}]}. Never the answer bodies. 404 for an unknown pack and for one whose add-on the workspace has not enabled (one answer for both)
POST {ai}/api/v1/knowledge/ask{"question", "packs"?} → answer, citations, packsUsed, attribution; spellingRepaired: [{from, to}] only when misspelt pack words were repaired to find the answer; meaningUnavailable: true only when nothing was found and the meaning step could not run

The MCP server’s knowledge resource reads /packs/:key and returns its JSON; there is no separate pack-listing tool.

All three take either a session JWT or a Logrite API key (lgp_live_). That is not a convenience: the MCP server forwards the developer’s raw bearer, and a Claude Code plugin user has no JWT at all.

/ask returns the assembled retrieval block rather than a written paragraph: no model runs, so the same question returns the same citations, which is what makes it usable as a test.

Matching by meaning when no words match (2026-10-15)

Section titled “Matching by meaning when no words match (2026-10-15)”

The word rules search an add-on pack only when the question names one of its products, and then need two words shared with a topic heading. “Our PI export keeps failing with 401” names no product, so it answered matched:false on both estates while the pack has a topic for exactly that. The synonym list (88ab3fd) did not help, because synonyms are read only after the product check.

When the words find nothing, and the question names no add-on the workspace has turned off, /ask now compares the question by meaning with every topic heading of the workspace’s packs (src/knowledge/meaning.ts). The question is embedded by the semantic API’s model, using the caller’s own bearer. It answers from the nearest topic only when all three of these hold:

CheckWhy
Similarity ≥ 0.50Right matches measured 0.51–0.70 on dev. Kubernetes, Kafka, a recipe, SAP transports and sales tax stayed under 0.36.
No other product namedA capitalised word after the first that appears nowhere in the packs’ own text, such as Jenkins, is another product. “How do I retry a failed Jenkins build?” scored 0.58 against the CTM retry topic. The model can’t tell the two apart; the corpus can.
Not ambiguousAn add-on topic must beat the best Logrite topic by 0.05. “Where are my application log files?” scored 0.644 against Worksoft and 0.629 against Logrite. A question that fits both equally isn’t evidence the user means the vendor’s product.

The pack’s synonyms are written beside the word they stand for before embedding, e.g. “PI (intelligence)”, “401 (unauthorized)”. The response says which path answered: matchedBy: "words" | "meaning" | null, so a reader can weigh a looser match.

Measured on dev (workspace 3103, ai-service 05519db). These are 18 questions written before the first live run, none of them used for calibration:

GroupResult
Worksoft questions in the user’s own words6 of 8 answered correctly: the 401/PI export, “run it again”, Power BI, the sign-in step and Business Capture by meaning, the exporter’s authentication by words
Off-topic (nginx, Gmail, Spring, cron, pandas, CSV contacts, GitHub Actions, Jira)0 of 8 answered
Logrite questions2 of 2 answered

The two misses: “make my automated tests data driven with a spreadsheet” found nothing. “Where can I find the scheduler service logs?” was answered from the wrong Logrite topic by the older word path (matchedBy: "words"), which the meaning fallback never reaches. On the calibration set, all four questions that failed before (PI/401, rerun, rejected creds, process mining) now answer, by meaning.

On /ask, a pack the workspace has not enabled answers 403 naming the add-on and where to enable it — never an empty result — after one fresh re-read of the entitlement (above). “No results” for an entitlement problem is indistinguishable from an empty corpus, and sends the reader looking for missing documentation.

Runnable from Sandbox → Playground → Ask a knowledge pack.

Every gate in front of a pack keys on exact spelling. A vendor pack is searched only when the question contains one of its product names (retrieve.ts); /ask keeps a topic only when two question words share a stem with its heading (ask.ts); and Cortex treats a turn as a product question only when a product name is present (detectProductKnowledge). So “wroksoft portal logs”, “certfy results api tokn” and “CMT suite fails at loggin step” found nothing, and Cortex answered “cerify databse conection failed, what do i check” from unrelated rows in the workspace’s own logs.

src/knowledge/spelling.ts repairs misspelt pack words, only after the question as written found nothing. A question answered today takes exactly the path it took before; the matcher itself was not widened, because widening it is what once let “log” match “login”.

WhereWhen the repair is used
/knowledge/askWords and meaning both found nothing and no disabled add-on was named. The repaired question goes through the same steps again; the answer carries spellingRepaired.
Cortex routingThe turn is not a product question as written, and the repair adds a product name it lacked.
Cortex knowledge blockThe question as written retrieved no entry.
Disabled add-on noteThe question as written named no disabled add-on.

A word is repaired only when all of these hold:

  • it is at least 4 letters, letters only, and not part of a path, number, address or code (C:\Wroksoft\…, cerify-2905, [email protected] are left alone);
  • it is not a real word: not in the bundled SCOWL word list (levels 10–50, 62,697 words, src/knowledge/spelling/englishWords.json, licence in SCOWL-COPYRIGHT.txt) and not used anywhere in a pack. Without the list, “suit” became “suite”, “port” “part” and “oven” “open”;
  • it is exactly one edit (a letter wrong, missing, extra, or two neighbours swapped) from a word of a pack noun or topic heading, starting with the same letter (or the first two swapped);
  • the closest word is unique. A tie is broken by how often each word appears in the packs, and left alone when still tied.

Abbreviations are too short to repair by distance, so a pack may list reviewed misspellings; Worksoft has cmt → ctm. More than three repairs in one question means it is not text the packs know, and nothing is repaired. KNOWLEDGE_SPELLING_REPAIR=off on ai-service turns the repair off (unset means on).

Not covered: a short statement that fails even when spelt correctly (“certify database connection failed”, “recordset vs layout certify”) — the two-term relevance floor, not spelling.

Measured on dev (ai-service c574b12, workspace 2905, 2026-10-16). On the deterministic word path, the repair changed the answer to 8 of 94 test questions — all eight misspelt — and none of the other 86 (HIPAA/SOC 2, platform and off-topic questions). Seven now reach the right Worksoft topic (“wroksoft portal logs”, “CMT suite fails at loggin step”, “proces inteligence exporter unauthorised 401”, “certfy results api tokn”, “user not foudn in certfy”, “busines captur privacy risk”, “worksft impact sap”); “hipa compliant worksoft” gets the same Logrite topic as the correctly spelt question. Live, all 22 misspelt questions were answered (12 before). In Cortex, “cerify databse conection failed, what do i check” is now answered from the Certify database topic with the Worksoft attribution, instead of from unrelated rows in the workspace’s logs.

Compliance questions, vendor answers and docs drift (2026-10-16)

Section titled “Compliance questions, vendor answers and docs drift (2026-10-16)”

Measured on dev before these changes: Cortex told users “Worksoft publishes its own SOC 2 report to customers under NDA” and “Certify does maintain check-in/check-out version history”, and /ask answered an audit-trail question with find-and-replace. Five changes, each checked against an answer snapshot of 693 questions (the test suite, every topic heading, every knowledge and intent test question) so that only the cases it targets moved.

A vendor question that is not a how-to now gets the pack or a rule (ai-service 114f4ea). Cortex uses a pack only for product questions, which need a how-to wording. “Is Worksoft HIPAA compliant?”, “Does Worksoft keep an audit trail…?”, “Which SOC 2 controls does Worksoft help me meet?” and “…kahan milenge” are not, so 9 of 11 such questions reached the model with no knowledge and no rule against guessing. chatEngine/vendorKnowledge.ts now gives a turn that is phrased as a question and names an enabled add-on’s product either that pack’s entries (the strict /ask lookup) or, when there are none, a rule: do not state the vendor’s features, certifications, BAA availability or compliance posture from general knowledge; say the pack does not cover it; general guidance about the regulation itself is allowed, labelled as such. Routing and tools are unchanged; product questions keep their block; data questions (“how many…”, “show me my…”, a named index) get nothing.

/ask no longer answers a compliance question with an unrelated topic (ada9974).

WasCauseNow
“Does Worksoft encrypt test data at rest?” → Logrite’s “Is my data isolated per workspace?”“worksoft” and “workspace” share the 5-letter stem “works…”Add-on pack names are removed from the question before a Logrite topic is judged
“audit trail…” → find-and-replace; “…see PHI…” → the Exporter 401 fix; “…retained?” → Failure SummaryEveryday words (“changed”, “results”, “test”) were the only evidenceA topic must mention the question’s compliance subject — audit, PHI/PII, retain/retention, encrypt, BAA — or the pack’s synonym for it. Framework names (HIPAA, SOC 2) are context, not subject. Applies to meaning results too
“certify database connection failed”, “recordset vs layout certify” → nothing; “What does Root Cause Analysis do in Certify?” → the platform overviewNothing was left once product names were removedOnly when every other rule found nothing: two specific product names in a heading, or one plus a distinctive shared word, identify the topic

New section: Security, audit and access (ec5f6c1). Nine topics, each from a cited page: Certify change history (Tools > Change History, CSV export), one process’s history, process versions (create, compare, restore), user login history, access levels, folder permissions, the Reporting Services audit trail, Portal change history, and Mainframe LT (IBM Personal Communications, IBM Aviva, QWS3270 Secure, Rocket BlueZone). Synonyms: audit → history, PHI/PII/patient → privacy, retain/retention → archive, LDAP → directory. A synonym is matched on a 5-letter stem, so forms that share one with unrelated words were refused (“confidential” matched “configure”, “recordset” matched “result of record”). Only the 9 new headings were embedded; the other 130 vectors are unchanged.

The meaning fallback says when it could not run (f8aa22e). OpenSearch’s ML plugin refuses embeddings while the JVM heap is above plugins.ml_commons.jvm_heap_memory_threshold (85%); dev’s heap peaked at 94% before each collection. The semantic API passes that on as 503, and a refused call read as “no match” — the same question was answered by meaning in one run and not the next. A 429/503 is now retried once after 300 ms inside the 4 s deadline, logged as [meaning] embedding unavailable: …, and /ask answers meaningUnavailable: true when nothing was found. Tests pin SEMANTIC_API_URL to a closed port (tests/offline.ts); before, they called the real dev semantic API with fake keys.

Docs drift is checked weekly and fails (1c81a40). .github/workflows/knowledge-drift.yml (Mondays 03:15 UTC, and on demand) runs npm run check:knowledge:worksoft:fresh: every cited page fetched fresh, and the run fails when a page’s text changed, it now redirects elsewhere, or it came back with fewer than 200 characters — naming the topics that cite it. Regenerating prints the same report before it overwrites the fingerprints. checks.yml now runs check:knowledge:vectors on every push. On a red run: re-read the named topics against the page, fix worksoft-topics.js if the procedure changed, then npm run gen:knowledge:worksoft -- --refresh.

Measured live on dev (ai-service f8aa22e, workspace 2905, 2026-10-16), same 97 + 16 questions:

Before (morning)After the typo fixNow
/ask lookup (97)73 pass · 7 partial · 17 fail79 · 8 · 1084 · 8 · 5
Cortex chat (16, graded by hand)7 · 3 · 68 · 3 · 514 · 2 · 0

No remaining failure is a wrong answer: two were the meaning step refused (and the reply says so), three are honest “no entry” (retention period, a spreadsheet-driven test, Certify on Linux). Not changed here: the OpenSearch heap itself, a Discord alert for the drift job (the webhook lives in a root-only file on the runner), and re-mining the log-signature catalogue.

Vendor- and product-named questions, Hinglish (2026-10-19)

Section titled “Vendor- and product-named questions, Hinglish (2026-10-19)”

A re-test with 37 new questions (six to seven per fixed issue) found two wrong answers and a Hinglish miss. Fixed in ai-service 2eac79d (src/knowledge/askFilters.ts):

  • A question naming an enabled vendor is not answered by a Logrite topic unless it also names Logrite. “Is Worksoft data isolated per workspace?” uses Logrite’s own words and got “Is my data isolated per workspace?”.
  • A question naming one vendor product is not answered by a topic whose title names another. The products are listed on the pack (KnowledgePack.products: Certify, Worksoft Impact, Portal, Business Capture, Process Intelligence, Automation Insights, CTM, Reporting Services, Scheduler…). “Does Worksoft Impact keep an audit log of SAP transports?” got the Reporting Services audit trail and Certify process versions; it now gets no entry. A topic that names no product still answers.
  • A single-word product name in a heading is matched only by a question word that begins with all of it (“certifyresultsviewer”), never on the shared five-letter stem (“workspace” ≈ “worksoft”) or by a shorter word (“work”).
  • Hindi/Hinglish function words (ke, ka, kahan, hain, kya, mein…) are not relevance terms, so “worksoft scheduler ke logs kahan hain” gets the same answer as its English twin — the service-log topic, found because its text lists the Scheduler’s folder (used only when nothing else matched).

Answer snapshot of 732 questions: 16 changed, all of them these cases or a stray other-product or Logrite citation removed. Live re-test on dev: 30 pass · 3 partial · 4 fail of 37 (was 27 · 3 · 7); issue-by-issue evidence is on the Worksoft pack review page.

The last four misses (ai-service 0c46d10). Each measured against the committed heading vectors through the dev semantic API before it shipped:

QuestionWasFixNow
“the exporter can’t sign in”meaning 0.383synonyms exporter → results exporter, sign → unauthorized0.656, Exporter Unauthorized
“how big should the SQL box be”meaning 0.494synonym sql → database0.586, database server sizing
“my tests stopped finding the login button after the UI changed”meaning 0.297new topic in the users’ words: “Why do my Certify tests stop finding a button or field after the UI changes?” (from the logical-naming page)0.706
“Which terminal emulators does Certify support for mainframe testing?”one shared wordsynonym emulator(s) → mainframeanswered by the word check

Synonyms that lift a vendor topic also lift it for other vendors’ questions: “my otel exporter can’t sign in” scored 0.598 against the Exporter topic. lowerCaseProductNames (meaning.ts) treats a lower-case word of 4+ letters that is neither English (the SCOWL list) nor used by an add-on pack — and is not a typo or inflection of one, nor Hinglish — as another product’s name, and keeps add-on topics out of that meaning answer; Logrite answers are untouched. Two candidates were tried and dropped: “terminal → mainframe” moved a Logrite collector question, and a heading worded “…after the application UI changes” answered an Epic/HIPAA question on “test” + “application”. Checked live on all 88 questions the change touches; only the targets moved. Re-test: 34 pass · 3 partial · 0 fail of 37. Known gap: “postgres” is one letter from the English “postures”, so it reads as a typo rather than a product name.

  • Sandbox → Playground: the add-on card sits in the Knowledge operation panel — disabled state names the add-on, enabled state offers prompts that land in the chat composer.
  • Settings → Cortex add-ons: the toggle. Any member sees the list; Admin or Owner flips it.
  • Sandbox identity bar: an Add-ons: row, none when there are none.
  • Cortex chat header: a chip naming the active packs, so a reader can see why an answer is vendor-aware.
  • MCP: logrite://knowledge/<pack> as a resource (the topic index from /packs/:key), knowledge_search as a tool, and workspace_addons to list or toggle add-ons. A workspace without the add-on gets ADDON_NOT_ENABLED.

The prod worksoft-demo workspace ([email protected]) has worksoft-cortex enabled and is filled by a demo seeder instance running the worksoft persona: eight Certify service agents whose log lines are generated from the signature catalogue, so findings and Cortex answers cite real signatures without copying a line of the Worksoft corpus. One annotated signature (the GetLogHeaderDetails InternalServerError variant) is never returned by matchWorksoftSignature: a longer unannotated sibling with the same 60-character match key always wins.

Before ai-service d7491fb (prod 2cbcb65b81cb), five of the demo’s six questions answered matched:false on ws 302. Three defects and three content gaps:

  • Signature first-sentence fallback (packs/worksoft.ts). matchWorksoftSignature needed the first 60 characters of the template’s leading literal, which for .NET runs straight into the exception type (:The supplied credential is invalid. System.DirectoryServices…), so the bare message as people type it never matched. An annotated signature now also matches on the message’s first sentence (leading punctuation removed, cut at the first full stop, ≤60 chars), only for heads of 4+ words that no other signature shares. The 60-character prefix is still tried first; a shared head such as Failed to get step info data matches neither.
  • Signature match before the domain gate (retrieve.ts). matchTopics ran only after the vendor-noun gate, and The supplied credential is invalid names no Worksoft noun. It now runs first; a pack is still only searched when its add-on is enabled.
  • One term plus noun (ask.ts isRelevant). Two non-noun terms were required, and “Where are the Worksoft Portal logs?” has one (logs). A question that names the pack now passes with one term when the topic’s section or question contains the most specific pack noun named. A question naming no pack keeps the two-term floor.
  • The user’s words (ai-service 88ab3fd, 2026-10-14). The pack had topics for Exporter authentication, its PI export setup and retrying a failed scheduled run, and /ask answered all three “no entry”: the questions said “authenticate”/“401”, “PI” and “rerun” where the headings say Unauthorized, Process Intelligence and retry. KnowledgePack.synonyms maps those words (read by the relevance check only — Cortex scoring is unchanged); a multi-word pack noun the question and the heading share (“Certify Results Exporter”) counts as the second piece of evidence, a bare brand noun never does; and 12 candidates are judged for relevance so the right topic is not cut on noun weight before it is looked at.
  • New topics for the Certify database connection, Portal log location, User not found in Certify, the Exporter’s 401 to Process Intelligence, and CTM login-step failures.
QuestionFirst cited page
Unable to connect to the Certify databaseWorksoft_Certify/Administration_Tasks/Configuring_Certify_Databases_and_Licensing.htm
The supplied credential is invalidConnectiveAutomationPlatform/Worksoft_Product_Data_Locations.htm (AuthenticationService LDAP signature diagnosis)
Where are the Worksoft Portal logs?ConnectiveAutomationPlatform/Worksoft_Product_Data_Locations.htm
Error during GetProjects: User not found in CertifyConnectiveAutomationPlatform/Worksoft_Product_Data_Locations.htm (Bookmark signature); “What does ‘User not found in Certify’ mean?” cites Worksoft_Certify/Administration_Tasks/Importing_and_Updating_Certify_Users_From_Worksoft_Portal.htm
Results Exporter Unauthorized exporting to Process IntelligenceProcessIntelligence/HowTo/Signing_In_To_Certify_Results_Exporter.htm
CTM suite fails at the login step on agent machinesWorksoftCTM/HowTo/Creating_Desktop_Credentials_in_CTM.htm

All under https://docs.worksoft.com/. tests/unit/knowledgeWorksoftDemo.test.ts runs the six through the real route. Regenerate with npm run gen:knowledge:worksoft; check staleness with npm run check:knowledge:worksoft.

An entry in AddonCatalog, a pack in logrite-ai-service/src/knowledge/packs/, and nothing else. The card, the Settings toggle, the MCP resource and the REST routes all render from the catalogue.