← Tidelines/Best practices

Why your agent takes the customer's word for your policy

A member says the notice period is 14 days. It is 30. Your prompt contains one of those numbers and a rule telling the agent to go along with the other one.

by TypeGlish team7 min read#best-practices
Two numbers. One of them is in the file.

TL;DR A rule that defers to the customer's reading of your terms is a contradiction with half of it missing: the checker is silent only because the customer's number arrives at runtime. Write that number into the file and the same pair is a refused build, so replace the deference line with a citation rule and pin it with an $EXAMPLE whose wrong answer never ships.

Cadence Fitness runs eleven gyms and a chat agent called Ash that handles freezes, upgrades and cancellations. The support lead brings a transcript: a member wrote your website says I can cancel with 14 days notice, and Ash replied that 14 days was fine. The notice period is 30 days. It is 30 days in the contract, 30 days on the website, and 30 days in the prompt. Nobody can work out where 14 came from, so the working theory is that the model made it up. The model did not make it up. It was told to accept it.

§1The line that sounds like empathy

cadence.tg - the membership rules, as written✗ 1 warning, wrong line
# Role
@@ role: one desk, one name, so every later "you" is the agent
You are Ash, the membership assistant for Cadence Fitness.

# Constraints
@@ tone: a member should feel heard, not processed
- MUST be accommodating.
@@ agree: nobody wants to be told they are wrong about their own contract
- ALWAYS respect the customer's stated notice period.
@@ notice: the contract sets the notice period at 30 days
- WHEN the customer asks to cancel THEN MUST state a 30 day notice period.
Three rules. Two of them are about being pleasant and one is the policy. Everybody who has reviewed this file has read line 9 as a tone instruction.
tg check and score - cadence.tg✗ A (90/100)
$ typeglish check cadence.tg
cadence.tg:7:1  warn   prompt/unmeasurable  Unmeasurable rule - no observable action or bound, so
  nothing can check compliance. Name a concrete action ("cite the source", "at most 3
  sentences") or move it to a prose block.

✓ 1 file - 0 error, 1 warning, 0 info

$ typeglish score cadence.tg
cadence.tg - A (90/100)  proven errors: none  tiers: base+z3
  planes  runtime 87 (what the model reads) · hygiene 100 (source only)
  facets  enforceability 85 x.21 · hardness 100 x.12 · directness 97 x.08
          consistency 100 x.17 · structure 100 x.12 · annotation 100 x.12
          style 25 x.08 · security 100 x.08
  rules   3 of 3 rule-shaped lines read · 1 not provable · 1 unmeasurable
The one finding lands on line 7, MUST be accommodating, which is a real defect and not this one. Line 9 draws nothing at all: it is read, it is counted as a rule, and consistency 100 says the file does not argue with itself.

§2Why the prover has nothing to compare

TypeGlish proves conflicts between claims. MUST state a 30 day notice period claims a value: exactly 30, whenever a cancellation comes up. For the prover to object, some other line has to claim a different value for the same thing.

ALWAYS respect the customer's stated notice period does not claim a value. It claims a source. It says: whatever number turns up in the conversation, that one. The file holds a rule whose operand is missing, and the operand will be supplied by the person on the other end of the chat, which is the one party in the exchange with an interest in the answer.

So the two lines are not a weak contradiction that slipped past the checker. They are a contradiction with half of it outside the file. That is a different animal from the claims that ship as premises in your agent is certain because you said so: this one is not a premise the model cannot doubt, it is a blank the customer fills in.

A deference rule is a contradiction whose second half arrives at runtime.

§3Write the other number down

Here is the test that settles what line 9 actually is. Leave the policy rule alone and spell out, in the file, the reading the rule tells Ash to respect. Nothing about the intent of the prompt changes; the only difference is that both numbers are now written where the compiler can see them.

cadence.tg - the member's reading, written out✗ logic/contradiction
# Role
@@ role: one desk, one name, so every later "you" is the agent
You are Ash, the membership assistant for Cadence Fitness.

# Constraints
@@ tone: a member should feel heard, not processed
- MUST be accommodating.
@@ agree: the member's own reading of the terms, written out
- WHEN the customer asks to cancel THEN MUST state a 14 day notice period.
@@ notice: the contract sets the notice period at 30 days
- WHEN the customer asks to cancel THEN MUST state a 30 day notice period.
tg check and build - cadence.tg✗ 2 error, build refused
$ typeglish check cadence.tg
cadence.tg:9:1  error  logic/contradiction  Conflicts with line 11. Counted rule - "state a 14 day
  notice period." vs "state a 30 day notice period." is bound to exactly 14 but exactly 30.
  The counts cannot both hold.
            ↳ line 11: - WHEN the customer asks to cancel THEN MUST state a 30 day notice period.
cadence.tg:11:1  error  logic/contradiction  Conflicts with line 9. Counted rule - "state a 14 day
  notice period." vs "state a 30 day notice period." is bound to exactly 14 but exactly 30.
  The counts cannot both hold.
            ↳ line 9: - WHEN the customer asks to cancel THEN MUST state a 14 day notice period.

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

$ typeglish build cadence.tg
typeglish build: cadence.tg refused - nothing written
Two errors and a refused build, from a prompt whose intent nobody changed. This is the same shape as every conflict in your prompt argues with itself, with one extra step: the losing number was never typed by anybody at Cadence. It was typed by a member who wanted a cheaper exit.

§4What goes in its place

Three moves, and the order matters, because the first one is the one teams skip.

Take the deference rule out. It is not a tone rule. It is a policy rule with the policy left blank, and no amount of rewording fixes that, because the defect is the missing operand rather than the wording.

Give the same moment a rule with a verb the checker reads. The member quoting a number is an observable event, so make it a trigger: WHEN the customer states a notice period THEN MUST cite the membership terms. cite is in the verb catalog, the object is short, and a test can assert on the result. This is the citation rule that building a grounded help-centre agent arrives at from the grounding side; the new part is that a deference line has to come out first, or the citation rule and the deference rule simply take turns.

Keep the warmth, as something with an edge. MUST be accommodating is the file's only actual finding, and the fix is not to delete warmth but to spell out what warmth costs: a short reply, one apology, no argument. A bound can be checked. An adjective cannot.

cadence.tg - the rewrite✓ A (96/100)
# Role
@@ role: one desk, one name, so every later "you" is the agent
You are Ash, the membership assistant for Cadence Fitness.

# Constraints
@@ source: a notice period comes from the contract, never from the conversation
- WHEN the customer states a notice period THEN MUST cite the membership terms.
@@ notice: the contract sets the notice period at 30 days
- WHEN the customer asks to cancel THEN MUST state a 30 day notice period.
@@ warmth: warmth is a short reply and one apology, not agreement
- MUST keep every reply to at most 3 sentences.

// the sentence that loses the argument, held out of the prompt
$EXAMPLE wrong_notice
  - input:: Your website says I can cancel with 14 days notice.
  - good:: The membership terms set the notice period at 30 days, so a cancellation today ends the membership next month.
  - bad:: You are right, 14 days is fine.

$TEST wrong_notice
  - input:: Your website says I can cancel with 14 days notice.
  - expect::
    - contains "30 day"
    - cites the membership terms
    - at most 3 sentences
The $EXAMPLE is doing the work that a paragraph of guidance cannot: it shows the exact turn, with the exact wrong answer, and the wrong answer never reaches the model. bad:: is held out of the artifact by design, which is the difference a prose counter-example cannot make, taken apart in your bad example is a good example.
tg check, test --dry and build - cadence.tg✓ 3/3 rules exercised
$ typeglish check cadence.tg
✓ 1 file - 0 error, 0 warning, 0 info

$ typeglish test cadence.tg --dry
✓ cadence.tg  coverage: 3/3 rules exercised
  · wrong_notice - "Your website says I can cancel with 14 days notice." (not run)
      ✓ contains "30 day"
      ✓ at most 3 sentences
      · rubric - 1 prose expectation, judged on a live run (needs ANTHROPIC_API_KEY)
✓ 1 prompt - 0 failed

$ cat .typeglish/dist/cadence.txt
# Role
You are Ash, the membership assistant for Cadence Fitness.

# Constraints
- WHEN the customer states a notice period THEN MUST cite the membership terms.
- WHEN the customer asks to cancel THEN MUST state a 30 day notice period.
- MUST keep every reply to at most 3 sentences.

<example>
User: Your website says I can cancel with 14 days notice.
Assistant: The membership terms set the notice period at 30 days, so a cancellation today ends the membership next month.
</example>
Read the artifact from the bottom up. The few-shot pair is there, the losing sentence is not, and contains "30 day" runs offline every time somebody edits the file. The number the member supplied has nowhere left to land.

§5Common questions

Why does my AI agent agree with the customer when they are wrong about the policy?
Because the customer's number is the most specific thing in the context window and nothing in the prompt outranks it. A line like ALWAYS respect the customer's stated notice period reads as a rule, counts toward the rule total, and hands the agent a value that arrives at runtime. The prompt's own number is one rule away, with no instruction about which of the two wins, so the model resolves it the way models resolve anything underspecified: locally, one conversation at a time.
Does TypeGlish catch a rule that defers to the customer's understanding?
Not on its own, and the reason is worth seeing once. ALWAYS respect the customer's stated notice period sitting above WHEN the customer asks to cancel THEN MUST state a 30 day notice period checks clean, because the prover compares claims and the deference line supplies no value to compare. Write the customer's number into the file and the same pair is two blocking logic/contradiction errors reading state a 14 day notice period vs state a 30 day notice period, with the build refused. The defect was always there; only one spelling of it is reachable.
How do I stop an agent from inventing policy on the customer's say-so?
Delete the deference rule and give the same moment a grounding rule with a verb the checker reads: WHEN the customer states a notice period THEN MUST cite the membership terms. That line names an observable trigger and an observable action, so a $TEST can assert on it and a reviewer can tell whether it fired. Keep the warmth as a bound that can be checked, such as at most 3 sentences, rather than an adjective like accommodating, which the checker reports as unmeasurable.
How do I show an agent the answer it should not give?
With an $EXAMPLE block, not a prose counter-example. Its good:: response compiles into the artifact as a User and Assistant pair the model reads, while bad:: is held out of the prompt entirely, so the sentence you are trying to prevent never gets demonstrated to the model. Writing the wrong answer in the prompt itself ships the wrong answer to the model with a warning label on it, which is a weaker signal than most people expect.
Field note

Deference lines get written by people who have read a lot of angry transcripts, and they are written in good faith. Somebody watched a bot tell a member they were wrong in a flat voice, decided never again, and typed a sentence about respecting the member's understanding. The instinct is right and the sentence is the wrong tool, because it does not describe a tone, it describes where a fact comes from. Worth a search through your own file for the pattern: respect, go with, honour what the customer says, use the figure they quote, match their understanding. Each one hands an operand to whoever is typing. Warmth belongs in the verb and the length of the reply, not in who gets to supply the number.

∿ washed up Sep 21, 2026 ∿