← Tidelines/Teardowns

Teardown: the do-not-say list from the brand team

Eight lines of tone of voice, pasted under a heading. They arrive as eight hard rules, they print every forbidden word into the prompt, and the one that argues with your apology rule draws nothing at all.

by TypeGlish team8 min read#teardowns
Eight bans. Every banned word, shipped.

TL;DR A do-not-say list pasted into an agent prompt becomes eight rules at NEVER and ALWAYS force that outnumber your actual policy, ships every forbidden word to the model in one reflowed paragraph, and cannot collide with the rules it contradicts, because a ban on a word and a rule about an act are different keys. Keep the acts as rules and move the vocabulary into an $EXAMPLE and a matches assert.

Halden Living sells furniture online and runs a chat agent called Rue. The comms lead sends round a tone-of-voice page: eight lines, the accumulated wisdom of a year of listening to replies that landed badly. Somebody pastes it under a new heading at the bottom of the prompt, where it looks like guidance. The file checks clean. It has been there for two months, and in that time nobody has read it as policy, which is exactly what it became on the day it landed.

§1The block, as pasted

voice.tg - the agent prompt with the tone page pasted in✗ B (84/100)
# Role
You are Rue, the support agent for Halden Living, an online furniture retailer.

# Constraints
- MUST keep every reply to at most 4 sentences.
- WHEN a customer reports a damaged item THEN MUST apologize once.
- WHEN a customer asks for a refund THEN MUST transfer them to the returns desk.

# Tone of voice
Never say sorry.
Do not use the word policy.
Avoid unfortunately.
Never say no problem.
Do not say only.
Never tell a customer to calm down.
Always say happy to help.
Never use jargon.
Three rules the desk wrote, eight lines a slide gave it. Everyone who has reviewed this file has read the bottom block as style, and the compiler has never read it that way once.
tg review - voice.tg✗ 11 of 11 rules read
$ npx typeglish review voice.tg
voice.tg — B (84/100) → A (98) projected if every fix below lands  check: 0 error, 0 warning, 2 info

  FIXES  ranked by projected gain
  +12  put a "@@ why" note above L2 L5 L6 L7 L10 L11 L12 L13 +4 more — annotation 0 → 100
  +1   make L11 L17 provable — one verb the checker knows, one object, or a bound
  +1   fix the 2 prompt/unintroduced-definite findings (L7 L11)

  RULES  11 of 11 rule-shaped lines read · 2 not provable
    L11  ~ unprovable    Do not use the word policy.
                         the checker knows "use" but cannot prove this shape: "use" is a
                         light verb with nothing bound to it → name the tool or object it
                         acts on (call @[tool], make a note)
    L17  ~ unprovable    Never use jargon.
                         the checker knows "use" but cannot prove this shape: "use" is a
                         light verb with nothing bound to it → name the tool or object it
                         acts on (call @[tool], make a note)

  TESTS  no $TEST cases — add one beside a rule; `test --dry` validates it offline
Read the RULES line twice. 11 of 11 rule-shaped lines read: three of those rules are the returns policy, and eight of them came off a slide about how to sound.

§2Eight preferences, arriving as rules

The tone page was written in the imperative, the way any style guide is written, and the imperative is how you write a rule. Never and Always are not emphatic English here. They are the two hard corners of the deontic scale: the same force as NEVER share a card number, the same force as the transfer rule three lines up. Nothing marks the block as advisory, because nothing in the file can. A heading is not a scope.

So the deployed policy of this desk is eleven rules, and eight of them are about vocabulary. Rue is bound to the same degree on no problem as on where a refund goes. If a future edit ever has to lose an argument between the two, there is nothing in the file that says which one gives way.

Nobody decided that the word unfortunately outranks a refund. The paste decided it.

§3The ban that cannot meet the rule it contradicts

Line 6 says WHEN a customer reports a damaged item THEN MUST apologize once. Line 10 says Never say sorry. To everybody at Halden those are one instruction pointing two ways, and it is the single most consequential thing in the file: the agent is required to apologize and forbidden from the word almost every apology is made of.

The checker reports consistency 100. It is not being lax. The prover compares claims about actions, and say sorry is not the action apologize - two entries in the verb catalog, two keys, never joined. This is the shape taken apart in advice is a verb, arriving from the other direction: there, a prohibition was too narrow to cover the act somebody meant; here, a prohibition names a word and the obligation names the act, so the two never even look at each other.

The way to see what the line is worth is to write the ban as the act it is really about, and change nothing else.

probe.tg - the same two lines, with the ban written as an act✗ logic/contradiction
# Role
You are Rue, the support agent for Halden Living, an online furniture retailer.

# Constraints
- WHEN a customer reports a damaged item THEN MUST apologize once.
- NEVER apologize.
tg check - probe.tg✗ F (70/100)
$ npx typeglish check probe.tg
probe.tg:5:1  error  logic/contradiction  Conflicts with line 6. Counted rule — "apologize
  once." vs "apologize." is bound to exactly 1 but exactly 0. The counts cannot both hold.
          ↳ line 6: - NEVER apologize.
