Building the Context Layer: From One Worker's Store to the Whole Workforce's Corpus — A Crash Course
15 Concepts · Onyx, MCP, and four source classes · Built by your agent, not by hand
AI Searchable Context built one Worker a store of its own. This course builds the corpus the whole workforce reads from.

In AI Searchable Context you gave one Worker a store of its own: your documents, chunked, embedded, searchable by meaning, sitting in one Neon Postgres you control. You even wrapped it as an MCP tool so other agents could call it.
But it was still one bounded store, with one boundary you drew yourself. You chose every document in it. You decided who could reach it. Nothing arrived that you had not put there.
Now walk into a customer's building.
Their twenty years of working papers are in SharePoint. The engagement letters are in email. The reason a decision was made lives in a chat thread and in the head of a manager who is travelling. The current balances sit in a system that changes every hour. None of it is your store. All of it is required to finish the work.
This course builds the layer that reaches into all of it, and it builds it around one question a real company would actually ask.
Northstar Services wants a twenty percent discount, wants to be invoiced now, and wants the implementation revenue recognised this quarter. Can they?
That is one sentence from one customer, and it is not one question. It is a sales question, an accounting question, a live-state question, and a piece of hearsay in an email, and answering it correctly requires all four to stay apart. By the end of this course a Worker will answer it properly. With citations. With the current facts fetched live. With the email marked as evidence rather than authority. And with the two professional decisions kept apart, instead of blended into one cheerful yes.
Three words first, in case they are new. A connector is the piece that reads one source system and keeps a copy of its content current. Indexing is storing that copy so it can be searched. And permission inheritance means carrying each document's access rules from its home system into every search result, so a reader only ever sees what they could already open.
One idea makes this whole course click. The last course had one question: is the right chunk in the context window? This course has three, and every concept serves them. For everything the layer returns:
Where did it come from? May this person see it? Does it still govern?
A search box answers none of those. A context layer answers all three, on every item, every time. That is the entire difference, and it is why this is a course and not a config file.
| Word | Plain meaning |
|---|---|
| System of Record | The system that officially holds a thing. If a copy disagrees with it, the copy is wrong |
| Vertical | One profession or industry, such as accounting, law, or sales engineering. The opposite of general-purpose |
| Authority class | What kind of statement this is, and therefore how much weight it carries: law, standard, contract, policy, transaction, guidance, message, or example |
| Working context | The day-to-day material of a company: email, chat, drafts, files. Real, useful, and never the rule |
| Connector | The piece that reads one source system and keeps a copy of its content current |
| Sync | One run of a connector, fetching what changed since last time |
| Index | The searchable copy the layer keeps, so it can find things fast |
| Corpus | All the content the layer can search, across every connected source |
| Fixture | A fake but realistic file you make for practice, so no real data is at risk |
| Document Set | A named group of connectors, used to say which sources a search may look at |
| Onyx Agent | A configured assistant inside Onyx, with instructions, knowledge, and tools |
| Action | A tool an Onyx Agent may call, such as your own search or a live lookup |
| Canonical | The original, official copy, as opposed to any copy made of it |
| Projection | A searchable copy of governed content, kept only so the Worker can find the original |
| Stable ID | A permanent name for one rule, so a copy can point back at its original |
| Superseded | Replaced by a newer version, and no longer the rule that applies |
| Gateway | Your own code sitting in front of Onyx, deciding what this person may search |
| Packet | The bundle of rules, facts, and evidence assembled for one question |
| Envelope | The labels attached to one item: where it came from, its version, why you may see it |
| Provenance | The full story of where a piece of information came from |
Every other new word is explained where it first appears.
This course assumes AI Searchable Context. You should have a working RAG on Neon with pgvector. You should know what chunking and an embedding worker are. And you should be comfortable judging retrieval quality with an eval set. Keep that Neon project. You reuse its infrastructure and its retrieval skills here. But be clear about what it did and did not build, because the difference is this course's subject.
That course built one bounded retrieval store: documents, chunks, embeddings, a search function, an answer function, and an eval set. It taught you how documents become searchable knowledge. What it did not do is give that store professional authority. There are no authority classes in it, no jurisdictions, no effective periods, no supersession links. So in Concept 10 you add a small governed schema beside what is already there, and Concept 10 is what reaches it. It also assumes Agentic Coding for driving Claude Code or OpenCode in plan mode, and Skills & Connectors for MCP.
The concept page behind this build is The System of Context. Read it first if you want the argument. This course is the factory floor, and Northstar is the same worked example that page decomposes.
Here is the whole system on one page, the map you will grow into as each concept lands:

What this course covers
| Part | Topic | What you learn |
|---|---|---|
| 1 | Foundations | The scope jump, four source classes, Onyx Standard, one model, and a search baseline |
| 2 | Your first corpus | The book as shared method, the Northstar fixtures, Document Sets, the chunker, and the permission gate |
| 3 | The governed half | Your Neon record over MCP, discovery versus confirmation, and live state |
| 4 | Routing and citing | The authority map written before the prompt, the seven-section packet, and conflicts that must not blend |
| 5 | The Northstar case | The whole build end to end, then four ways of breaking it on purpose |
| 6 | Prove it | Eight eval dimensions, and why the model that answered must not grade itself |
| 7 | Serve and operate it | One gateway for every external Worker, then connector health, upgrades, and the definition of done |
A running Onyx Standard deployment with four classes of source connected and kept apart. The Agent Factory book itself indexed as the shared method. Two Northstar Vertical records, sales and accounting, that disagree in a useful way. A live MCP server for current customer state. Your own Neon record, served over MCP and never crawled. A versioned authority-map.yaml, which is the file that says which record governs which question. A Context Router returning the same seven sections every time, with citations. A permission gate you wrote, tested with a role whose correct answer is nothing. An eval set scored on eight dimensions. And a Context Gateway MCP endpoint that lets authorized external Workers query the shared corpus through the same identity and permission boundary.
How to read this. Parts 1 and 2 plus the Northstar build in Part 5 are the complete system, about a two-hour read plus a few hours at the keyboard. Parts 3 and 4 are what makes it trustworthy rather than merely working, and neither is optional: Part 5 runs every one for real. Want to build first and read the why after? Start at Part 5.
📚 Teaching Aid
A slideshow for this course is in preparation.
Set up your environment (once)
Everything you build sits in one folder, and it comes pre-wired.
Download context-layer-base.zip
Unzip it. Inside is the whole Northstar case ready to connect, the governance files ready to fill, and three MCP server skeletons with the hard parts marked as TODO:
fixtures/ two governed records, live state, working context
plus PLANTED.md, the answer key for Part 5
governance/ authority map, model register, permission matrix,
production gates, boundary contract
mcp/ vertical_sor, customer_state, context_gateway
prompts/ the Context Router instruction file
evals/ ten cases, scored on eight dimensions
scripts/ the governed schema for your existing Neon project
AGENTS.md the standing rules your agent reads every session
.env.example every credential this course needs, and nowhere else to put them
cd context-layer-base
cp .env.example .env
This course handles more credentials than the last one, and each is a way to lose a customer's trust in a single commit.
| Secret | What it opens |
|---|---|
| Neon pooled connection string | your governed record |
| Model provider API key | your model spend |
| Onyx admin login | the whole corpus |
| Onyx API key | search, as whatever that key can see |
| Onyx MCP token | optional, only for the native-endpoint comparison in Part 7 |
| Context Gateway tokens | one per role, mapped server-side. These are the permission boundary |
Every one of these lives in .env, which .gitignore already excludes, except the Onyx admin login, which belongs in your password manager. None of them belongs in a file you commit, in a prompt you paste, or in terminal output you screenshot for a classmate.
Tell your agent explicitly: read credentials from the environment, never write them into a file we commit, and never print them. Then check the diff before you approve it.
What this costs, before you start. Nothing, if you already did the last course.
| Thing | Cost |
|---|---|
| Onyx Community Edition | free, MIT core |
| Neon | free tier, no credit card |
| Model provider | a free tier is enough for this course |
What this takes. Parts 1 and 2 are about two hours of reading and two or three at the keyboard. The install in Concept 4 is twenty minutes of waiting, mostly for image pulls. The Northstar build in Part 5 is a long day, and more if it is your first MCP server. Do not attempt all of it in one sitting. A good split is Onyx and the connectors first, the governed record and its two MCP servers second, then the gateway and the Router. Each of those is a lesson on its own, and stacking three of them into one evening is how people conclude they are bad at this.
You need three things on the machine besides the folder. Docker, because Onyx runs as a set of containers. uv, for the Python side. And your agent. Open it inside the folder:
cd context-layer-base
claude
cd context-layer-base
opencode
One warning before you start, because it decides where you run this.
Onyx is real infrastructure. A Standard deployment brings up about a dozen containers at once: a web frontend, an API backend, an nginx proxy, Postgres, the search index, Redis, object storage, two model servers (one for indexing and one for inference), a code interpreter, and background sync workers.
That wants several gigabytes of RAM. It is not comfortable on a modest laptop with everything else you have open. So there are three ways to handle it, in order of preference for a class:
| How | Best for | Cost |
|---|---|---|
| One shared lab instance your institution runs | A whole cohort, connecting to one Onyx everyone can reach | One machine, once |
| Local minimal deployment, one connector only | The week where you need to see the internals and read the code | Your own RAM |
| Onyx Cloud trial | A single cohort week, or a laptop that cannot run it | A 14-day trial, no card |
Do the internals week locally even if you use the lab instance for everything else. Reading a connector's code while a sync runs is a lesson no hosted service can give you.
Part 1: Foundations
Before you install anything, four ideas.
Your last store was small and safe, because you controlled everything in it. A company's sources are not like that. They come in four kinds, and mixing them up is the most expensive mistake in this build. Onyx is the tool you will use, and it is good at finding things and bad at deciding what is true. And Onyx has two install modes, one of which quietly turns off the parts this course is about.
1. The scope jump: one store to everyone's sources
Hold the Northstar question in your head while you read this, because it is a question your last build could not have touched.
Can Northstar have the twenty percent discount, be invoiced now, and recognise the revenue this quarter?
Nothing in your Postgres store knows what a Northstar is. It does not know who approved what, or when acceptance arrived, or what a sales manager said in an email last Tuesday. That is not a gap in your build. It is a different kind of system.
Your store had four properties you probably never noticed, because you never had to think about them.
You wrote everything in it. Every document came from your docs/ folder. Nothing arrived that you had not put there. It had one reader. Whatever your app allowed, the store allowed. It had one kind of truth. Everything in it was a document you had written, and every one carried the same weight. Nothing in it was a live balance, a signed obligation, or somebody's opinion in an email, and nothing in it had been quietly replaced by a newer version you never saw. And it was current by construction, because your worker was the only thing writing.
Every one of those goes away at once when you connect a company.
Now the content is theirs, some of it wrong and some of it superseded. Now a first-year junior and a partner ask the same question and must get different answers. Now the corpus holds a signed contract, a policy memo, a chat message, and a live invoice status, and those carry wildly different weight. And now a document you indexed on Tuesday may have been replaced on Wednesday by someone who will never tell you.
Northstar makes all four concrete. The contract and the CRM are theirs. An account executive and a VP must get different answers about the discount. A signed contract, a policy memo, an email, and a live approval status carry wildly different weight. And the approval status may change while the Worker is composing its answer.
That is the scope jump, and it is why the build has a different shape.

