← Tidelines/Teardowns

Teardown: the system prompt an AI wrote for you

Ask a model for an agent system prompt and it gives you something fluent, tidy, and instantly recognisable. Run it through a checker and you get twelve errors, none of which is the bug. The bug is underneath, and the typography is what was hiding it.

by TypeGlish team7 min read#teardowns
Twelve errors. None was the bug.

TL;DR A machine-drafted agent prompt fails first on its own typography (em-dash, emoji, decorative bullets, a math symbol) and those errors are not cosmetic: they keep the checker from reaching the logic. Sweep the character plane, commit the hedges to real modals, and the actual defect surfaces as logic/numeric - two length rules that cannot both hold, present since the first draft. Rebuilt properly it goes from F (51/100) to A (90/100).

Generated prompts have a house style. Once you have seen a few you can spot one from across the room: the em-dash, the "highly capable and empathetic" preamble, the bullet list with a star emoji, the hedge in every third clause. The interesting thing is not that the style is recognisable. It is that the style is load-bearing in the worst way: every one of those tics costs the checker a tier of analysis, so the fluent draft is also the one whose real defects you cannot see. Below is a returns-agent prompt in that house style. If you have ever asked a model to draft one, you will recognise every line.

§1The prompt, as it arrives

returns.tg - as generated✗ F (51/100)
# Role
You are a highly capable, empathetic AI assistant for Acme — a leading provider of home coffee equipment. Your goal is to delight every customer!

# Guidelines
• Always strive to be as helpful as possible 🌟
• Keep responses ≤ 3 sentences where possible
• When explaining the return policy, provide at least 5 sentences of detail so the customer feels fully informed
• If the customer’s request seems complex, you should probably escalate to a human
Eight lines. Every mark in it is a default a generating model reaches for, not an accident: the spliced dash, the decorative bullet, the star, the math symbol, the curly apostrophe, and a hedge on every rule.

Before reading the diagnostics, try the exercise a reviewer would do: find the behavioural defect. It is in there, in plain English, and almost nobody finds it on the first pass. We will come back to that.

§2Twelve errors, and not one of them is the bug

tg check - output (one line per distinct code)
returns.tg:2:59  error  structure/em-dash  An em-dash splices two statements into one
  line: the checker reads one unparseable blob, and models mirror the tic (the
  canonical AI-tell). Split the statements, or use a comma or colon.
returns.tg:5:46  error  structure/special-character  Emoji is outside the language: the
  instruction plane is checkable English, and models mirror prompt decoration into
  output. Remove it, or demonstrate it inside <examples>.
returns.tg:5:1   error  structure/special-character  Not a list bullet the parser reads: use "- ".
returns.tg:5:1   error  structure/missing-period  Unterminated statement - end it with a period.
returns.tg:5:10  info   prompt/hedging  Hedging - "strive to" turns this instruction into a
  suggestion the model may skip. Delete the hedge, or commit to a modal.
returns.tg:6:18  error  structure/special-character  The numeric tier parses bounds written in
  English: '≤ 3' lowers with no bound while 'at most 3' is Z3-provable. Write it out.
returns.tg:8:18  error  structure/curly-quote  A curly apostrophe is a lookalike: the parsers
  read ASCII ', so possession and contractions written with it are invisible to the
  consistency checker. Straighten it.

 1 file - 12 error, 0 warning, 3 info
Trimmed to one line per distinct code: each of the four bullets also carries its own Not a list bullet and Unterminated statement error, which is how eight lines produce twelve. Every single error is about characters and line shape. Not one is about what the agent will do.

Now the part that should bother you. Run the score and look at the consistency facet.

tg score - as generated
returns.tg - F (51/100)  proven errors - grade capped at F  tiers: base+z3
  planes  runtime 89 (what the model reads) · hygiene 0 (source only)
  facets  consistency 100 x.29 · structure 0 x.21 (hygiene) · annotation 0 x.21 (hygiene) · style 55 x.14 · security 100 x.14
  lever   structure 0/100 (up to +21 overall) - Fix the ledger rows with structure/ codes; most carry a one-click fix.