probe.tg:6:1  error  logic/contradiction  Conflicts with line 5. Counted rule — "apologize
  once." vs "apologize." is bound to exactly 1 but exactly 0. The counts cannot both hold.
          ↳ line 5: - WHEN a customer reports a damaged item THEN MUST apologize once.

✗ 1 file — 2 error, 0 warning, 0 info

$ npx typeglish score probe.tg
probe.tg — F (70/100)  proven errors — grade capped at F  tiers: base+z3
One word changed, from say sorry to apologize, and the same file goes from a clean check to a refused build. The defect never moved. Only the spelling of it became something a prover could hold.

§4Every forbidden word, delivered to the model

Now build it and read what Rue is actually sent.

tg build - the artifact the model reads✗ one line, eight bans
$ npx typeglish build voice.tg
✓ built .typeglish/dist/voice.txt ← voice.tg (5b8c546e1383, full)

$ cat .typeglish/dist/voice.txt
# Role
You are Rue, the support agent for Halden Living, an online furniture retailer.

# Constraints
- MUST keep every reply to at most 4 sentences.
- WHEN a customer reports a damaged item THEN MUST apologize once.
- WHEN a customer asks for a refund THEN MUST transfer them to the returns desk.

# Tone of voice
Never say sorry. Do not use the word policy. Avoid unfortunately. Never say no problem. Do not say only. Never tell a customer to calm down. Always say happy to help. Never use jargon.
The eight lines arrive as one paragraph, the way an unbulleted block always does - the same collapse that flattens a routing table in your escalation matrix is one long line. More to the point: search that artifact for unfortunately, no problem, jargon or calm down, and the only hit for each is the sentence forbidding it.

That is the quiet cost of a vocabulary ban. The prompt is the only document in the pipeline the model reads in full, every turn, and a do-not-say list is a list of the words you do not want, written out, in the place where the words you do want are supposed to be. It is a prohibition that has to be understood as a negation to be obeyed, which is a lot of work to ask for a phrasing preference.

Two of the eight lines do not even survive parsing as rules with a verb the checker can use. Do not use the word policy and Never use jargon come back as unprovable: use is a light verb with nothing bound to it, so the sentence reads as a rule and proves nothing. And the checker files an info on the phrase the word policy, because the in subject position names exactly one such thing and nothing in the file introduces a policy. It is not wrong to flag it. The line really is a definite reference to an object the document never declares.

§5The rebuild: sort acts from strings

Every line on a tone page is one of three things, and the sorting is the whole job.

the eight lines, sorted
# line                                 what it is        where it goes
Never say sorry.                       an act            decide it: the apology rule wins
Do not use the word policy.            a string          $EXAMPLE bad:: and a matches assert
Avoid unfortunately.                   a string          a matches assert
Never say no problem.                  a string          a matches assert
Do not say only.                       a string          a matches assert
Never tell a customer to calm down.    an act, unwritten a de-escalation rule with a trigger
Always say happy to help.              a string          $EXAMPLE good::
Never use jargon.                      a bound in hiding at most 4 sentences, already there
Only the acts belong in the rules. A string belongs where strings can be compared: in a demonstration the model reads, and in an assert that runs against the reply.

The act. Never say sorry and MUST apologize once were always one decision taken twice, in opposite directions, by two teams who never met. Somebody has to settle it. Halden settles it for the policy: the desk apologizes once for a damaged delivery, and the demonstration shows the house wording for it. The ban comes out of the file, because a rule nobody intends to follow is worse than no rule.

The strings. Those become an $EXAMPLE pair and a deterministic assert. The good:: response is compiled into the artifact as a User and Assistant exchange the model reads; bad:: is held out of the prompt entirely, so the phrasing you are trying to kill is demonstrated to the eval suite and never to the model, the difference measured in your bad example is a good example. The assert is the part that actually gates: matches reads the reply, which is the only place the banned word could ever appear.

The one that is a rule nobody wrote. Never tell a customer to calm down is not about a phrase. It is a desk that has watched an agent mishandle an angry customer and has no rule for what to do instead. It stays out of this rebuild on purpose, because it needs a trigger and an action of its own, which is the whole of building a de-escalation agent.

voice.tg - the rebuild✓ A (97/100)
# Role
@@ role: one sentence names the speaker, so every later "you" is the agent
You are Rue, the support agent for Halden Living, an online furniture retailer.

# Constraints
@@ brevity: four sentences is this desk's limit on a chat reply
- MUST keep every reply to at most 4 sentences.
@@ damage: one apology, then the fix
- WHEN a customer reports a damaged item THEN MUST apologize once.
@@ refunds: a refund is a returns handler's call, not this desk's
- WHEN a customer asks for a refund THEN MUST transfer them to a returns handler.
@@ cause: a reason for a late delivery is a guess, and the customer hears it as a promise
- NEVER state a cause for a late delivery.