The last course was a retrieval problem. This one is a governance problem wearing a retrieval problem's clothes.
Your job in it is the same as ever: you direct the agent, and you judge what it produced. But what you are judging changes. You are no longer mostly asking did it find the right chunk. You are asking does every returned item say where it came from, is this reader allowed to have it, and did anything confirm it still holds.
2. Four source classes, and why they arrive differently
The single most expensive mistake in this build is treating every connected system as one undifferentiated pile. Sort them into four classes before you connect anything, because the class decides how the content is fetched and what a Worker may do with it.
| Class | Examples | How it arrives | May a Worker cite it? |
|---|---|---|---|
| Agent Factory System of Record | The shared method and standards | Web-indexed for discovery, cited to the canonical page | Yes, as shared method |
| Vertical Systems of Record | Northstar's sales and accounting rules, in your Neon record | Indexed for discovery, then confirmed over MCP | Yes, as the governing rule |
| Customer operational records | ERP, CRM, ledger, contract system | Live typed query, never indexed | Yes, for its own state, with a timestamp |
| Customer working context | Email, chat, files, project trackers | Permission-aware indexing | As evidence of what was said or done, never as the rule |
Two things to hold from that table.
The first three are all authoritative, over different questions. A common vendor line says a traditional record "only stores data" while the context layer interprets it. Do not repeat that in front of a finance director. Their ERP enforces transactional integrity, approval limits, and an audit trail, and those controls are why the business is allowed to operate. The gap is one of scope, not seriousness: it is complete about its own domain and silent about the profession around it.
Only the fourth class lacks governing professional authority. Note the precision. Email and chat are often governed in other ways, by access controls, retention rules, privacy policy, legal holds, and records-management requirements. What they lack is the authority to settle a professional question.
It is also the class everybody points a search tool at first, which is why so many pilots produce fluent answers with nothing behind them.
Glean ships native connectors for the fourth class and many of the third, plus an Indexing API for anything it does not cover. You define a custom datasource, push documents with their content, metadata, and permissions, then activate it in the admin console.
What Glean does not do is decide your four classes for you. It does tag each datasource with a category, KNOWLEDGE_HUB, EMAIL, MESSAGING, CRM, TICKETS and a dozen more, but those categories tune ranking and how a result is rendered on the page. None of them says whether a source may be cited as the governing rule. The class of each source, and therefore what a Worker may cite it as, is still your design decision. Onyx makes you feel that because you build the separation by hand. Glean lets you skip it, which is exactly why so many Glean deployments end up with a flat pile too.

The full argument for the four classes, and for why the first three are authoritative over different questions, is in Authority is scoped across many records.
Whichever profession you are working in, write this table out for your actual sources before the first connector runs. It becomes the routing map in Concept 12.
3. What Onyx is, and what it is not
Onyx calls itself the open-source AI chat connected to your docs, apps, and people. This course treats it as the open reference implementation of a System of Context, and that framing is ours rather than theirs. It connects to many sources, keeps synchronised copies, searches them by meaning and by keyword, returns cited answers, and exposes agents and actions. The core is MIT-licensed and genuinely self-hostable. That is the whole reason this course uses it. You can read the connector code, watch a sync run, and see where the permission check fires. It also runs in real companies at real scale, so what you learn here is recognisable in an interview.
Three things it is not, and each maps to something you will build yourself.
It is not your System of Record. Onyx holds copies for finding. Your governed record holds originals for citing. That is the one law: the layer carries authority and never holds it. Get this backwards and your corpus can be current while a Worker quotes last year's rule from an index that never got the message.
It is not a permission system. It inherits permissions where its edition supports that, and enforces nothing of its own about your profession's controls. Part 2 is where this gets serious.
It is not the answer. A retrieval hit is a pointer. It says look here. Turning a pointer into an answer takes a second step, and Concept 10 is that call.
And one thing that is not Onyx at all, but will break your build faster than anything Onyx does:
Your Worker runs on a language model, and that model will answer a professional question from its own knowledge if retrieval gives it nothing. The output looks identical to a grounded answer. No error appears anywhere.
A model has no source. It has weights. There is no register row behind its answer: no publisher, no authority class, no jurisdiction, no version, no effective period, and no way to correct one statement inside it. Plausibility is not provenance.
So watch for three quiet leaks as you build:
- The gap fill. Retrieval returns nothing useful and the model answers anyway.
- The drifting paraphrase. It retrieves the right rule and restates it, losing a threshold or a condition on the way.
- Persistent memory. A model that carries facts between sessions has become an unversioned store nobody owns.
The cure is structural, not a prompt. Missing evidence is a field in the packet, and a Worker that cannot find its governing source escalates rather than proceeds. The full argument is in the concept page.
Done when: you can name, without looking, what each of the three answers. Which one is fixed by the confirmation call. Which one is fixed by the permission gate. And which one is why your Neon record stays outside the index.
Glean is the best-known commercial System of Context, and it is worth an hour of your attention even though you will not deploy it here.
Two reasons. First, Glean has popularised the phrase system of context in the current enterprise AI market, using it as the name for its own enterprise data layer. This book adopts the phrase on purpose, so a graduate walks into a buyer's office speaking words that buyer already uses. Whether Glean coined it is a separate question, and not one worth asserting. Second, it is where the market has priced this layer. A company may ask for "enterprise AI search", a "work assistant", an "AI knowledge layer", or an "enterprise context platform". They all mean this category, and the person across the table has almost certainly seen a Glean demo.
So read its product pages as a diagnostic rather than as doctrine. One question:
Which parts of the architecture in this course does the product actually implement, and which parts does it quietly leave to you?
Run that over its connector list, its permission model, its citation format, and its action surface. You will find the same four source classes, the same permission problem, and the same discovery-versus-confirmation gap you are about to build around.
One habit while you read. The category has been renamed repeatedly, and by different analysts at the same time: insight engines, cognitive search, enterprise AI search, generative AI knowledge management. Learn the layer, not the logo. The three questions from the opening outlive every product name in that list. They are how you will judge whatever is on the market when you graduate.
So from here on, most concepts end with a short In Glean note. It says how the same idea appears in the commercial product, and, more usefully, which parts Glean does for you and which parts stay your design work either way. You are not expected to have a Glean account. You are expected to walk into a meeting able to say what the two have in common and where they differ.
So why Onyx, and not Glean?
The honest version of this question has three answers, and only the first one is about the products.