consistency 100. The checker is telling you, honestly, that it found no conflict between any two rules in this file. It is also wrong, and it is wrong because of the structure score sitting at zero next to it.

This is the mechanism worth taking away from the whole teardown. The checker works in tiers, and the early ones gate the later ones. A line the parser cannot resolve into a statement never reaches the solver, so a conflict inside that line is not missed, it is unreachable. Two of the four bullets here are not statements at all: one is an unterminated fragment, the other carries its bound as a glyph the numeric tier cannot lower. There is nothing for the prover to prove.

The typography is not the defect. It is the reason you cannot see the defect.

§3Pass one: sweep the character plane

So we do the boring pass first, and only the boring pass: plain hyphen for the dash, - for the bullets, straight apostrophe, the emoji gone, and ≤ 3 written out as at most 3. Not one word of policy changes.

returns.tg - ASCII swept, nothing else touched✗ F (46/100)
# Role
You are a highly capable, empathetic AI assistant for Acme, a leading provider of home coffee equipment. Your goal is to delight every customer!

# Guidelines
- Always strive to be as helpful as possible.
- Keep responses at most 3 sentences where possible.
- When explaining the return policy, provide at least 5 sentences of detail so the customer feels fully informed.
- If the customer's request seems complex, you should probably escalate to a human.
Twelve errors to zero errors. The grade goes down, from 51 to 46, which is the correct outcome: the file is no longer failing on hygiene, so the score stops being dominated by it and starts judging the rules. There were never any good rules.
tg check - after the sweep
returns.tg:5:10  info   prompt/hedging  Hedging - "strive to" turns this instruction into a
  suggestion the model may skip.
returns.tg:6:38  info   prompt/hedging  Hedging - "where possible" turns this instruction into
  a suggestion the model may skip.
returns.tg:7:1   warn   typeglish/if-then  WHEN needs a THEN - write WHEN <condition> THEN <action>.
returns.tg:8:1   warn   typeglish/if-then  IF needs a THEN - write IF <condition> THEN <action>.
returns.tg:8:48  info   prompt/hedging  Hedging - "should probably" turns this instruction into a
  suggestion the model may skip.

 1 file - 0 error, 2 warning, 3 info
A second layer, invisible until the first was cleared. Three hedges, and two conditionals that open a condition and then never say what to do about it. Consistency is still reported at 100, because these lines still are not rules.

§4Pass two: make them rules, and meet the bug

Both remaining complaints ask for the same thing: commit. A hedged line is not an instruction, and When explaining the return policy, provide... is a condition with no consequent. So we do what the diagnostics say. Every rule gets a modal, and the sentences say plainly what the draft was gesturing at.

returns.tg - hedges committed to modals✗ logic/numeric
# Role
You are a support agent for Acme, a home coffee equipment retailer.

# Guidelines
- MUST keep every reply to at most 3 sentences.
- MUST give at least 5 sentences of detail when you explain the return policy.
- WHEN the request needs an exception to policy THEN escalate to a human agent.
Shorter, stricter, and now failing. Nothing was added: these are the generated draft's own two length rules, finally written as rules.
tg check - output
returns.tg:5:1  error  logic/numeric  Numeric conflict - "at most 3 sentences" and "at
  least 5 sentences" can't both hold. (conflicts with line 5)
returns.tg:6:1  error  logic/numeric  Numeric conflict - "at most 3 sentences" and "at
  least 5 sentences" can't both hold. (conflicts with line 4)

 1 file - 2 error, 0 warning, 0 info
There it is. "Keep responses short" and "explain the return policy in at least five sentences" were both in the first draft, three lines apart, and they cannot both hold. On every returns-policy question the model has been picking one, per conversation, with nothing in the prompt to say which.

Note what it took to surface a two-line contradiction: a character sweep and a modal pass. Nobody was hiding it. The solver simply could not reach it, because ≤ 3 lowers with no bound and the five-sentence line was not a statement yet. The numbers in a prompt are constraints a prover can hold, which is the argument in the arithmetic in your prompt, but only once they are written in a form it can read.

§5The rebuild

