Your agent has never heard of a wallboard
A prompt review reads the rules. It almost never reads the nouns, which is unfortunate, because the nouns are the part your company invented and the model is quietly filling in from somewhere else.
TL;DR A system prompt carries two glossaries and only one of them ships: $DEFINE word teaches the compiler that a term names exactly one thing and is stripped at build, while a declaration teaches the model what the term means and renders into the artifact, so choosing between them is choosing whether the definition reaches the model at all.
Here is a rule from a broadband support prompt: You MUST log the disposition code before you close a contact. It is measurable, it is second person, it is hard, and it will pass any review your team runs. It is also addressed to a reader who has never worked in your contact centre, has no idea which of several things a disposition code might be, and will not say so.
§1The words you stopped seeing
Every operation grows a private vocabulary, and a contact centre grows more than most. Wallboard, truck roll, after-call work, disposition code, tier 2, deflection, soft close, ACW. Some of these are industry terms a model has plausibly read about. Some are yours. The two categories look identical in the file, because by the time you write the prompt you have been saying these words daily for two years and they have stopped registering as jargon at all.
The model does not resolve them the way it fails to resolve a nonsense word. It resolves them the way it resolves any underspecified reference: to the most probable reading, drawn from everything else it has read. That is a guess with a confident surface, which is the worst kind to debug, because the transcript looks like the agent followed your rule.
TypeGlish has a name for the specific place this bites, and it is grammatical rather than semantic. The definite article is a lookup instruction. Writing the wallboard tells the reader to go and retrieve one particular wallboard, so if the document never introduced one, the retrieval happens somewhere else.
# Role @@ role: name the domain so "helpful" has a scope You are a support agent for Northwind Broadband. # Constraints @@ disposition: the reporting pipeline reads this label, not the transcript - You MUST log the disposition code before you close a contact. @@ no_dates: scheduling is owned by dispatch, so a date here binds a team that never saw it - You NEVER quote a date for a truck roll. @@ surge: a wallboard surge means the queue is deep, so shorter replies clear it faster - WHEN the wallboard shows a surge THEN you MUST keep a reply under 3 sentences.
priors.tg:7:1 info prompt/unintroduced-definite "the disposition code" retrieves something this document never introduces - a model must guess which code is meant. Introduce it on another line ("You manage a code.") or name it outright. priors.tg:11:1 info prompt/unintroduced-definite "the wallboard" retrieves something this document never introduces - a model must guess which wallboard is meant. Introduce it on another line ("You manage a wallboard.") or name it outright. ✓ 2 files - 0 error, 0 warning, 2 info
Two findings from three jargon terms, which is itself instructive. A truck roll is indefinite, so it introduces itself and nothing fires; the model still does not know what one is, it just has not been ordered to look one up. The customer never fires either, because a support agent’s customer is a role the language already knows. The check is a floor, not a vocabulary audit, and the terms it stays quiet about are still yours to worry about.
§2Two glossaries, one file
The reframe: your prompt has two glossaries, they are written in different syntax, and they answer different questions.
The compiler glossary is $DEFINE word, which shipped in TypeGlish 0.7.2. It takes one lemma and a closed schema of two parameters: - class:: picks noun, verb or adjective, and - unique:: true declares that the lemma names exactly one thing, which is what makes the wallboard need no introduction.
The model glossary is ordinary TypeGlish declaration syntax, and its defining property is that a declaration renders. Binding and instruction are the same statement, so The %disposition code% IS the outcome label you attach to a closed contact registers the name for the checker and tells the model the thing it needed to know. The %…% sigils bind the two words as one name and strip on compile.
Here is the same prompt with both glossaries used deliberately.
<$CONFIG> $DEFINE word wallboard - class:: noun - unique:: true </$CONFIG> # Role @@ role: name the domain so "helpful" has a scope You are a support agent for Northwind Broadband. # Context @@ disposition_def: the label is ours, so the model cannot know it The %disposition code% IS the outcome label you attach to a closed contact. @@ truck_roll_def: an engineer visit, not a delivery The %truck roll% IS a visit by an engineer to a customer address. # Constraints @@ disposition: the reporting pipeline reads this label, not the transcript - You MUST log the %disposition code% before you close a contact. @@ no_dates: scheduling is owned by dispatch, so a date here binds a team that never saw it - You NEVER quote a date for a %truck roll%. @@ surge: a wallboard surge means the queue is deep, so shorter replies clear it faster - WHEN the wallboard shows a surge THEN you MUST keep a reply under 3 sentences.
Not one rule changed. The scorecard moves anyway, and it moves in a place worth understanding.
priors.tg - A (92/100) proven errors: none tiers: base+z3 planes runtime 89 (what the model reads) · hygiene 100 (source only) facets enforceability 90 x.21 · hardness 100 x.12 · directness 67 x.08 · consistency 100 x.17 structure 100 x.12 (hygiene) · annotation 100 x.12 (hygiene) · style 63 x.08 · security 100 x.08 L7 prompt/unintroduced-definite −0.25 "the disposition code" retrieves something this document L11 prompt/unintroduced-definite −0.25 "the wallboard" retrieves something this document never glossary.tg - A (96/100) proven errors: none tiers: base+z3 planes runtime 95 (what the model reads) · hygiene 100 (source only) facets enforceability 90 x.21 · hardness 100 x.12 · directness 83 x.08 · consistency 100 x.17 structure 100 x.12 (hygiene) · annotation 100 x.12 (hygiene) · style 100 x.08 · security 100 x.08
enforceability does not budge, because the rules were always measurable. directness goes 67 to 83, which is the honest one: directness is the minimum over a statement’s doer and its resolved pointers, and an unintroduced definite is an unresolved pointer. The prompt got more direct by naming its nouns, not by rewriting a single instruction.§3Only one of them ships
This is where the mental model stops being a nice framing and starts changing what you write. Build the file and look at what the model actually receives.
✓ built .typeglish/dist/glossary.txt ← glossary.tg (43bdf828cd47, full) # Role You are a support agent for Northwind Broadband. # Context The disposition code IS the outcome label you attach to a closed contact. The truck roll IS a visit by an engineer to a customer address. # Constraints - You MUST log the disposition code before you close a contact. - You NEVER quote a date for a truck roll. - WHEN the wallboard shows a surge THEN you MUST keep a reply under 3 sentences.
$DEFINE word wallboard block is gone, and so the word wallboard appears in the artifact exactly once, in a rule, with no definition anywhere.Read that artifact as the model. You are told what a disposition code is and what a truck roll is. You are told to watch the wallboard for a surge, and you are told nothing else about wallboards, because the only thing the file said about wallboards was said to the compiler.
Which is correct, in this case. A contact-centre wallboard is a real and reasonably well-documented thing, so the odds a model resolves it sensibly are good, and paying tokens to define it every turn would be waste. But the shape of the decision is now visible, and it has a sharp edge: $DEFINE word silences the finding without answering the question. Use it on a term the model genuinely does not know and you have made the file quieter and the agent no better informed. The finding was the only thing telling you the gap existed.
A compiler row is a promise you are making. A declaration is a definition you are giving.
§4The compiler glossary is checked, not trusted
A vocabulary system that accepted anything would be a comment with extra syntax, so the rows are parsed strictly and a malformed one is a blocking error rather than a silent no-op. The boundary you will hit first is that a lemma is one word.
<$CONFIG> $DEFINE word disposition code - class:: noun - unique:: true </$CONFIG> # Role You are a support agent for Northwind Broadband.
<$CONFIG> $DEFINE word wallboard - class:: noun - plural:: wallboards </$CONFIG> # Role You are a support agent for Northwind Broadband.
badword.tg:2:3 error structure/define-word-form $DEFINE word defines ONE word per row - "disposition code" isn't a single word (letters, with interior ' or -). Split it into one row per word, or use the compound catalog for multiword vocabulary. badparam.tg:4:5 error structure/define-word-param "plural" isn't a param of $DEFINE word (class, unique) - the row was read WITHOUT it, so it configured nothing. Remove it, or move a runner setting to $CONFIG. ✗ 2 files - 2 error, 0 warning, 0 info
Three more codes close the same gap: structure/define-word-class for a class that is not one of noun, verb or adjective, structure/define-word-unique for a non-boolean uniqueness or a unique referent claimed on something that is not a noun, and structure/duplicate-define-word for one lemma defined twice. The whole point of a strict schema here is that a vocabulary declaration you got wrong is worse than none: it reads as though the word is handled.
§5Which glossary does a term belong in?
Three questions, in order, and they take about ten seconds per term.
- Does a rule depend on this word? If no rule mentions it, it does not belong in the prompt at all. A forty-term glossary the rules never touch is a document, and documents belong behind a retrieval step where they cost nothing until something asks.
- Would a competent new hire, on day one, with no access to your wiki, know what it means? That is a good proxy for the model. If the answer is yes, a compiler row is enough. If the answer is no, it needs a rendered declaration, and the tokens are the price of the rule working.
- Is it one word? If yes,
$DEFINE wordis available. If it is a compound, which most of them are, the model glossary is the route, and that is fine: a compound almost always needs the definition anyway.
The reason this ordering matters is that the usual instinct runs backwards. Faced with two prompt/unintroduced-definite findings, the fast fix is two $DEFINE word rows, and the check goes green. What you have done is tell the compiler that both terms are fine, on your authority, for a reader who was never consulted.
The rules are the part everyone reviews. The nouns are the part everyone assumes.
§6Common questions
- How do I teach an AI agent my company’s internal terminology?
- Decide first which of the two glossaries the term belongs in, because they do different jobs. If the model already knows roughly what the word means and you only need the checker to stop asking you to introduce it, use
$DEFINE word <lemma>with- class:: nounand- unique:: true. If the term is yours, a code, a queue name, an internal label, then it needs a declaration in the file body, because a declaration renders:The %disposition code% IS the outcome label you attach to a closed contactboth binds the name and puts the definition in front of the model. - Why does the checker say my prompt never introduces a noun?
- Because the definite article is a lookup instruction. The wallboard tells the model to go and retrieve one specific wallboard, and if the document never introduced one it retrieves whatever its priors offer instead, confidently and without telling you. That is
prompt/unintroduced-definite, an info finding, and it fires on exactly the words that feel most obvious to write, because those are the words your team has stopped seeing. - Does $DEFINE word explain the word to the model?
- No, and this is the part worth getting right.
$DEFINE wordis a compiler directive: it sits inside<$CONFIG>, it is stripped at build, and nothing about it reaches the artifact. It tells the checker that a lemma is legal vocabulary naming exactly one thing, which is a promise you are making rather than a definition you are giving. Silence the finding on a word the model genuinely does not know and you have removed the warning without removing the guess. - Should the glossary live in the system prompt or in retrieval?
- Put the terms that appear in your rules in the prompt, and everything else in retrieval. A definition only has to be in the prompt if a rule depends on it:
You MUST log the disposition codeis unenforceable if the model does not know what a disposition code is, so that one definition earns its tokens. A glossary of forty terms the rules never mention is a document, and a document belongs behind a retrieval step where it costs nothing until something asks for it.
The reason a pasted policy document goes wrong so reliably is this same seam, seen from the other end: the policy doc somebody pasted into your agent comes out at six prompt/unintroduced-definite findings, because a handbook is written for a reader who already has the vocabulary and a prompt is not. The compiler-versus-model split is the same one that governs @@ notes and every $-command, which your system prompt has a compile time lays out in full: when in doubt about a line, build the file and read what came out.