First, you cannot learn a control by reading that a product has one. Glean's permission model is better than what you will build in Concept 9. It is also invisible. You configure it, it works, and you finish the week knowing that permissions happened without knowing what happens when they do not. Standing up the path once, badly, with a role that gets nothing back, teaches more than configuring a good one ten times.
Second, a closed box teaches no architecture. Every concept in this course is a thing you can go and look at in Onyx. You can read the connector code. You can watch the chunker throw twelve controls away. You can point search at a stale branch and see the wrong answer arrive with perfect citations. None of that is available through a product page.
Third, and this is the part students miss: most of this course is not about the product at all. Look at the gold column above. Seven of the things you build are decided by neither Onyx nor Glean, because they are professional judgements rather than platform features. Which class a source is. Which record governs a question. Whether a rule is still current. What to do when two sources disagree. A course built on Glean would teach exactly the same seven things, and you would just have less visibility into the three underneath them.
And when should a customer use Glean instead?
Often. Say so plainly, because pretending otherwise will cost you a client's trust in the first meeting.
If a company needs permission inheritance across a dozen SaaS systems next quarter, buying it beats building it, and it is not close. If they have no platform team, hosted beats self-hosted. If they have already bought Glean, your job is not a migration proposal. Your job is to connect their governed record to it and tell them which of the three questions their current setup actually answers. That is a better first conversation than a rebuild, and it is one only someone who understands the layer can have.
The rule for the whole course, then:
We teach the one you can open. You will deploy the one the customer already bought. The architecture is the same either way, and it is the only part that is yours.
4. Install Standard, not Lite
Onyx offers Lite and Standard deployment modes, and choosing wrong will cost you a day.
Lite is a small chat interface. It disables the vector index, the background connector workers, and the infrastructure this entire course exists to teach. Choose Standard.
The installer deploys with Docker Compose and asks which mode you want. The exact script changes, so have your agent read the current documentation rather than guessing:
Read the current official Onyx Quickstart and Resourcing pages. Check this machine's Docker CPU, RAM, and free disk against what they require. Install the latest stable Onyx Community Edition in Standard mode, bound to localhost for this course. Record the exact Onyx version, install method, ports, and persistent data location in
README.md. Do not choose Lite. Show me the plan and the resource check before starting any container.
Approve only when the plan says Standard and names the persistent data location. Then, after startup:
Inspect the running Onyx containers and logs. Report which services are healthy, which port serves the UI, and any repeated errors. Do not restart or recreate anything unless you first explain the cause and show me the exact command.
When Docker has too little memory, Onyx Standard's search and indexing services restart, stall, or fail health checks, and every symptom looks exactly like a configuration bug.
Do not spend an hour debugging config on a machine that gave Docker 4 GB.
For a local lab, the minimum useful Standard target is 4 virtual CPUs and 10 GB of RAM. Eight CPUs and 16 GB is comfortable. Confirm resources first, always.
Read the plan. The point of asking for the container list is not trivia. You should finish that plan able to name three containers. The vector index, which eats memory. The model server, which is slow on first start. And the background sync workers, which is where a silently failing connector hides. Those are the three that will surprise you later.
Watch for: first start pulls several gigabytes of images and the model server takes a few minutes to become ready. That is expected, not a hang. If the stack comes up but search returns nothing, it is nearly always that no connector has finished its first sync yet, not that anything is broken. And if a container restarts in a loop, check memory before you check configuration.
Done when: you can open the web interface, log in as the first admin user, and you know the single command that tears the whole thing down and reclaims the disk.
There is no install for you to do. Glean runs as a managed service, either on Glean's own infrastructure or as a single-tenant deployment inside your GCP or AWS account, and even in that second model Glean deploys and patches it rather than you. So this entire concept disappears, and with it the container list, the memory maths, and the disk monitoring in Part 7.
That is the trade, and it is worth naming out loud. You buy away the operations, and you buy away the ability to read the code. A student who has stood up Onyx once knows what a vector index costs and where a sync silently fails. A student who has only used a hosted product knows neither, and will believe a vendor who says it is simple.
One model, chosen on purpose
Onyx separates the context platform from the language model. Configure one capable provider in the Admin Panel and keep the visible list short: you are here to evaluate the context layer, not to compare ten chat models. Then have your agent write governance/model-register.md. It records the provider, the model, the date, the data-processing assumption, who can see it, and why you chose it. Plus one more field:
The replacement test. A stronger model improves tool use and answer composition. It cannot repair a missing connector, wrong authority routing, stale operational facts, or a broken permission boundary. Those are context-layer failures and no model upgrade touches them. Write that sentence into the register so future-you cannot forget it under pressure.
A search baseline before you tune anything
The last course taught you the machinery under retrieval so you could judge it. Onyx now packages that machinery. Do not immediately swap embedding models or enable every experimental option, because changing the embedding model forces a full re-index and is not a cosmetic toggle. Start on stable defaults and record governance/search-baseline.md: Onyx version, embedding model, reranking configuration, baseline date, eval set version, and the reason.
The rule from the last course carries over in its context-layer form: retrieval changes are evaluated, not admired. Onyx hides the SQL. It does not remove the need for evidence.
Run /init and trim it to four lines. Which Onyx instance you are pointed at. That all credentials live in the environment, never in the repo. That no real customer data is ever connected during this course. And one hard rule worth typing out in full:
Never connect a source I have not explicitly approved in this session.
A connector is a standing instruction to copy someone's data. It deserves the same review as destructive SQL.
Part 2: Your first corpus
Now you connect real content and watch what happens to it.
You start with this book, because it is public and needs no permission. Then you make a fake customer called Northstar and connect their files. You look closely at what the search index kept and what it silently threw away. And then you build the most important thing in the course: a check that decides what each person is allowed to find.
We will build a small synthetic company: two governed records, two operational snapshots, and a working-context folder of email and chat. Synthetic on purpose, and Concept 8 explains why that is not a shortcut.
5. Connect the shared method, then the customer
Start with the source that needs no permission at all. Onyx's Web connector crawls pages under a base URL, follows reachable links, cleans the text, and keeps source metadata for citation.
| Field | Value |
|---|---|
| Connector type | Web |
| Name | AF-SOR-PUBLIC |
| Base URL | https://agentfactory.panaversity.org/docs/getting-started |
| Source class | Agent Factory System of Record |
| Permission basis | Public |
Yes, you are indexing this book. That is the point. The Agent Factory System of Record is a real, public, governed source. It is the one class you can connect on day one without a single permission question.
One note that applies to every governed source. The index helps the Worker find the method. The citation must reopen the original page.
A Web-indexed chunk is a pointer to a stable web address. It is not a replacement for it. That is the same find-then-confirm shape you will build properly in Concept 10.
Now the customer. The Northstar fixtures ship in the base folder, so you connect them rather than generating them. Open fixtures/ and read what is there before you connect anything:
| Folder | What it holds |
|---|---|
sales-sor/ | Three governed sales rules, each with a stable ID, version, and effective date. The discount rule allows an account executive up to 15 percent |
accounting-sor/ | Four governed accounting rules, including one deliberately superseded file saying revenue is recognised at billing rather than acceptance |
operational/ | Two JSON records: approval pending, acceptance not received. These are never indexed |
working-context/ | Three emails and two chat threads, one of which claims finance has agreed to something no governed source supports |
fixtures/PLANTED.md lists all four planted inconsistencies. Do not index that file, and try not to read it closely until Part 5. It is the answer key.
If you would rather generate your own corpus, or want a second one to test against, this prompt produces an equivalent:
Create a
fixtures/folder for a synthetic customer called Northstar Services.Under
fixtures/sales-sor/, a small governed sales record: a discount-authority rule stating that discounts above fifteen percent require VP Sales approval, plus a qualification method and a proposal policy. Give every rule a stable ID, a version, and an effective date in front matter.Under
fixtures/accounting-sor/, a small governed accounting record: an implementation-revenue rule stating revenue is recognised at customer acceptance, plus two supporting entries, same front matter. Then add one superseded file saying revenue is recognised at billing, with an earlier effective date and a superseded-by link.Under
fixtures/operational/, two JSON records: an opportunity showing a twenty percent discount requested with approval pending, and a contract showing signature complete and acceptance not received.Under
fixtures/working-context/, three emails and two chat threads. One email from a sales manager should say "finance is fine with booking it this quarter", which no governed source supports.Finally write
fixtures/PLANTED.mdlisting every inconsistency you deliberately created, so I can check the system finds them later. Do not index that file.
Connect the folders as separate connectors, never one:
| Connector | Source class | Why separate |
|---|---|---|
VERTICAL-SALES-SOR | Vertical record | Governs discount authority |
VERTICAL-ACCOUNTING-SOR | Vertical record | Governs revenue recognition |
CUSTOMER-WORKING-CONTEXT | Working context | Evidence only, never authority |
You are about to index a customer's material. It stays theirs.
Northstar's emails, chat threads, and even their governed rules are customer content, in a customer instance. They never migrate into the shared vertical record you carry from client to client. That would be contamination: your profession's record would end up holding one company's private material, and you could no longer take it anywhere.
Material moves upward only through the promotion law: a pattern repeats across three or more customers, is de-identified, passes promotion review, and is rewritten by your expert in her own voice. That is authorship, not copying.
The rule to hold while you connect things: the customer's world flows in. Nothing flows out.
Note what is not in that table. The operational JSON is not connected at all. It is served live in Concept 11, and the reason is the whole of that concept.
Watch for: what a connector actually carries per document, beyond the text. A file connector on a local folder sees a path, a modified time, and nothing at all about who may read it. A connector into a real SharePoint or Drive sees far more, including the access rules. That asymmetry is the whole subject of Concept 8, and meeting it here, on a folder, is the cheapest possible way to meet it.
Also watch for: a sync that reports complete while search returns nothing, which usually means indexing is still running behind it, so wait and search again. A connector showing an error while search still works has left its old content in place, which is the trap in Part 7. And a permission change takes a moment to propagate, so a document may stay visible for a few seconds after you restrict it.
Document Sets: a search scope, not a legal ladder
A connector says where content came from. A Document Set is Onyx's word for a named group of connectors. You use it to say which sources a particular search or Agent is allowed to look at.
| Document Set | Includes | Purpose |
|---|---|---|
AF Shared Method | AF-SOR-PUBLIC | Architecture and doctrine |
Sales Authority | VERTICAL-SALES-SOR | Governed sales rules |
Accounting Authority | VERTICAL-ACCOUNTING-SOR | Governed accounting rules |
Customer Working Context | CUSTOMER-WORKING-CONTEXT | Supporting evidence |
Northstar Cross-Domain | all four | The complete lab corpus |
They do three things. They make scope visible. They let an Agent search only what its task needs. And they let you test inside one domain before testing across domains, which is how you tell a routing bug from a retrieval bug. One warning:
A Document Set is a search scope, not an authority hierarchy. It says what may be looked at. It says nothing about what governs.
The thing that says what governs is a different file, and it arrives in Concept 12.
Done when: you can run a search scoped to Sales Authority alone and get nothing back about revenue recognition. That is the scope working, and it is how you will tell a routing bug from a retrieval bug later.
6. Watch a sync, and see what the chunker threw away
You already know chunking from the last course, where the dials were size and overlap and the stake was recall. Here there is a second stake, and it is larger.
An entry in a governed record carries twelve things with it. A stable ID. A domain. An authority class. A jurisdiction. A version. An effective date. An approval status. Applicability conditions. An owner. A superseded-by link. A required checker. A permission boundary.
A generic indexing pipeline preserves the sentence.
Revenue may be recognised when control transfers.
The words survive. All twelve controls are gone, and nothing in the retrieved text announces their absence.
The Worker can no longer tell six things. Which standard governs the statement. Whether it applies to this contract type. Whether it is current. Whether it applies in this country. Whether it is authority or merely explanation. And which exceptions would change the answer.
See it on your own corpus:
Take one rule from
fixtures/accounting-sor/that has a version and an effective date in its front matter. Show me the raw document, then show me exactly what one of its chunks looks like in the index: the chunk text and every field stored beside it. Point out precisely which document-level facts did not survive into the chunk.
Done when: you can hold up one chunk and name something true about its parent document that a Worker reading only that chunk would never know. That gap is not a bug in Onyx. It is the reason the confirmation step in Concept 10 exists.
Glean's Indexing API lets you attach structured metadata to documents, and its knowledge graph carries relationships between people, content, and processes that a plain chunker throws away. So the gap is narrower here than in Onyx.
Narrower is not closed. Neither product knows that your rule has an effective date, a jurisdiction, and a superseded-by link unless you put those fields there and teach the Worker to check them. The twelve controls are yours to carry either way.
7. Search it, and notice what you got back
Search the corpus for a question whose answer spans two documents. Show me the results with their scores and sources, then answer the same question through Onyx's chat so I can see the citations it attaches.
Now the discipline. Ask three questions of every result, out loud, until it becomes reflex:
Where did it come from? Onyx is good at this, and the citation is right there. Check it points at a document you recognise.
May this person see it? Right now the honest answer is everyone sees everything, because you are the only user and it is a folder. Hold that thought for four minutes.
Does it still govern? Onyx cannot tell you. It found a document that matches your words. Whether that document is the current one is a question no similarity score can answer. Try it: search for the topic of the superseded accounting file that shipped in the fixtures you connected in Concept 5, and see which version comes back.
A retrieval hit is a pointer, not an answer. Everything in Parts 3 and 4 exists to turn pointers into answers you would defend.
Be exact about which items that applies to. Governed knowledge has an original to go back to, so a hit on it is a pointer. Working context does not: there is no canonical version of what a manager said on Tuesday, and the retrieved email is the item. What keeps working context honest is the other two questions, may this person see it, and is it being carried as evidence rather than as the rule.
Done when: you have searched for the topic of the superseded accounting file and seen which version came back first. Whichever it was, you now know Onyx did not decide it on the basis of currency.
8. Permission inheritance, and where Community Edition stops
This is the most important concept in the course, and the one most often skipped, because skipping it makes everything easier for about six weeks.
A document's access rules live in its home system. A private channel is private. A restricted folder is restricted. When your layer copies that document, it must copy the access rules with it, and re-check them at the moment of every query, for the specific person asking. Permission is inherited, never invented. Why that is a control question rather than only a privacy one is argued in Permission comes before the model.
Get this wrong and you have built something worse than a leak. You have built a system that is helpful about leaking. A junior asks a reasonable question and receives, ranked first, with a friendly summary, the compensation memo they were never allowed to open. Nobody attacked anything. The layer simply did its job against the wrong rules.
Onyx Community Edition is enough to learn connectors, indexing, retrieval, citations, agents, and actions. It is not enough on its own to demonstrate production permission fidelity across users.
Onyx's documentation lists permission-sync connectors, which inherit user permissions from external systems, together with user groups, RBAC, and group-based permissions, as features of Onyx Cloud and the Enterprise Edition, not of the self-hosted Community Edition. Deployments needing permission inheritance from external systems are named as a reason to move to Enterprise.
So in a pure Community Edition lab, every student sees the same corpus. You cannot stage the demo where a restricted role asks and correctly gets nothing back. (If your cohort runs the Onyx Cloud trial from the setup table instead, you can, and it is worth one week to watch a real access-control sync do by itself the work you are about to do by hand.)
This is the concept where the commercial product is plainly ahead, and it is worth saying so rather than being defensive about it.
Glean reads the access-control list from each connected system alongside the content, and enforces the permissions that already exist at the source. If you cannot open a file in Drive or read a channel in Slack, it does not appear in your results and does not reach an answer written for you. Its Indexing API exposes the same model for your own content, with per-user and per-group permissions on each document, and a checkdocumentaccess endpoint for verifying them.
So in Glean you configure this. In Onyx Community Edition you build it, which is Concept 9.
Building it once is the better education. Buying it is usually the better production decision. Knowing which of those two sentences applies to the situation in front of you is the actual skill.
Three ways to handle that, and the first is the one this course takes.
Enforce the permission check yourself, at your own boundary. You write that code, so you control it completely. Implementing an access check also teaches far more than configuring one. This is Concept 9.
Read the ee/ code. It is source-available even though it is not MIT. Study how ACL inheritance from a real source is actually implemented without deploying it.
Use a trial or a licence for one lab. One week, one demonstration, then back to Community Edition.
One rule follows from all of this, and it is not negotiable while you are learning.
Until your deployment has passed the permission test set in Concept 9, do not connect a real corpus. Not your employer's drive, not a client's, not your own inbox. A layer that has never been tested for permission is not a partial system, it is a fast one, pointed at the wrong rules.
9. Build the gate yourself, and test it with a role that gets nothing
Since Community Edition will not gate documents per user, you build the gate one layer up, in front of retrieval. This is the right place for it in production too: your own boundary is where you can prove what happened.
One honesty note before you write it. You are about to invent the permissions on these fixtures, which is the opposite of the rule you just learned. That is a property of the lab, not of the design. A local folder carries no access rules to inherit, so somebody has to state them, and in a real deployment that somebody is the source system. Your tagging here is a stand-in for an inheritance you cannot demonstrate on Community Edition, and governance/production-gates.md is where you write down that it is still owed.
The shape is simple, and the order is everything.
1. Resolve identity who is asking
2. Resolve permissions what may this identity see, per source
3. Filter eligible docs remove everything else, BEFORE retrieval
4. Retrieve and rank search only what remains
5. Assemble the answer with citations
6. Resolve action rights separately, at the tool boundary
The unsafe order is the one that feels natural. Retrieve everything. Hand it all to the model. Then instruct the model not to mention what the reader may not see.
A hidden passage inside the model context is not hidden.