The conflict has two honest resolutions, and choosing between them is the decision the generated draft quietly declined to make. Either reconcile the band (pick one length for every reply), or admit that the policy explanation is a genuine exception and scope it, so the bound only applies where it belongs. A trailing "when you explain the return policy" does not scope anything, it is prose hanging off an unconditional MUST. A real WHEN ... THEN does, and the checker treats it accordingly.

returns.tg - rebuilt✓ compiles · A (90/100)
# Role
@@ role: name the domain, so "helpful" has an edge
You are a support agent for Acme, a home coffee equipment retailer.

# Constraints
@@ brevity: three sentences is the length a chat reply actually gets read at
- MUST keep every reply to at most 3 sentences.
@@ policy_detail: the one place length is worth spending, scoped so it cannot fight the cap
- WHEN you explain the return policy THEN give at least 5 sentences of detail.
@@ order_number: the order number is what makes a return reconcilable
- MUST ask for the order number before starting a return.
@@ window: stating the window prevents the second contact
- MUST state the 30-day return window when a return is requested.
@@ escalation: an exception costs less as a handoff than as a wrong answer
- WHEN the request needs an exception to policy THEN escalate to a human agent.
@@ no_dismissal: dismissal is the complaint that reaches the review site
- NEVER dismiss a customer's complaint.

$TEST policy_length
  - input:: What is your return policy on a grinder I opened last week?
  - expect::
    - states the 30-day return window
    - at least 5 sentences
A (90/100), no errors, no warnings. The two length rules coexist because one is scoped and the compiler can see the scope. The $TEST pins the expensive case: tg test --dry reports coverage: 2/5 rules exercised, so you also know exactly which rules are still riding on hope.

Compare the two files as artifacts and the trade is plain. The generated draft has a persona paragraph, four friendly bullets, and a star. The rebuild has six rules, a note on each saying why it exists, and one test. It is not more beautiful. It is checkable, and the version that ships to customers should be the checkable one.

Field note

The character plane is not a style guide with delusions of grandeur: structure/em-dash, structure/curly-quote, and structure/special-character exist because each of those marks hides meaning from a tier that parses ASCII English, and every figure above is re-run against the real checker in CI on each commit. The same "clean it before you can read it" order shows up in the voice-agent teardown, where the decorative marks were being read aloud to customers. And the hedges in §3 are the first item in say what you mean, for the same reason: a rule the model may skip is not a rule.

FAQCommon questions

Is an AI-generated system prompt good enough to ship?
As a first draft, yes; as a spec, not without a pass. A generated prompt is fluent, which is the problem: it reads as finished. The draft in this teardown carried twelve blocking errors before anyone looked at its logic, and the real defect (two length rules that cannot both hold) only became provable after the typography was swept and the hedges were committed to modals. Treat the generated text as raw material and run it through a checker before it reaches a customer.
Why do em-dashes and emoji matter in a system prompt?
Two reasons, and only one of them is taste. The model mirrors prompt decoration into its output, so an em-dash in the prompt buys you em-dashes in customer replies. More importantly, the marks hide meaning from the tiers that parse English: a curly apostrophe means a possession is invisible to the consistency checker, and a written-out bound like at most 3 is provable by the solver while the math symbol version lowers with no bound at all. The typography is not the bug, it is what stops you seeing the bug.
How do I clean up a system prompt a model wrote for me?
Four passes, in this order. Sweep the character plane first, so the checker can read the file: plain hyphens, straight quotes, ASCII bullets, bounds written in English. Then commit every hedge to a modal, because try to and should probably are not rules. Then finish every conditional, so a line that starts with when or if actually says what to do. Only then are the remaining diagnostics about logic, and that is where the real conflicts surface.
Why did new errors appear after I fixed the ones the checker reported?
Because the checker works in tiers and the early ones gate the later ones. An unparseable line cannot be handed to the solver, so a numeric or logical conflict inside it is not missed, it is unreachable. Clean the structure and those lines become statements, the statements reach the solver, and conflicts that were always in the file finally get proven. A rising error count after a cleanup pass is progress: the file is now legible enough to be wrong out loud.
∿ washed up Jul 25, 2026 ∿