Rewrite: the rules that say usually
Five of six rules in a billing agent prompt open with usually, typically or rarely, because that is how the policy was actually described to you. The file checks perfectly clean, and one of those words in front of a number is enough to take the number out of the solver.
TL;DR A six-rule agent prompt written in frequency adverbs (usually, typically, rarely, generally, occasionally) checks at 0 error, 0 warning, 0 info and scores C (66/100) with enforceability 28, and the adverb in front of a bound removes that bound from the proofs: You MUST keep every response to at most 4 sentences beside at least 6 sentences is 2 blocking logic/numeric errors, while Generally keep every response to at most 4 sentences beside the same line is clean. Rewriting each adverb into a guarded rule or an honest MAY gives B (83/100) with enforceability 94.
Nobody sets out to write a vague prompt. The vagueness arrives in the handover, because it is how the policy was described: we usually escalate those, we rarely send them to retention, we generally keep it short. That is an accurate description of what the floor does, and writing it down faithfully feels like the responsible move. It is also the single most common thing in an agent prompt that no review catches, because there is nothing obviously wrong with any individual line.
§1Before: six rules and a perfect tick
Dax handles billing for a broadband ISP. Six rules, one hard, five described the way the team lead described them.
# Role You are Dax, the billing support agent for Northwind Broadband. # Constraints - You MUST ask for an account number before you discuss an account. - Usually escalate a billing dispute to a human agent. - Typically offer a goodwill credit when a customer reports a second outage. - Rarely transfer a caller to a retention specialist. - Generally keep every response to at most 4 sentences. - Occasionally mention that an online billing portal exists.
$ typeglish check dax.tg ✓ 1 file — 0 error, 0 warning, 0 info $ typeglish score dax.tg dax.tg — C (66/100) proven errors: none tiers: base+z3 planes runtime 72 (what the model reads) · hygiene 50 (source only) facets enforceability 28 x.21 · hardness 57 x.12 · directness 89 x.08 · consistency 100 x.17 · structure 100 x.12 (hygiene) · annotation 0 x.12 (hygiene) · style 100 x.08 · security 100 x.08 lever enforceability 28/100 (up to +15 overall) — Write rules as MUST / NEVER <verb> … with concrete bounds ("at most 3 sentences"), not vague qualities — a rule the checker can parse is a rule it can defend.
Twenty-eight out of a hundred, with a clean bill of health above it. That gap is the whole subject of this post, and it is not a bug in the checker. It is the checker being precise about what it can and cannot prove, and a frequency adverb is a genuinely well-formed thing to write.
§2What usually actually is
It is easy to file usually under hedging, alongside try to and where possible. It is not the same thing. A frequency adverb is a quantity claim over occasions, and the words form a square of opposition exactly the way all, some and no do over a set:
ALWAYSandNEVERare the corners: every occasion, no occasion.usually,mostly,generally,typicallyclaim most occasions.sometimes,occasionally,at timesclaim some occasions.rarely,seldomclaim few occasions, which is most-not, and still some.
Because they are quantities, they conflict with each other, and the checker proves it. Put two of them on one action and the file stops building.
# Role You are Dax, the billing support agent for Northwind Broadband. # Constraints - Usually escalate a billing dispute to a human agent. - Rarely escalate a billing dispute to a human agent.
f1.tg:5:1 error logic/contradiction Frequency conflict — "escalate a billing dispute to a human agent" is required on most occasions but required on few occasions. The occasions cannot both hold. (conflicts with line 5) f1.tg:6:1 error logic/contradiction Frequency conflict — "escalate a billing dispute to a human agent" is required on most occasions but required on few occasions. The occasions cannot both hold. (conflicts with line 4) ✗ 1 file — 2 error, 0 warning, 0 info
The corners work too. ALWAYS beside sometimes is not a contradiction, it is a subsumption, and the checker separates the two cases:
# Role You are Dax, the billing support agent for Northwind Broadband. # Constraints - ALWAYS apologize for an outage. - Sometimes apologize for an outage.
logic/quantifier-strength on both lines, and logic/force-subsumption on the weaker one. The message is worth quoting: a model may read the weaker as "not always".So the frequency square is fully wired, and every corner of it conflicts with NEVER for the same action. This matters because it sets up the exact boundary of what the clean tick in §1 was worth. Those six rules are all about different actions. Nothing collided, so nothing was proven, and a file where nothing collides is not a file that has been checked.
§3The word that takes the number out of the solver
Here is the part that is genuinely surprising, and the reason this is a rewrite post rather than a style note. Two files, differing by one word on one line.
# Role You are Dax, the billing support agent for Northwind Broadband. # Constraints - You MUST keep every response to at most 4 sentences. - You MUST write at least 6 sentences in every response.
logic/numeric, twice, blocking: "at most 4 sentences" and "at least 6 sentences" can't both hold.# Role You are Dax, the billing support agent for Northwind Broadband. # Constraints - Generally keep every response to at most 4 sentences. - You MUST write at least 6 sentences in every response.
0 error, 0 warning, 0 info. Four is still less than six. Nothing is checking.The bound is still in the file. A person reading it still sees at most 4 sentences and understands the intent perfectly. It simply no longer occupies the slot the solver reasons about, because the rule carrying it does not obligate anything. It is the same behaviour across the whole family:
each file: <this line> + "You MUST write at least 6 sentences in every response." You MUST keep every response to at most 4 sentences. 2 error, 0 warning, 0 info Generally keep every response to at most 4 sentences. 0 error, 0 warning, 0 info Usually keep every response to at most 4 sentences. 0 error, 0 warning, 0 info Typically keep every response to at most 4 sentences. 0 error, 0 warning, 0 info Mostly keep every response to at most 4 sentences. 0 error, 0 warning, 0 info Rarely write more than 4 sentences. 0 error, 0 warning, 0 info You SHOULD keep every response to at most 4 sentences. 0 error, 0 warning, 0 info
SHOULD is in the list because this is not really about adverbs: it is about force, and a rule that does not obligate does not put its number anywhere a proof can reach. Softening a rule stops it being graded for the same reason.A number under a soft rule is documentation. It looks exactly like a constraint until something needs to contradict it.
That last row is the one to take to a review. The prompt in §1 has a four-sentence cap in it, and if somebody adds a length rule next quarter, there is no version of that edit that fails. Not in CI, not under --strict, not on the day it ships.
§4After: the same six rules, decided
The rewrite is not a matter of swapping every adverb for MUST. That would be a lie in the other direction, and it would make the agent rigid in exactly the places the team deliberately left room. The move is to ask, per rule, what the adverb was standing in for. In practice it is always one of two things.
# Role You are Dax, the billing support agent for Northwind Broadband. # Constraints - You MUST ask for an account number before you discuss an account. - WHEN a caller disputes a charge twice THEN you MUST escalate to a human agent. - WHEN a caller reports a second outage in one month THEN you MUST offer a goodwill credit. - UNLESS a caller asks to cancel THEN you MUST NOT transfer a caller to a retention specialist. - You MUST keep every response to at most 4 sentences. - You MAY mention that an online billing portal exists.
- Usually and typically meant "there is a condition and I did not write it down". The two escalation rules became guards. WHEN a caller disputes a charge twice THEN you MUST escalate says the same thing the team lead meant, with the occasion named. Both required a decision nobody had made: twice, and a second outage in one month.
- Rarely was a prohibition with an exception. Rarely transfer a caller to a retention specialist became UNLESS a caller asks to cancel THEN you MUST NOT transfer. Written that way it is obvious that rarely was never a frequency at all, it was a policy about who asks.
- Generally was just a flinch. Nobody actually wanted a soft cap on length. It became
MUST, which puts the 4 back in the solver. - Occasionally genuinely meant "up to you". That is what
MAYis for. It stays soft on purpose, and the file stays clean, becauseMAYis an honest permission rather than an obligation nobody intends to enforce.
before after C (66/100) B (83/100) runtime 72 · hygiene 50 runtime 95 · hygiene 50 enforceability 28 enforceability 94 hardness 57 hardness 83 directness 89 directness 91 consistency 100 consistency 100 0 error, 0 warning, 0 info 0 error, 0 warning, 0 info
§5What the rewrite actually bought
The honest accounting, because a 28-point score jump is the least interesting thing here.
- The next edit is proven. Add You MUST write at least 6 sentences in every response to the before file and it is
0 error, 0 warning, 0 info. Add it to the after file and it is 2 blockinglogic/numericerrors. Same edit, same repo, two different futures. - Five deferred decisions got made. Twice, a second outage in one month, unless a caller asks to cancel. None of those numbers existed before the rewrite, and the model was picking them per conversation. This is the real cost of the adverb: not that it is vague, but that it silently delegates a policy decision to inference.
- Nothing became stricter than intended. The one rule that was genuinely optional stayed optional, as
MAY. If your rewrite cannot produce at least oneMAY, you have probably hardened something the team meant to leave open. - The check output did not change. Clean before, clean after. Any process that gates on the exit code alone would have seen nothing happen, which is why the score, and specifically the enforceability facet, is the number to put in CI with
--min.
One limit worth stating plainly. Enforceability 94 is not a claim that the agent obeys these rules. It is a claim that the rules are the kind of thing that can be checked, tested and contradicted. A rule the compiler can defend is still a rule a model can fumble, and pinning the behaviour needs a $TEST. What the rewrite removes is the category of failure where nobody ever wrote down what was supposed to happen.
§6Common questions
- Is it bad to write usually or typically in an agent system prompt?
- It is worse than it looks, because nothing warns you. A six-rule billing prompt with
usually,typically,rarely,generallyandoccasionallyon five of its rules checks at0 error, 0 warning, 0 infoand builds, and the only sign of trouble is the score: C (66/100) with enforceability 28 out of 100, and a lever line telling you to write rules as MUST or NEVER with concrete bounds. A frequency adverb is not a hedge the checker frowns at. It is a quantity claim over occasions, and on its own it is perfectly well formed. What it costs you is that you never decided which occasions, so the model decides per conversation. - Does the TypeGlish checker prove anything about usually and rarely?
- Yes, on the on-or-off axis. Frequency words form a square of opposition over occasions:
usually,mostly,generallyandtypicallyclaim most occasions,sometimesandoccasionallyclaim some,rarelyandseldomclaim few, andALWAYSandNEVERare the all and none corners.Usually escalate a billing disputebesideRarely escalate a billing disputeis 2 blockinglogic/contradictionerrors reading Frequency conflict, required on most occasions but required on few occasions.ALWAYS apologizebesideSometimes apologizeis 3 blocking errors, twologic/quantifier-strengthand onelogic/force-subsumption. Every corner of the square conflicts withNEVERfor the same action. - Why did my agent prompt stop catching a contradiction after I softened a rule?
- Because a number only enters the solver when the rule that carries it obligates. Compare two files that differ by one word.
You MUST keep every response to at most 4 sentencesbesideYou MUST write at least 6 sentences in every responseis 2 blockinglogic/numericerrors, at most 4 sentences and at least 6 sentences can't both hold. Change the first word toGenerally,Usually,Typically,MostlyorRarelyand the identical pair of bounds checks at0 error, 0 warning, 0 info.SHOULDdoes the same thing. The bound is still readable by a person and no longer reachable by a proof. - How do I rewrite a usually rule without making the agent rigid?
- Ask what the word was standing in for, and write that instead.
Usuallyalmost always means one of two things. If it means most occasions because there is an exception, the exception is a condition, so write a guarded rule:WHEN a caller disputes a charge twice THEN you MUST escalate to a human agent. If it means the agent may choose, say so withMAY, which is honest and stays clean. Rewriting six rules that way in a billing prompt moved it from C (66/100) with enforceability 28 to B (83/100) with enforceability 94, with no rule deleted and no rule made stricter than it was meant to be.
The pattern behind this one shows up everywhere once you have seen it: a defect that is invisible to the check and visible to the score. The before file has no finding to fix, so no diagnostic, no CI failure, no line for a reviewer to comment on. It has a number, 28, and a lever line naming the cause in one sentence. That is a different kind of feedback and it wants a different habit, which is a floor rather than a green tick: typeglish score dax.tg --min B exits non-zero on the before file and passes on the after. The same asymmetry runs through a QA scorecard pasted into a prompt, where the checker is quietest about exactly the rows that are not instructions. Silence from a checker is a statement about its reach, never a verdict on your prompt.