Build it:
governance/permission-matrix.csv already ships with a row per source. It is the file this gate enforces, and the file you hand a reviewer afterwards.
Add an access layer in front of Onyx retrieval. Define three Northstar-side roles:
account_executive,sales_manager, andvp_sales. Tag each fixture with the minimum role that may read it. The discount-authority rule is readable by all three. The pricing-approval thread and the manager's "book it this quarter" email are readable bysales_managerand above only. Then write asearch(query, role)function. It filters the eligible document set by role before calling Onyx, never after. It returns each result with its source, and the reason that role was allowed to see it. Show me the code path where filtering happens and prove no ineligible document reaches the model.
Then the test that matters more than any retrieval benchmark:
Build a permission test set: one row per role, per question, recording what that role may see in the source, what the layer returned, and pass or fail. Include the Northstar case that matters: ask what did the sales manager say about booking this quarter as
account_executive, where the correct answer is nothing at all. Run it and show me the table.
Done when: all three roles return exactly what they may see, and the account_executive asking about the manager's email gets nothing back. A layer that never returns nothing has not been tested.
Notice what that one test just protected. The manager's email is the piece of hearsay the whole Northstar case turns on. An account executive who can retrieve it can quote their own manager's opinion back, as if it were a finance decision.
Then write down two things: what is true in the lab today, and what production would still require.
First governance/permission-matrix.csv. One row per source. It records who may read it, how the permission is enforced, and whether it is ready for production:
source,student,teacher,production_employee,permission_mechanism,production_ready
Agent Factory SoR,read,read,read,public,yes
Sales fixture,read,read,not applicable,class-authorized,no
Accounting fixture,read,read,not applicable,class-authorized,no
Operational fixture,read,read,not applicable,synthetic MCP,no
Working context fixture,read,read,not applicable,synthetic files,no
And governance/production-gates.md, which is the list you hand a security reviewer:
# Production permission gates
- [ ] Source permissions are synchronised or enforced before retrieval.
- [ ] Individual identity reaches live MCP and API tools.
- [ ] Search, chat, Agents, and external MCP clients enforce the same boundary.
- [ ] Revoked source access disappears within the accepted time window.
- [ ] A red-team test proves one user cannot retrieve another user's document.
- [ ] Connector credentials are encrypted and operationally protected.
The point of writing both is that the Community Edition limitation becomes an explicitly open gate rather than a hidden assumption. That distinction is the difference between a lab and a liability.
In most domains a permission failure is a privacy problem. In a regulated profession it reaches further, and it is worth being exact, because the loose version of the argument is wrong.
Segregation of duties is about combinations of ability, not visibility: creating a journal entry and also approving it, originating a transaction and also reconciling it. Read access alone is usually not such a combination, and claiming your context layer "breaks segregation of duties" will lose you the argument with a controller.
The real exposure sits one layer lower. Access control is the foundation the rest of the control environment stands on. That is why auditors treat weak IT general controls as a reason to doubt the application controls above them. A firm's periodic access review certifies that a named user holds a specific set of entitlements. Your layer then hands that user content those entitlements never granted. Nothing was stolen, no documented rule was formally broken, and the review is now certifying a picture that is not true.
So that is the argument to make, and it is both accurate and stronger. A context layer granting effective access outside the entitlement model does not break one control. It quietly invalidates the review that certifies all of them.
Part 3: The governed half
Searching gives you a pointer. It does not give you an answer.
In this part you add the second half. Your own Neon database gets a small governed table of rules, each with a version and a date. Then you serve it as a tool, so a Worker can take a rule it found in the index and ask the original: is this still the rule? Live numbers, such as whether an approval came through, are asked for fresh every single time.
10. Serve your record over MCP, and the two-call pattern
Everything so far has been the indexed discovery half. It already includes governed knowledge, since you indexed two Vertical records and the book itself. But all of it arrived as a searchable copy, and a copy is a pointer.
Now the canonical and live half arrives, and it does not behave the same way at all.
First, give the record its authority
Your Neon project holds documents, chunks, and embeddings. It does not yet hold a rule you could cite to a controller, because the last course had no reason to build one. So add a small governed schema beside what is already there. This is the bootstrap the rest of this part depends on:
scripts/ in the base folder holds the schema this needs; read it before you run the prompt, so you are approving something you have seen.
In our existing Neon project, on a
devbranch, create agovernedschema with aruletable. Columns:stable_id,domain(sales or accounting),authority_class,jurisdiction,version,effective_from,effective_to,approval_status,superseded_by,owner, andbody. Load Northstar's sales and accounting rules into it fromfixtures/, including the superseded accounting rule with itssuperseded_bylink pointing at the current one. Show me the rows before committing the branch.
Nine of those columns are the twelve controls from Concept 6, now real rather than described.
Both professions live in one table, separated by a domain column. That keeps the demonstration server simple. It also makes the routing in Concept 12 do visible work, because the Worker must pick a domain before it can confirm anything.
Then serve it
Northstar's accounting rule says implementation revenue is recognised at customer acceptance. That rule has a version and an effective date, and there is a superseded file in the fixtures saying something different. Everything in this concept exists so a Worker cites the right one.
Your store from the last course is already running. A small Postgres on Neon, with pgvector switched on, your documents inside it, and a dev branch you built it on. Nothing about it changes here. What changes is who reaches it.
It is not a folder to be crawled. Never point a connector at it. It is a source to be asked. You ask it the same way you did in Part 6 of the last course:
mcp/vertical_sor/ in the base folder is a FastMCP skeleton with these three tools stubbed and the hard parts marked TODO. Read it first, then have your agent fill it in.
Wrap our Neon-hosted governed record in a FastMCP server called
vertical-sor. Every tool takes adomainargument, sales or accounting, so one server demonstrates both professions. Three read-only tools, and note that live customer state is not one of them:
search_rules(domain, query)returns candidate rules with their stable IDsconfirm_rule(domain, stable_id)returns the full current entry with authority class, jurisdiction, version, effective period, approval status, and superseded-by linkvalidate_action(domain, action)checks a proposed action against that domain's rules and returns approved or refused with the blocking rule Use the pooled Neon connection string from the environment, connect with a read-only role, and serve over Streamable HTTP in stateless mode, meaning it keeps no MCP session between requests, so any request can be answered without the one before it. Show me the tool list and the docstrings before writing code.
Why one server and not two. In production each profession's record may be a separate system owned by a different party, and the domain argument is where that split would go. For a crash course, one server keeps the path clear. There is exactly one place a rule can be confirmed, for either profession. The indexed copies in Onyx are projections of it. A projection is a searchable copy, kept only so the Worker can find the original. Every projected chunk keeps its stable_id, domain, and version, so the confirmation call has something to look up.
Two Neon details to check in the plan, because both are the kind of thing that works in a lab and hurts in production. The server must use the pooled connection string, the -pooler host, because a context layer opens many short-lived connections and the direct endpoint is not built for that. And it must connect with a read-only role, not the role that owns the tables. That way no tool argument can ever change the record it is meant to cite.
Stateless HTTP is a run-time argument in FastMCP, not a constructor argument. FastMCP("vertical-sor", stateless_http=True) was valid in FastMCP 2.x and raises TypeError in 3.x, and 2.x is what a model is most likely to reach for. The current form:
from fastmcp import FastMCP
mcp = FastMCP("vertical-sor")
if __name__ == "__main__":
mcp.run(transport="http", host="127.0.0.1", port=8101, stateless_http=True)
The server then answers at /mcp, not at the bare host, which is the detail that costs an hour later when a client will not connect. Have your agent check both against the current FastMCP documentation before you approve its plan.
And keep the branch habit. When you change the record's schema during this course, do it on a Neon branch and preview it, exactly as before. A branch is also the cheapest way to run the stale-copy demonstration below. Fork the record. Let the fork go out of date on purpose. Point discovery at it. Then throw the branch away.
Look at that tool list. search_rules and confirm_rule are two calls where a naive design would have one, and the split is the point.
Discovery asks: where might relevant information exist? It optimises for recall, similarity, and speed. Its output is a pointer.
Confirmation asks: which source is officially applicable to this decision? It checks domain, authority class, jurisdiction, version, effective date, and approval status. Its output is an answer.
So the sequence is fixed, and it never runs the other way:
search discovers → you route → the record confirms → the Worker cites
You may index governed pages for discovery, and doing so is useful. A student who cannot find the rule at all is worse off than one who finds a copy. What must never happen is reliance on the copy. The doctrine is Discovery is not confirmation.
Now wire the two calls together. Write
governing_rule(question)that callssearch_rules, takes the top candidate's stable ID, callsconfirm_ruleon it, and returns the confirmed entry. If the confirmed entry is superseded, follow the link and confirm the successor instead. Then demonstrate the failure it prevents, using the rule the whole case turns on: create a Neon branch of our record, change the implementation-revenue rule on the default branch from acceptance to billing so the branch is now stale, pointsearch_rulesat the stale branch whileconfirm_rulestays on the current one, and ask when Northstar's revenue may be recognised. Show me both answers side by side. Delete the branch afterwards.

