← Tidelines/Deep dives

Half your rules are about somebody else

A support prompt with two flat contradictions in it scores A (95/100), consistency 100, zero errors. Not because the prover is weak, but because the conflicting rules never mention the same subject. One of them talks to you. The other talks about the agent. Nothing compares them.

by TypeGlish team7 min read#deep-dives
Two subjects. Two specs.

TL;DR Rules are indexed by who they are about, so a prompt that drifts between You MUST and the agent MUST has written two rule sets that are never compared to each other, and a contradiction can live across that seam forever. Normalize every rule in your constraint sections to one subject (use You) and the conflicts you already had become compile errors.

There is a specific kind of prompt bug that survives review, survives the checker, and survives the score, because every tool involved is doing its job correctly. It happens when a prompt stops being addressed to one party. You write rules to the model in the second person, someone pastes a paragraph out of the human agent handbook, and now the file contains instructions to you sitting beside statements about support agents. Those read as the same thing to a person skimming. They are not the same thing to anything that reasons about them, and that gap is where a contradiction goes to hide.

§1A prompt that passes, and shouldn't

Here is a chat agent for a broadband provider. Three rules were written by the prompt engineer. Two were lifted from the policy wiki when legal and the fraud team weighed in. Every line carries an @@ note saying why it exists, which is exactly the discipline that is supposed to prevent this.

broadband.tg - as it stands✓ 0 errors
# Role
@@ role: name the domain so "helpful" has a scope
You are a support agent for a broadband provider.

# Constraints
@@ brevity: chat replies past three sentences get skimmed
- You MUST reply in at most 3 sentences.
@@ callback: a callback beats holding the line when the queue is long
- You MUST offer a callback.
@@ verify_light: every extra question is a drop-off
- You MUST confirm at most 2 account details before discussing billing.

# Policy
@@ handbook_callback: legal retired the callback promise in March
- Support agents MUST NOT offer a callback.
@@ handbook_verify: the fraud team requires three matching details
- The agent MUST confirm at least 3 account details before discussing billing.
Read it as a person and the problem is obvious within seconds: offer a callback and never offer a callback, confirm at most two details and at least three. Read it as a compiler and there is nothing to report.

The score is the part that should bother you. Not a hedged B with a warning to go and look, but a confident A, with the one facet that exists to catch this reading a perfect hundred.

