System logic

Copilot — display spec, behaviour and knowledge base

Copilot — display spec, behaviour and knowledge base

One copilot component for every portal. Its look, positions and controls are identical everywhere; only the instructions, greeting, notices and knowledge base differ, and those are edited from Admin → Copilot & Knowledge Base, never in code. Last updated 2026-09-02.

1. Where it appears

PortalMounted byKnowledge baseTalks to
School (admins, teachers, staff)PortalShellSCHOOL + GLOBALhow the school portal works; never the school's own records
Startup / vendorPortalShellSTARTUP + GLOBALleads, pilots, integration
Platform adminPortalShellADMIN + GLOBALoperations, audit, KB upkeep
ParentPortalShellPARENT + GLOBALwhat the portal shows, how to ask the school

The onboarding wizard keeps its own embedded step copilot (it is a single flow with a fixed script); the pupil launcher has none (children's surface).

2. Display spec (components/copilot/copilot.tsx)

ModeAppearanceHow you get there
closeda launcher pill at the bottom-right edge; an amber dot when the page is a function pageClose, or Esc from panel/docked
panelslides out from the right over the page, 420 px wide, full height, shadowclick the pill; Undock
dockedsits beside the page at 420 px and pushes the content (the main column reserves --copilot-dock)Dock
maxfills the viewport; conversation centred at 3xl widthMaximise

Toolbar, left to right: Dock / Undock, Maximise / Revert, Close. *Revert* returns to whichever mode the copilot was in before it was maximised. Esc reverts from max, otherwise closes. The chosen mode is remembered per portal in localStorage (eduspaze.copilot.<portal>).

Panel anatomy: header (avatar, display name, current module, state), function-page notice bar (amber, when applicable), greeting bubble, suggested prompts (before the first question), conversation, input row. Assistant answers list the knowledge-base articles they drew on; when no LLM key is configured they say so in small print.

Accessibility: role="complementary", labelled toolbar buttons with aria-pressed, an aria-live region that announces entering and leaving a function page, input disabled with an explanatory placeholder when blocked.

3. Function pages

A function page is any page where the user can create, edit or delete model data (forms and actions). On such pages the copilot:

  1. announces, once, that it is not enabled for the module (functionPageNotice, with {module} replaced by the menu name), both in the conversation and via aria-live;
  2. disables the input and shows the notice bar;
  3. announces it is back when the user leaves the page.

The classification lives in one registry, lib/copilot/registry.ts (MODULES), so the server enforces the same rule: the chat API refuses questions from function pages and logs the refusal. Unknown pages under a portal are treated as function pages (fail closed).

PortalFunction pagesInformation pages
SchoolStaff & Access, Students, Classes & Groups, School Settings, Needs Survey, Challenge Statements, Parent Questions, a pipeline conversation, Bundles & Credits, Audit Log, Matchmaking Trips, a marketplace listingDashboard, Recommendations, Marketplace, My Pipeline, Benchmarking, Engagement, Platform discovery
StartupProfile & Pilot Offer, Integration & API, a lead conversation, Challenge Statements, Matchmaking TripsDashboard, Lead Inbox, Market Insights
AdminVetting, Schools, Bundles, Credits, Trips, Grants, Challenges, Settings, Audit, Copilot & KBDashboard, CRM, Reports
ParentApp detail & questionsYour children, Apps, Timeline, Activity

4. Answering (lib/copilot/rag.ts)

Retrieval-augmented generation over the portal's knowledge base:

  1. Retrieve: Postgres full-text search (ts_rank over title, summary, tags, body) across *published* articles for the portal plus GLOBAL, top 4; keyword fallback on title/tags.
  2. Generate: the admin-selected LLM (Admin → Settings) with the portal's instructions plus platform guardrails: answer only from the excerpts, say when they do not cover the question, never reveal or guess other tenants' data, under 150 words, cite excerpt numbers, never claim to have performed an action.
  3. Fallback (no key or provider error): the best article's summary and related titles, so the copilot is useful with zero keys (NFR-1).
  4. Log: every exchange is stored (CopilotExchange: portal, route, user, tenant, question, answer, source, articles used). Questions are free text, so the row carries the PII flag columns and is captured by the audit harness like any other write.

The copilot never queries business tables. It knows how the platform works, not what is in it; that keeps the parent-module and tenant-isolation guarantees intact by construction.

5. Knowledge base (database, not code)

ModelPurpose
CopilotConfig (per portal)enabled, display name, greeting ({name}), instructions, function-page notice ({module}), suggested prompts
KnowledgeArticleportal (or GLOBAL), slug, title, summary, markdown body, tags, status (draft / published / archived), version
CopilotExchangequestion/answer log for gap review

Admin → Copilot & Knowledge Base shows, per portal: the settings form, the article list with status and version, 30-day counts by answer source, and recent questions with a badge when none matched an article. Articles render with the same markdown renderer as /docs.

Seed content: prisma/seed-data/knowledge.ts (starting set only; edits live in the database and are audited like every other change).

6. Adding the copilot to a new portal

  1. Add the portal to CopilotPortal, PORTAL_PREFIX, MODULES and ROLE_PORTAL.
  2. Pass portal="…" to PortalShell.
  3. Seed a CopilotConfig and a few articles; the admin page picks the portal up automatically.

7. Open items

  • Streaming responses and message history persistence across page loads.
  • Per-tenant article overrides (a school's own how-tos) — the schema allows a tenantId later; the retrieval query would union them.
  • Feedback buttons on answers feeding the gap review.

Source: docs/copilot.md in the repository. Last updated with the code it describes.

Copilot — EduSpaze