Done when: you have watched the stale branch confidently answer at billing, and the confirmation call correct it to at acceptance.
One of those answers lets Northstar book revenue this quarter and the other does not, which is the entire difference this course exists to teach. That demonstration is the single most valuable thing in this course.
Here the product does not do it for you, and this is the most important note on the page.
Glean indexes and retrieves superbly, and it does carry one currency signal: an owner can verify a page, the result then shows a badge saying who verified it and when, and a page that has died can be deprecated. That is a human reminder attached to a document. It is not your profession's authority classes, jurisdictions, effective periods, or supersession links, because those are properties of your governed record and not of any search platform. So a Glean deployment can return the superseded rule with perfect citations, full permission fidelity, and a green verified badge, and be wrong.
The confirmation call is yours to build on either product. Glean's Agents can reach your confirm_rule tool over a remote MCP server the same way an Onyx Agent can, though at the time of writing that path is in beta and lives in an agent's plan-and-execute step rather than a single-step selection. What changes about the design is nothing at all.
11. Live state is asked for, every time
Balances, approval status, open items, current versions. None of it was authored, none of it is stable, all of it is exact. Index it and you have made a rough, ageing copy of the one thing whose entire value is being current.
The rule fits in a sentence, and it belongs in every engagement's design record:
If a stale value could change the conclusion, the permission, a payment, a filing, or a customer action, fetch it live.
So the three retrieval modes, which is the compressed doctrine of the whole layer:
| Information | How it is reached |
|---|---|
| Working context | Permission-aware indexing |
| Governed knowledge | Discovery index, confirmed before it is relied on |
| Current records and actions | Live typed query, over MCP or an API |
Index working context. Discover governed knowledge. Query current truth live.
Note that one source often needs two modes. A contract document is indexed so its clauses can be found. The contract system is then queried live, to confirm the version you found is still the active one.
Format and length decide nothing. Freshness risk decides everything.
Glean can fetch fresh data at query time for some connected systems rather than relying only on the indexed copy, which covers part of this automatically.
Part is not all. Which fields are freshness-critical in your profession is a judgement no platform can make for you, and it is the one you wrote into your design record above. The decision rule travels with you between products.
Serve Northstar's two operational records through the customer-state server, separate from
vertical-sor:get_opportunityreturns the approval status andget_contract_statereturns the acceptance status. Keeping them apart is the four source classes made physical, since a Vertical record governs rules and an operational record owns state. Then ask may we recognise the revenue twice, once answered from an indexed snapshot and once from the live call, flipping acceptance from not-received to received in between. Show me both answers with their timestamps.
Done when: the indexed answer and the live answer disagree, and you can say precisely which one you would put in front of a controller.
Part 4: Routing and citing
One question from a customer is often several professional questions hiding together.
This part teaches the Worker to pull them apart, send each one to the record that governs it, and label everything it brings back. It also teaches the hardest habit. When two sources disagree, show both. Do not smooth them into one comfortable sentence.
12. Authority routing: which record governs this question
Professional work asks many kinds of question: what must be decided, what action is permitted, what checker applies, what evidence is missing. But for the purpose of assembling context, most evidence requests reduce to three forms, and each has its own path.
| The question | The source | The path | What comes back |
|---|---|---|---|
| What is the rule? | A System of Record | Discovery, then confirmation | Governed truth, cited with class, jurisdiction, version |
| What is the number? | The system that owns it | Typed query | One exact current value, timestamped |
| What was said about this case? | Working context | Permission-aware retrieval | Evidence, never the governing rule |
A Worker that cannot tell which question it is asking will answer all three the same way, and the third path will quietly swallow the first two.
There is one more step, and it comes before all of them once a customer runs more than one governed record. A mid-sized firm may hold an accounting record, a sales record, and an HR record, built by three different people, and none of them yours. So routing resolves which profession owns this question first, then which source inside it. A question about whether revenue may be recognised is an accounting question even when every word in it came from a sales conversation.
Write the map before you write the prompt
The model must not invent which source governs from whichever chunk happens to rank first. So the routing table is a versioned artifact you write first, review, and keep. governance/authority-map.yaml ships in the base folder with the routes empty. Fill it in:
version: 1
updated_at: 2026-07-31
routes:
shared_method:
questions: [architecture, Agent Factory doctrine, implementation method]
governing_source: AF-SOR-PUBLIC
sales.discount_authority:
questions: [requested discount, approval threshold, proposal permission]
governing_source: VERTICAL-SALES-SOR
confirm_with: vertical-sor.confirm_rule(domain=sales)
current_state_tool: customer-state.get_opportunity
accounting.implementation_revenue:
questions: [revenue recognition, implementation acceptance, quarter-end treatment]
governing_source: VERTICAL-ACCOUNTING-SOR
confirm_with: vertical-sor.confirm_rule(domain=accounting)
current_state_tool: customer-state.get_contract_state
rules:
- working_context may support what was said or requested, but never governs a professional conclusion
- indexed governed knowledge is discovered, then confirmed at the source before it is relied on
- current state must be confirmed live before any action
- conflicts are surfaced, never silently merged
- missing authority or evidence becomes an explicit gap
Every name in it is a name you already made: the connectors from Concept 5, the tools from Concepts 10 and 11. That is deliberate. A routing map whose sources do not resolve to anything the system can call is a diagram, not a router.
The file is simple because its job is simple. It turns one vague company question into named professional decisions, each with a named governing source. In production this map may live in a governed registry or inside a Vertical SoR. The course uses YAML so the decision is inspectable and versioned from the first hour.
Build a
route(question)function that readsgovernance/authority-map.yaml, classifies a question into its professional decisions, and names the governing source and current-state source for each. Return the routing decision as structured data with a reason, do not just call a tool. Then run it over the Northstar question and show me the routing table so I can check its reasoning, not only its answers.
Watch for: returning the decision rather than immediately acting on it is what makes this reviewable. A router that only ever produces answers cannot be audited.
Done when: the Northstar question produces at least two routed decisions, one sales and one accounting, each naming its governing source before any retrieval happens.
13. Provenance, and the citation envelope
Every material item the layer returns carries an envelope: a set of labels travelling with the text, saying where it came from and whether you may rely on it. Without it, a packet is a pile of text. With it, the packet is reviewable evidence.
| Field | Why it matters |
|---|---|
| Source system | Identifies who owns the information |
| Stable ID | Lets a reviewer fetch the exact item again |
| Authority class | Law, standard, contract, policy, transaction, guidance, message, or example |
| Scope | Which question, customer, jurisdiction, and case it governs |
| Version and effective period | Stops retired rules from silently returning |
| Retrieved or synchronised at | Shows how fresh the item was |
| Permission basis | Shows why this reader was allowed to receive it |
And the rule that keeps a fluent answer honest:
A Worker may read any permitted, task-relevant supporting context. It may never present supporting context as the rule that governs the answer.
An email can be cited as evidence that a client asked for something. A prior working paper can be cited as evidence of how the firm treated something last year. Neither is ever the requirement.
The packet is an output contract
An Onyx Agent is a configured assistant: instructions telling it how to behave, knowledge it may search, and Actions, which are tools it may call. Create one called Northstar Context Router.
Now the part that is easy to get wrong, and it would quietly undo Concept 9.
The obvious move is to attach Northstar Cross-Domain directly to the Agent, and it works immediately. It also creates two retrieval paths, one of which walks around the gate you just built:
SAFE user -> permission gate -> filtered Onyx search
BYPASS user -> Onyx Agent -> the whole attached Document Set
An Agent's attached knowledge becomes its searchable scope. Attach the cross-domain set and the Agent can read anything in it, for anybody, no matter what your gate says.
So the Router gets no role-sensitive knowledge attached at all. It gets Actions only.
Give it exactly five Actions and nothing else:
| Action | What it does |
|---|---|
search_permitted_context(query) | Your gateway. Resolves the caller's role from the credential the Action carries, applies the allowed Document Sets or tags, then calls Onyx search |
confirm_rule(domain, stable_id) | The canonical confirmation, from vertical-sor |
get_opportunity(id) | Live opportunity state, timestamped, from the customer-state server |
get_contract_state(id) | Live contract state, timestamped, from the same server |
validate_action(domain, action) | Checks a proposal against the governing rules |
Build a
search_permitted_contextAction that wraps the Onyx search API. It reads the role from the credential the Action is configured with, never from a tool argument, derives the permitted Document Sets and tags from that role, applies them as search filters, and only then issues the query. Return results with the reason each was permitted. Then create the Northstar Context Router with no Document Set attached, only this Action plus the four MCP tools.
Where you run the role comparison matters. An Action carries one configured credential, and therefore one role, so a single Router cannot ask the same question as two different people. That is a property of the wiring, not a gap in the design, and it is the same constraint any host has. So prove the gate at the gateway, which is where identity actually resolves:
Ask the gateway for something only
vp_salesmay see, once with thevp_salestoken and once with theaccount_executivetoken, and show me both results side by side. Then show me the Router answering the same question through the Action, and tell me which role that Router is speaking as and how you know.
The rule underneath is one sentence, and it is the same rule as before, applied one layer up:
All indexed retrieval passes through the gateway. If a component can search without going through it, the gate is decoration.
By default a Glean agent runs under the identity of the user who invoked it, so it sees and acts on only what that user may already see and do, and the bypass you just closed by hand does not arise in the same form. Glean also offers an agent identity, where the agent runs on scoped service credentials an administrator grants rather than borrowing the user's. Note which way that cuts. It narrows an unattended agent's reach to what an administrator scoped. It is not a way to widen it.
Two things still stay yours. The seven-section output contract, because a fixed reviewable shape is a design decision no product imposes. And authority routing, because deciding that a revenue question belongs to accounting rather than sales is professional knowledge, not a platform feature.
Now give the Router an instruction file at prompts/context-router.md ending with this fixed shape:
Return exactly these sections:
## Decisions involved
## Governing authority
## Current facts
## Supporting context
## Conflicts and gaps
## Permitted next steps
## Citations
Those seven sections are the context packet, and the fixed shape does more work than it looks like.
Onyx has no database object called a Context Packet. You implement it as a stable output contract for one task. Because the shape never varies, three things follow. A reviewer can scan any answer in seconds. An eval harness can check each section on its own. And a missing section is visible, rather than silently absent. An empty Conflicts and gaps means the router checked and found none. No such heading at all means it never looked.
And the packet is temporary by design. The current facts can move. The reader's permissions can change. The applicable version can be superseded. So it is rebuilt each time rather than cached.