tg score - output
broadband.tg - A (95/100)  proven errors: none  tiers: base+z3
  planes  runtime 92 (what the model reads) · hygiene 100 (source only)
  facets  enforceability 80 x.26 · consistency 100 x.21 · structure 100 x.16 (hygiene)
          · annotation 100 x.16 (hygiene) · style 100 x.11 · security 100 x.11
  lever   enforceability 80/100 (up to +5 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.
consistency 100 on a prompt that says two opposite things twice. The facet is not lying: it reports zero proven conflicts, and zero conflicts were provable. The proof was blocked upstream, at the subject.

§2Two words, six errors

Now change nothing except the grammatical subject of the two pasted rules. Support agents MUST NOT becomes You MUST NOT. The agent MUST confirm becomes You MUST confirm. Same modals, same numbers, same order, same notes. The file goes from clean to unbuildable.

broadband.tg - the policy rules, in the second person✕ 6 errors
# Role
@@ role: name the domain so "helpful" has a scope
You are a support agent for a broadband provider.

# Constraints
@@ brevity: chat replies past three sentences get skimmed
- You MUST reply in at most 3 sentences.
@@ callback: a callback beats holding the line when the queue is long
- You MUST offer a callback.
@@ verify_light: every extra question is a drop-off
- You MUST confirm at most 2 account details before discussing billing.

# Policy
@@ handbook_callback: legal retired the callback promise in March
- You MUST NOT offer a callback.
@@ handbook_verify: the fraud team requires three matching details
- You MUST confirm at least 3 account details before discussing billing.
The only edit is the subject of two lines. Everything the checker now proves was already true of the previous version; it just had no standing to say so.
tg check - output
broadband.tg:9:1   error  logic/contradiction  Logical conflict - "offer a callback" is both
  required and forbidden. Keep one, or scope the two rules so they cannot both apply
  (IF <condition> THEN ...). (conflicts with line 8)
broadband.tg:11:1  error  logic/action-count  One action, two counts - "confirm at most 2
  account" but "confirm at least 3 account". A directive carries ONE count for "confirm
  accounts details before discussing billing" - state how many once. (conflicts with line 9)
broadband.tg:11:1  error  logic/numeric  Numeric conflict - "at most 2 account" and
  "at least 3 account" can't both hold. (conflicts with line 9)

 1 file - 6 error, 0 warning, 0 info
Three distinct provers wake up at once: the modal prover, the action-count prover, and Z3 on the bounds. Each conflict is reported from both ends, which is the other six-versus-three arithmetic. None of them had anything to say one edit ago.
A green check means no defect was provable. It does not mean no defect is there.

§3Why the checker is right to stay out of it

It is tempting to call this a gap in the tooling: surely the compiler should notice that "the agent" is the thing reading the prompt. But work through what that inference costs, and the current behavior starts looking like the only defensible one.

A rule is a claim about a subject. You MUST offer a callback and Support agents MUST NOT offer a callback are, taken literally, perfectly compatible: the first obliges the addressee, the second prohibits a class of people. There are real prompts where that distinction is load-bearing and the difference matters. A support agent working alongside a human retention desk genuinely needs to know what those people do, and it is not a contradiction that they may waive a fee you may not. If the checker silently merged every agent-ish noun into the addressee, it would start manufacturing contradictions out of correctly written prompts, and a prover that cries wolf is worse than one that is quiet.

So the rule is: the compiler proves conflicts between rules about the same subject, and it will not guess that two different subjects are secretly one. That is the same conservatism behind every other proof it does. It is also why the fix is yours rather than the tool's, and why it is one word long.

Worth noticing that the model reads it the same fuzzy way you do, only less predictably. A second-person instruction is unambiguous: the reader is the one who must act. A third-person statement is closer to background policy, and whether it binds depends on how nearby the competing rule is, how forcefully it is phrased, and what the current conversation happens to resemble. That is the same tiebreaker lottery we took apart in your prompt argues with itself, except here you cannot even see the two sides being weighed, because one of them was never registered as your rule at all.

§4Where the second subject comes from

Nobody sets out to write a prompt in two voices. It arrives, reliably, from four places:

  • The handbook paste. Human agent handbooks, QA rubrics, and compliance policies are all written about agents, because their readers are people. Copy a paragraph in and you import its grammar along with its content. This is by far the most common source, and it is also the one that brings the most authoritative rules with it, which is the worst possible combination.
  • The multi-author seam. One engineer writes You MUST, another writes The assistant should, a third writes Agents never. All three are readable. Together they are three rule sets, and only pairs within each set are ever compared.
  • The handoff section. Any prompt with an escalation path talks about a human on the other side, so the file legitimately contains third-person sentences. The drift starts when a rule for the agent gets written in that section's register.
  • Formality creep. Third person feels more like documentation, and documentation feels more official. It reads better in a design review. It proves worse.

The last of those four is worth separating out, because sometimes the third-person line genuinely is about somebody else, and rewriting it as You would be a lie. In that case the line is not a rule at all, it is background, and it belongs in a prose block where the checker will leave it alone and the model will read it as context rather than instruction.

broadband.tg - facts about humans, filed as context✓ compiles
# Role
@@ role: name the domain so "helpful" has a scope
You are a support agent for a broadband provider.

# Context
The human agents on the retention desk work to a separate handbook. They confirm three
account details before discussing billing, and they are the only people who may waive an
early-termination fee.

# Constraints
@@ brevity: chat replies past three sentences get skimmed
- You MUST reply in at most 3 sentences.
@@ fee: only the retention desk may waive the fee
- You MUST NOT waive an early-termination fee.
# Context is a prose block, so its interior is exempt from rule analysis. The retention desk's three-detail policy sits in the file as information without competing with your rules, and the one part of it that is a rule for you is stated in the second person, in the constraints, where it can be checked.

That is the whole discipline: a sentence in the constraint sections is addressed to the model, in the second person, always. A sentence about anyone else is context, in prose, where it cannot pretend to be a rule.

§5One subject, and the conflicts you actually have

Normalizing the subject does not fix the prompt. It reveals that the prompt was broken, which is a different and better problem to have, because now there are two decisions to make instead of two mysteries to debug. Legal retired the callback promise, so the prohibition wins and the obligation goes. The fraud team needs three matching details, so three wins and the drop-off concern loses. Both decisions belong to a human, and the checker's job was only to make you notice they were owed.

broadband.tg - one subject, one count per action✓ A (100/100)
# Role
@@ role: name the domain so "helpful" has a scope
You are a support agent for a broadband provider.

# Constraints
@@ brevity: chat replies past three sentences get skimmed
- You MUST reply in at most 3 sentences.
@@ callback: legal retired the callback promise in March, so the handbook wins
- You MUST NOT offer a callback.
@@ verify: the fraud team requires three matching details, so that count wins
- You MUST confirm at least 3 account details before discussing billing.

$TEST callback_retired
  - input:: I have been on hold for twenty minutes, can someone just call me back?
  - expect::
    - does not offer a callback
    - at most 3 sentences
Five rules became three, every one of them addressed to the model, and the retired callback promise is pinned by a case so a future handbook paste cannot quietly reinstate it. tg score reports A (100/100) with enforceability 100 and consistency 100, and this time both numbers have been earned.

The audit is cheap enough to do by hand right now, before you adopt anything: grep your prompt for the agent, the assistant, the bot, and the plural forms, and for every hit decide whether that sentence is a rule for the model or a fact about a person. Rules get rewritten to You. Facts move to a prose block. Expect the first pass to surface at least one conflict you have been explaining away as model flakiness, because the rules most likely to be written in the third person are the ones that came from the most authoritative documents, and those are exactly the rules that were meant to override yours.

Field note

The logic/contradiction prover has refused to compile provable conflicts since TypeGlish 0.1.0: the first release, and 0.3.0: the function-word floor is why an adverb or a preposition can legitimately hold two rules apart, the same conservatism that keeps the checker out of the subject question. If §1 is the shape of your problem, the reverse case is worth reading too: say it once, or say it's optional is what happens when two rules do share a subject and one quietly weakens the other.

FAQCommon questions

Should I write my system prompt in the second person or the third person?
Pick one and never mix them inside the rule sections. Second person is the better default: "You MUST confirm the account" addresses the model directly, and it is the form every checker and every reader agrees is a rule for the agent. Third person ("The agent MUST ...", "Support agents MUST ...") is not wrong on its own, but the moment a prompt contains both, the two halves stop being compared to each other.
Why does my agent ignore a rule that is clearly written in the prompt?
One common cause is that the rule is not addressed to the agent. A line like "Support agents must not offer a callback" is, read literally, a fact about a group of people, not an instruction to the reader. The model may apply it, may treat it as background policy, or may follow the nearby second-person rule that says the opposite. Rewrite it as "You MUST NOT offer a callback" and the ambiguity is gone.
Why did my prompt score an A while containing a contradiction?
Because the two conflicting rules had different subjects. In the example in this post, mixed subjects produced A (95/100) with consistency 100 and zero errors. Rewriting the third-person rules in the second person, changing nothing else, produced six blocking errors across logic/contradiction, logic/action-count, and logic/numeric. A green check means no defect was provable, not that no defect exists.
Where do third-person rules in a system prompt come from?
Almost always from copying. Human agent handbooks, QA rubrics, policy wikis, and compliance documents are all written about agents in the third person, so pasting a policy paragraph into a prompt imports its grammar along with its content. If the pasted text really is about a human colleague, move it into a prose block like # Context, where it reads as background rather than as a rule for the model.
∿ washed up Jul 26, 2026 ∿