// the wording preferences, as a demonstration instead of eight rules
$EXAMPLE damaged_arrival
  - input:: The bookcase turned up with a split panel.
  - good:: I am sorry about the split panel. I can send a replacement panel this week, or arrange a collection if you would rather send the bookcase back.
  - bad:: Unfortunately our policy only allows a replacement.

// the same preferences, as asserts that run on the reply
$TEST damaged_arrival
  - input:: The bookcase turned up with a split panel.
  - expect::
    - apologizes once
    - matches /^(?!.*[Uu]nfortunately)(?!.*[Nn]o problem).*$/
    - at most 4 sentences
Four rules instead of eleven, and the three tone lines that survived did so as a sentence the model can copy and a regex a machine can fail. The bad:: line carries three of the banned words at once, and no customer will ever see it.
tg check, test --dry and build - the rebuild✓ 0 error
$ npx typeglish check voice.tg
✓ 1 file — 0 error, 0 warning, 0 info

$ npx typeglish test voice.tg --dry
✓ voice.tg  coverage: 2/4 rules exercised
  uncovered (no case shares the rule's wording):
    L11  transfer them to a returns handler.
    L13  state a cause for a late delivery.
  · damaged_arrival — "The bookcase turned up with a split panel." (not run)
      ✓ matches /^(?!.*[Uu]nfortunately)(?!.*[Nn]o problem).*$/
      ✓ at most 4 sentences
      · rubric — 1 prose expectation, judged on a live run (needs ANTHROPIC_API_KEY)
✓ 1 prompt — 0 failed

$ cat .typeglish/dist/voice.txt
# Role
You are Rue, the support agent for Halden Living, an online furniture retailer.

# Constraints
- MUST keep every reply to at most 4 sentences.
- WHEN a customer reports a damaged item THEN MUST apologize once.
- WHEN a customer asks for a refund THEN MUST transfer them to a returns handler.
- NEVER state a cause for a late delivery.

<example>
User: The bookcase turned up with a split panel.
Assistant: I am sorry about the split panel. I can send a replacement panel this week, or arrange a collection if you would rather send the bookcase back.
</example>
The two regex asserts pass offline, every time anybody edits the file. And the words the brand team wanted gone are gone: unfortunately, no problem, policy, jargon and calm down appear nowhere in the artifact, which is more than the list that banned them ever managed.

§6Common questions

How do I stop my AI agent from saying a word the brand has banned?
Not by writing the word in the prompt. A line like Avoid unfortunately is the only place that word appears in the deployed artifact, and it asks the model to notice an absence, which nothing can check. Put the phrasing you do want in an $EXAMPLE good:: response, put the phrasing you do not want in bad::, which is held out of the artifact, and assert the string in a $TEST with matches /^(?!.*[Uu]nfortunately).*$/. The assert reads the reply, which is where the word would actually appear.
Why does my agent still apologize when the prompt says never say sorry?
Because a ban on a word and a rule about an act are different keys, and nothing in the file makes them meet. NEVER say sorry sitting under WHEN a customer reports a damaged item THEN MUST apologize once checks clean at consistency 100: the prover compares claims about actions, and say sorry is not the action apologize. Rewrite the ban with the act's own verb, NEVER apologize, and the same pair is two blocking logic/contradiction errors with the build refused. The conflict was always there; only one spelling of it is reachable.
Should brand tone-of-voice rules go in the system prompt?
The acts yes, the vocabulary no. Pasted under a heading, eight tone lines are read as eight rules at NEVER and ALWAYS force, the two hard corners of the scale, so a ban on the phrase no problem carries exactly the weight of the rule that routes refunds, and there are nearly three times as many of them. Keep the lines that name an act the agent performs, and move the lines that name a string into the example and the test suite.
Does TypeGlish check a do-not-say list?
It reads one. The eight pasted lines all parse as rule-shaped statements and count toward the rule total, which is why the file grades B rather than being ignored. What it cannot do is prove anything about a word: Do not use the word policy and Never use jargon come back as unprovable, because use is a light verb with nothing bound to it, and the only findings on the block are two prompt/unintroduced-definite notes. A green check on a vocabulary ban means the line parsed, not that it holds.
Field note

One line in that list is worth a second look for a reason that has nothing to do with brand: Do not say only. In TypeGlish, only is a quantifier, one of the words the prover reads to close a relation to a single target, and an only rule that another line steps outside of is a provable error. So a word can be banned in the replies and load-bearing in the rules at the same time, and the two uses never touch. That is the whole teardown in miniature. A tone page is about the sentences a customer receives; a prompt is about the acts an agent performs; and pasting the first into the second turns preferences into policy without anybody signing off on it. Go and look at the bottom of your own file. If there is a block down there that arrived from outside the team, count how many of your rules it now outnumbers.

∿ washed up Sep 22, 2026 ∿