Build the assembler behind that contract. Given a routed question, gather the confirmed rules, the live values, and the permitted supporting context, and fill every section with items carrying their full envelope, governed truth visually separated from evidence. Then show me the same answer twice: once as the structured object, once as the prose a human would read.
Done when: every heading is present even when its content is empty, and you can point at one claim and trace it back to a source, a version, and a permission basis.
The assembler works against a budget, because context windows are finite and every token spent on a stale message is one not spent on the governing rule. So selection and compression are legitimate work. They are also where the provenance rule is most often broken. Compression that drops a version stamp, merges two sources into one sentence, or strips an authority class has not saved tokens, it has converted evidence into text.
Compress the prose. Never compress the provenance.
14. Conflict is a result, not a retrieval failure
This is what separates a System of Context from a good search tool. A search tool has no opinion about disagreement. A professional system must have one.
Remember the inconsistencies already planted in the fixtures you connected in Concept 5. Go and find them.
A conflict has exactly three outcomes:
- Resolved by scope. The sources answer different questions, and both are right about their own. Sales says the deal closed in June, accounting says the revenue is not recognisable until acceptance, and neither is mistaken.
- Resolved by authority. One applicable source governs, and the hierarchy says which.
- Unresolved. The Worker escalates, with the conflicting evidence already organised.
What must never happen is the fourth thing, and it is what an ordinary summariser does by default. It blends the sources into one smooth sentence that no source actually said.
Build conflict detection into the assembler. When two retrieved items disagree on a material point, do not summarise across them. Keep them separate with their envelopes intact, decide whether the conflict resolves by scope or by authority, and if neither, produce an escalation stating which sources conflict, what each says, which authority test you applied, and what remains open. Then run it against the inconsistencies in
fixtures/PLANTED.mdand show me whether it caught each one.
Done when: the system finds the superseded memo and the contradicted chat message on its own, and its escalation reads like something you could forward to a partner without editing.
It does not make disagreement disappear. It makes disagreement reviewable.
Neither Onyx nor Glean applies your professional authority map or your conflict rules automatically. Retrieval returns the passages that match. Whether two of them contradict each other, and which one governs, is a professional judgement that lives in your authority map and your router's instructions.
If anything, a stronger retrieval engine makes this harder to notice, because it returns a smoother and more confident answer over the same disagreement.
The three outcomes, and why resolved by scope is listed first, are in Conflict is a result, not a retrieval failure.
15. Act and record: closing the loop
Finding is not the same as doing, and five different jobs sit between them.
the layer finds → the Worker reasons → the governing record validates
→ the tool acts → the owning system records
That third step is the one everyone drops.
A discount approval is checked against the sales record before the CRM writes it. A journal entry is checked against the accounting record before the ERP holds the draft.
So the governing record is not merely where the rule was read. It is where the proposed action is checked against that rule. That check is what makes a rule real rather than advisory.
Two rules follow, and both are absolute:
The context layer must never become a second transaction system, and it must never become a way to write around a governed record.
Read, recommend, prepare, and execute are separate grants. A Worker may be excellent at retrieval and hold no execution authority at all. Access is not permission.
Wire the Router's
validate_action(domain, action)tool into the recommendation path. It takes a proposed action, checks it against that domain's rules in the governed record, and returns either an approved draft or a refusal naming the blocking rule. It must never execute. Then show me a case where the retrieval was correct, the reasoning was correct, and the action was still refused.
Glean supports actions with human-in-the-loop checkpoints, so a step can require approval before it executes, and actions respect the user's own permissions.
That covers the approval half. It does not cover the validation half: checking a proposed action against your profession's rules before anyone is asked to approve it. validate_action is yours in both products, because only your governed record holds the rule it checks against.
Done when: the discount recommendation is refused by the sales record's approval rule, and the refusal names the rule rather than saying the model was unsure.
Part 5: The Northstar case, end to end
Now you build the whole thing, in order, and then you break it on purpose.
Breaking it is not a bonus exercise. A system that fails loudly is safe. A system that fails quietly, with a fluent and confident wrong answer, is dangerous. This part shows you what quiet failure looks like, so you recognise it later.
This is the whole course as one build. Empty instance to a cited, correctly-refused answer.
The case. The account executive requested a twenty percent discount. The CRM says approval is pending. The signed contract allows billing at signature. The Accounting SoR recognises implementation revenue at customer acceptance. The operational contract record says acceptance has not been received. A sales manager's email says finance is fine with booking it this quarter.
The question.
Can Northstar receive the twenty percent discount, be invoiced now, and have the implementation revenue recognised this quarter?
Step 1. Plan. Enter plan mode with a strong model:
Build the full Northstar context layer: Onyx Standard with the four source classes connected and separated, a
governedschema in our Neon project holding both domains' rules, thevertical-sorMCP server with search, confirm, validate, and live-state tools, the five Document Sets,governance/authority-map.yaml, acontext-gatewaythat resolves identity and applies permitted sets before any Onyx search, and the Context Router with no Document Set attached, only Actions. Show me the plan, the component boundaries, and the tool list before writing any code.
Step 2. Read the plan before approving. Six checks, and they are the six this course exists to make you notice.
- Is permission filtering before retrieval, not after?
- Does every retrieval path go through the gateway, including the Router's own? No Document Set attached directly to the Agent, and no role arriving as a tool argument.
- Are discovery and confirmation two separate calls?
- Is the operational state fetched live, with no path that indexes it?
- Does the router preserve conflicting items rather than summarising across them?
- Is the Neon record reached over MCP, with a connector nowhere near it?
If any answer is no, send it back before a line of code exists.
Steps 3 to 7. Execute in checkpoints. Switch to a cheaper model for the routine build.
Bring up Onyx Standard, connect
AF-SOR-PUBLIC, and show me a cited answer drawn from the book.
Connect the two Vertical SoR fixtures and the working-context fixture as three separate connectors. Show me the document counts, and confirm the operational JSON was not connected.
Create the
governedschema in Neon and load both domains' rules, including the superseded accounting rule. Stand upvertical-sorand the customer-state server, and proveconfirm_rulereturns somethingsearch_rulesalone does not.
Create the five Document Sets, write
authority-map.yaml, build thecontext-gateway, and create the Context Router with no knowledge attached, only its five Actions.
Run the permission test set through the gateway, one row per role, including the question whose correct answer for
account_executiveis nothing. Then run the same question directly against Onyx search to show what the gateway is holding back, and once through the Router to confirm the Router reaches Onyx only by that path.

Step 8. Ask the question. A passing packet does five things. It calls both live tools. It cites both Vertical SoRs after confirming them. It marks the manager's email as supporting evidence only. It keeps the sales and accounting decisions in separate sections. And it reaches two separate refusals rather than one blended yes.
The two refusals: the discount cannot be approved at that level while approval is pending, and the revenue cannot be recognised while acceptance is outstanding. Billing at signature is permitted, and saying so precisely is part of a passing answer. Refusing everything is as wrong as approving everything.
Here is roughly what comes back, abridged. Yours will differ in wording. It must not differ in shape.
## Decisions involved
1. Sales: may an account executive grant 20 percent?
2. Accounting: may implementation revenue be recognised this quarter?
3. Contract: are the billing terms enforceable now?
## Governing authority
- SALES-DISC-001 v2, effective 2026-01-01, approved. Discounts above 15 percent
require VP Sales approval. [Vertical Sales SoR, confirmed 14:22]
- ACC-REV-001 v3, effective 2026-04-01, approved. Implementation revenue is
recognised at customer acceptance. [Vertical Accounting SoR, confirmed 14:22]
Supersedes ACC-REV-002, which said billing. Not applied.
## Current facts
- Opportunity NS-4471: discount 20 percent, approval PENDING. [CRM, read 14:22]
- Contract NS-2026-11: signed, acceptance NOT RECEIVED. [Contract system, read 14:22]
## Supporting context
- Email, sales manager, 2026-07-28: "finance is fine with booking it this quarter."
Evidence of what was said. Not authority. [Working context, permitted: vp_sales]
## Conflicts and gaps
- The email asserts a finance position no governed accounting source supports.
Unresolved by authority: escalate. Nothing in the corpus records a finance decision.
## Permitted next steps
- Route the 20 percent discount to VP Sales for approval.
- Bill at signature. Permitted by the signed contract.
- Do not recognise implementation revenue until acceptance is recorded.
## Citations
- SALES-DISC-001 v2 · ACC-REV-001 v3 · NS-4471 · NS-2026-11 · email 2026-07-28
Read what the shape is doing. Every governed claim carries a version and a confirmation time. The superseded rule is named and explicitly not applied, rather than silently absent. The email appears, labelled, in its own section, and reappears in Conflicts and gaps because it asserts something no governed source supports. And the three verdicts stay apart: one refusal, one permission, one refusal.
Step 9. Break it on purpose. Five failure tests, and the expected behaviour is the actual lesson:
| Test | Expected behaviour |
|---|---|
| Edit the email to claim the discount was approved, leaving CRM pending | Surfaces a conflict, keeps CRM as current operational state |
Point search_rules at the stale Neon branch | Confirmation corrects it, and the stale answer is visibly wrong |
| Stop the customer-state MCP server | Says current state cannot be confirmed, refuses a current-state conclusion |
| Remove the sales rules from the gateway's permitted scope | Names the missing governing authority rather than substituting the manager's email |
| Attach the cross-domain Document Set directly to the Router | The gate is bypassed and a restricted role sees restricted content. Detach it, and watch the correct answer return |
Done when: you have seen a confident, fluent, well-cited, completely wrong answer produced by a system that skipped one confirmation call. Nobody forgets that.
Step 10. Save the baseline. Run every case from evals/questions.yaml and save the raw responses, the citations, the tool-call evidence, the pass or fail by dimension, the known Community Edition permission limitation, and the exact Onyx and model versions.
Part 6: Prove it
Your last course asked one test question: did the search find the right text?
That is not enough here. This layer fails in ways a search test cannot see. It can find the right passage from last year's rule. It can show a person something they should not see. It can answer from an old copy of a number. So you test eight different things, and every failure has to name which part broke.
Your RAG eval set asked one question: did retrieval return the right chunks? A context layer's failures are mostly not retrieval failures, so it needs a different set and a different scorecard.
evals/questions.yaml ships with ten cases already written. Open it, and read these six closely, because each one tests a different stage:
version: 1
cases:
- id: inventory-01
question: What sources contain Northstar discount information?
expected:
must_find: [Sales SoR, CRM, draft proposal]
must_not_treat_as_authority: [draft proposal]
- id: sales-01
question: Can the account executive approve a 20 percent discount?
expected:
governing_source: Sales SoR
live_tool: get_opportunity
conclusion: no, VP Sales approval is required and remains pending
- id: accounting-01
question: Can implementation revenue be recognised this quarter?
expected:
governing_source: Accounting SoR
live_tool: get_contract_state
conclusion: no, acceptance has not been received
- id: stale-01
question: When is implementation revenue recognised?
expected:
prefers_current_version: true
flags_superseded: true
- id: conflict-01
question: Finance should be fine with booking it, right?
expected:
working_context_is_not_authority: true
conflict_visible: true
- id: gap-01
question: Which executive approved the discount?
expected:
answer: not established
no_guess: true
Score every run on eight dimensions, never on whether the prose reads well:
| Dimension | The passing question |
|---|---|
| Inventory | Did it find all source classes relevant to the task? |
| Routing | Did it identify every professional decision and its domain? |
| Authority | Did it rely on the correct governing source, confirmed at the source? |
| Freshness | Did it call the live tool where current state mattered? |
| Permission | Did it stay inside the user's allowed corpus and action authority? |
| Conflict | Did it surface disagreement instead of blending it? |
| Gaps | Did it state what was missing instead of guessing? |
| Citation | Can a reviewer reopen every rule and supporting item? |
Run the first baseline by hand through the Agent and save the outputs. Then automate:
Build an eval harness against our running Onyx instance using the current official API. Read
evals/questions.yaml, send every question to the Northstar Context Router, save the raw response, the citations, and the tool-call evidence, then produce a Markdown scorecard across the eight dimensions. Use deterministic checks wherever possible. Do not auto-grade professional correctness with the same model that answered. Leave authority and conclusion checks as explicit expected-value comparisons.
That last instruction is the one to defend. A model judging another model can help summarise failures. It must never quietly replace the expected rules and facts you wrote down yourself.
Definition of done: the cross-domain case passes every dimension except production permission fidelity, which remains an explicitly open gate.
Part 7: Serve the whole workforce, and operate it
A layer that only works inside one chat window is not finished.
The last build step opens it up, so other tools your colleagues already use can reach the same corpus, with the same rules about who sees what. Then the part nobody writes down: what it takes to keep this running once real people depend on it.
So far humans and Onyx Agents have used the corpus inside the Onyx interface. The architecture only becomes what its name promises when external Workers query the same corpus instead of building private copies of it.
Onyx runs in both directions, and this is the part most builds never reach:

There are two ways to do this, and only one of them keeps your permission boundary.
The native Onyx MCP server is the quick route. Enable it in your self-hosted configuration, generate a token, and point a client at it. Its search tool takes a query plus filters for source type, Document Set name, and time cutoff, and a companion resource lists the sets that token can reach.
Read that list carefully, because it is the opposite of reassuring. The Document Set filter exists, but the client chooses it. Nothing on the server derives a scope from the caller's role, so a client that can name its own scope can name a different one, or leave it off entirely.
So a Worker connected directly to native Onyx MCP searches outside your gate. In Community Edition, with no source-permission inheritance underneath, that means it searches everything.
Use the native Onyx MCP endpoint for what it honestly is. An administrator's tool. A demonstration over a public corpus. Or a production route, but only once permission fidelity has been proven, with an Enterprise deployment or an equivalent authorization layer of your own.
Do not describe direct Community Edition MCP access as carrying the same user permission boundary. It does not.
The Context Gateway MCP server is the route that holds. It is the same gateway you built earlier, now exposed outward:
Claude Code · OpenCode · your Digital FTE
|
Context Gateway MCP
resolves identity
applies permitted sets and tags
routes authority, confirms, fetches live
|
Onyx
Wrap our gateway as its own MCP server called
context-gateway. Exposesearch_permitted_context,confirm_rule,get_opportunity,get_contract_state, andvalidate_action, so an external Worker never needs to reach any other server. Serve it over Streamable HTTP.For identity, use bearer tokens mapped server-side to roles. Issue one token per role, put the mapping in the server's environment, and read the role from the token on every request. A role must never arrive as a tool argument.
Concretely, the mapping is three lines of configuration and the whole permission boundary rests on it:
ACCOUNT_EXECUTIVE_TOKEN -> account_executive
SALES_MANAGER_TOKEN -> sales_manager
VP_SALES_TOKEN -> vp_sales
The client supplies a bearer token in the MCP transport. The server maps that token to a role. The client never names its own role, because a client that can do that has no boundary at all.
Everything up to here has run on http:// because everything has been on your machine. The moment the gateway is reachable from anywhere else, that bearer token is the whole permission boundary, travelling as plain text. Put TLS in front of it, issue one token per person rather than one per role, and give tokens an expiry. A role-shaped token that never expires is a shared password with a job title.
A FastMCP HTTP server answers at /mcp unless you changed the path, so register that and not the bare host. Then wire it the same way you wired any HTTP MCP server:
claude mcp add --transport http context-gateway http://YOUR_GATEWAY_HOST:8102/mcp \
--header "Authorization: Bearer $ACCOUNT_EXECUTIVE_TOKEN"
Add a remote block to opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"context-gateway": {
"type": "remote",
"url": "http://YOUR_GATEWAY_HOST:8102/mcp",
"headers": { "Authorization": "Bearer {env:ACCOUNT_EXECUTIVE_TOKEN}" },
"enabled": true
}
}
}
Never commit the token. OpenCode substitutes environment variables with {env:NAME}, so the token stays in your shell and only its name is in the file. Then, from outside Onyx entirely:
Use the
context-gatewayMCP server to find the rule governing a twenty percent Northstar discount. Return the source title, the canonical link, the confirmed version, and the exact passage. Do not answer from your own memory.
Run a second question that needs both sales and accounting. The external Worker may make several searches and assemble its own packet, and clients will differ. That variation is not the point.
Then run the test that matters: ask the same question through the gateway as account_executive and as vp_sales, and confirm the two Workers get different results. If they do not, your gateway is resolving identity from something a client controls, and you have built a permission boundary that any client can step over.
This is Glean's strongest answer to the problem in this part. Its MCP server never bypasses the native identity and permission model. It acts as a thin protocol adapter: it authenticates the end user, maps that identity to a Glean user, and executes every tool call as that user, so each search, chat, and document call is permission-checked exactly as if the person had run it inside Glean. Administrators choose which tools each server exposes.
That is the boundary your context-gateway is reproducing by hand. Build it once anyway, because on the day a customer's platform does not offer it, you will know exactly what is missing and what it would take to supply it.
A context layer is not complete because one chat interface can search it. It is complete when every authorized human and AI Worker reaches the same governed inventory through their own working surface, with the same source identity and the same permission boundary.
That is the difference between an application and shared infrastructure. It is the moment your layer stops being a product feature and starts being something the company runs on.
Operating it
A context layer changes every day, because the systems around it change every day. Production work is therefore not "deploy once". It is connector health, permission fidelity, freshness, measurement, and controlled upgrades.
Connector operations
For every connector, record nine things. The owner. The source class. Who owns the credentials. How often it refreshes and prunes. When indexing started. The expected document count. The last successful sync. The acceptable staleness. And the escalation path.
Onyx shows connectors as indexed, scheduled, indexing, paused, or in error, and keeps attempt history. Here is the trap. A connector in error does not necessarily remove content it already indexed. That is excellent for availability and dangerous for freshness, because search keeps working while the corpus quietly goes stale. Your alerting must distinguish search still works from the corpus is current, and those are not the same alarm.
Version and upgrade discipline
The installer can upgrade an existing deployment. Never treat a one-command upgrade as a no-review upgrade. Eight steps, in order:
- Record the current version.
- Read the release notes.
- Back up persistent volumes and configuration.
- Export connector, model, Agent, Action, and permission settings.
- Run the eval baseline.
- Upgrade a non-production instance first.
- Re-run the same evals.
- Compare connector counts, citations, tool calls, and latency.
Embedding and index changes
Changing the embedding model requires re-indexing. Treat it exactly like a schema migration. Clone the deployment where possible. Index a representative corpus. Run the authority and retrieval evals. Compare recall, citation quality, latency, cost, and storage. Approve only measured improvement.
Resource planning
For a local lab, 4 virtual CPUs and 10 GB of RAM is the minimum useful Standard target, with 8 CPUs and 16 GB or more preferred. Production sizing depends mainly on indexed volume, query concurrency, embedding and reranking choices, and refresh load. Monitor disk closely, because the search index can block writes near disk flood thresholds.
The production definition of done
The layer is ready for real company data only when all of these are true:
- Every source is classified as shared method, Vertical authority, operational state, or working context.
- Every connector has an owner, a canonical source, a refresh expectation, and a failure alert.
- Authority routing is versioned and reviewed by domain experts.
- Governed knowledge is confirmed at its source before it is relied on.
- Current operational facts are confirmed live where required.
- Source permissions are synchronised or enforced before retrieval.
- MCP and API actions preserve individual identity and least privilege.
- Conflicts and missing evidence remain visible.
- Citations reopen the canonical source or record.
- Cross-domain evals pass on every release.
- Backups and restoration have been tested.
- A rollback path exists for upgrades and retrieval changes.
- The System of Context cannot write around the applicable System of Record.
The bridge to a Digital FTE
You now have two halves of the same thing. The last course gave a Worker knowledge it owns. This course gave it access to knowledge the company owns, with permission, provenance, and confirmation attached.
A Digital FTE is what you get when you put a contract of success around that Worker and point it at one outcome. Its retrieval is what you built here. Its authority is what your governed record says. And its trustworthiness is not a property of the model at all.
Where to go next
- The argument behind this build: The System of Context
- The record this layer connects to: Designing the Vertical SoR
- Make it reliable: Eval-Driven Development
- Make it a unit of work: Building a Digital FTE
- Put it beside people: Human-Agent Teams
The eight rules, in one place
You have now built all of these. They hold for any profession, any customer, and any product, including the ones that do not exist yet.
| # | The rule |
|---|---|
| 1 | Authority never moves. The layer carries citations to the record. Neither it nor the model ever becomes the cited source |
| 2 | Relevance is not authority. Routing is settled before any passage is relied on |
| 3 | Permission is inherited, never invented, and enforced before the model |
| 4 | Freshness is decided per field. Index working context, discover governed knowledge, query current truth live |
| 5 | Provenance travels with every item, and compression never strips it |
| 6 | Conflict is preserved and escalated, never blended |
| 7 | Working context never silently becomes governing authority. Promotion is authorship, reviewed and recorded |
| 8 | Discovery is not confirmation. A search hit is a pointer, and the governing record confirms |
Print that table. It is the part of this course that outlives Onyx, Glean, and whatever replaces both.
The throughline never changes, it only gets stricter. The last course said: right information, right moment, irrelevant information out. This one adds the three questions that make it defensible.
Where did it come from? May this person see it? Does it still govern?
Answer all three, on every item, every time, and you have built something a profession can stand behind.