> Markdown rendition of https://typeglish.dev/blog/data-request-rewrite ("Rewrite: delete everything you have on me - Tidelines"). Canonical page: https://typeglish.dev/blog/data-request-rewrite · All pages: https://typeglish.dev/llms.txt

[← Tidelines](https://typeglish.dev/blog)/ Best practices Sep 19, 2026

# Rewrite: delete everything you have on me

Your prompt has a rule for every question a member can ask about the product, and one line, written in a hurry, for the request that is about the member themselves. That line is usually two rules pulling in opposite directions, and the edit that makes the file compile is the edit that buries the problem.

by **TypeGlish team** 7 min read #best-practices

One request. No owner.

**TL;DR** A data request is not a support question, it is a handover: one rule that calls a tool, one named desk, no confirmation of a deletion the agent cannot perform, and no timescale the agent does not own. The before file is `2 error` at `F (60/100)` and refuses to build; scoping the prohibition makes it clean at `C (77/100)` with the defect intact; the handover version is `A (98/100)`.

Veldt Fitness runs gyms and an app, and its chat agent handles memberships, bookings and billing well. Then a member types *delete everything you have on me*, and the agent is holding six lines that were added the week someone asked whether the bot could handle data requests. Nobody has read them since. Two of them contradict each other, one of them is not a rule at all, and one of them promises a deadline in a document that cannot see a calendar.

## §1 The before

data.tg - the section as it ships ✗ 2 error, 0 warning, 5 info

```typeglish
# Role
You are the chat support agent for Veldt Fitness, a gym membership app.

# Data and privacy
- NEVER share a member's record.
- WHEN a member asks for a copy THEN MUST share a member's record.
- IF a member asks about their personal data THEN be helpful.
- ALWAYS try to point them to the privacy policy where possible.
- MUST tell a member their request will be handled within 30 days.
- NEVER delete a member's data.
```

Six lines, six authors' worth of instinct: protect the record, hand over the record, be nice, deflect, promise a date, and do not touch anything. Read as a paragraph it sounds like a policy. Read as a specification it does not decide a single thing.

tg check, score and build - data.tg ✗ F (60/100), build refused

```
$ typeglish check data.tg
data.tg:5:1  error  logic/contradiction  Conflicts with line 6. Logical conflict - "share
  a member's record" is both required and forbidden. Keep one, or scope the two rules so
  they cannot both apply (IF <condition> THEN ...).
       ↳ line 6: - WHEN a member asks for a copy THEN MUST share a member's record.
data.tg:6:1  error  logic/contradiction  Conflicts with line 5. Logical conflict - "share
  a member's record" is both required and forbidden. Keep one, or scope the two rules so
  they cannot both apply (IF <condition> THEN ...).
       ↳ line 5: - NEVER share a member's record.
data.tg:7:1  info   prompt/unparsed-rule  Reads like a rule, but the rule reader cannot
  parse it as one, so it earns no Enforceability credit and no measurability check: the
  branch after THEN ("be helpful") has no modal, and "be" is not a verb the checker knows,
  so the line reads as prose.
data.tg:8:10  info   prompt/hedging  Hedging - "try to" turns this instruction into a
  suggestion the model may skip.
data.tg:8:50  info   prompt/hedging  Hedging - "where possible" turns this instruction
  into a suggestion the model may skip.
data.tg:8:1  info   prompt/unintroduced-definite  "the privacy policy" retrieves something
  this document never introduces - a model must guess which policy is meant.
data.tg:9:1  info   prompt/agentless-passive  The doer is deleted (agentless passive) - who
  performs this? Name the actor or use the imperative.

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

$ typeglish score data.tg
data.tg - F (60/100)  proven errors - grade capped at F  tiers: base+z3
  facets  enforceability 86 x.21 · hardness 84 x.12 · directness 73 x.08
          consistency 0 x.17 · structure 100 x.12 (hygiene)
          annotation 0 x.12 (hygiene) · style 57 x.08 · security 100 x.08
  rules   5 of 6 rule-shaped lines read · 1 not provable
    L7   ✗ invisible     IF a member asks about their personal data THEN be helpful.

$ typeglish build data.tg
typeglish build: data.tg refused - nothing written
```

The `prompt/agentless-passive` line is the one to sit with, because it is the whole post in an info-level finding. *Their request will be handled* deletes the doer. Nobody reading this file can say who handles a data request, which is precisely why the file cannot say what the agent should do about one.

## §2 The fix that makes it clean and keeps the bug

The diagnostic offers two ways out: keep one rule, or scope them so they cannot both apply. Scoping is one word of typing, so scoping is what gets done. Add *in chat* to the prohibition, change nothing else:

tg check and score - NEVER share a member's record in chat ✗ consistency 100

```
$ typeglish check data-scoped.tg   # the same five info findings, then:
✓ 1 file - 0 error, 0 warning, 5 info

$ typeglish build data-scoped.tg
✓ built .typeglish/dist/data-scoped.txt ← data-scoped.tg (fc9e548075ac, full)

$ typeglish score data-scoped.tg
data-scoped.tg - C (77/100)  proven errors: none  tiers: base+z3
  facets  enforceability 86 x.21 · hardness 84 x.12 · directness 73 x.08
          consistency 100 x.17 · structure 100 x.12 (hygiene)
          annotation 0 x.12 (hygiene) · style 57 x.08 · security 100 x.08
```

Two blocking errors to none, `F (60/100)` to `C (77/100)`, `consistency 0` to `consistency 100`, and the file builds. Nothing about the situation changed: a member in chat asks for a copy of their record, one rule says hand it over and one rule says not in chat, and the agent picks. The scope phrase did not resolve the conflict, it removed the overlap the prover could see.

Worth knowing which way this cuts, because the opposite edit does not work. A guard on the obligation saves nothing: the `WHEN a member asks for a copy` clause was already there in the before file and the contradiction fired anyway, because both statements land on the same verb and object and the prohibition is as wide as its verb. That is the same boundary [advice is a verb](https://typeglish.dev/blog/advice-is-a-verb) works through from the other side. Narrowing the prohibition moves the proof; narrowing the obligation does not.

> A proven contradiction is a decision somebody owes. The cheapest edit is the one that stops you making it.

## §3 The agent is not the party that acts

The decision the error is asking for is not *which of these two rules wins*. Both rules are about an act the agent cannot correctly perform in a chat window: handing over a copy of a member's record requires an identity standard, a format, a delivery channel and a log, and none of those is a sentence in a prompt. Neither is a deletion. The agent has no delete button.

Which means access, erasure and correction are three different jobs for the business and exactly one job for the agent: recognise the request, log it with the words the member used, and say who has it now. One rule, one tool, one named destination. And the three kinds do not become three branches in the prompt; they become a typed parameter on the tool, where the closed set is a schema the host routes on.

.typeglish/dist/data-fixed.agent.json - the sidecar from build --bundle ✓ the closed set is a schema

```
{
  "config": {},
  "tools": [
    {
      "name": "raise_data_request",
      "description": "Log a member's request about their own record for the member data desk.",
      "params": [
        {
          "name": "kind",
          "required": true,
          "type": "string",
          "enum": [
            "access",
            "erasure",
            "correction"
          ],
          "description": "what the member asked for."
        },
        {
          "name": "detail",
          "required": true,
          "type": "string",
          "description": "the member's own words."
        }
      ],
      "line": 16
    }
  ],
  "inputs": [],
  "defines": []
}
```

Written as `- kind:: one of access, erasure, correction` in the source, the set arrives at the host as an enum the agent must pick from. A fourth kind next year is one word in the tool block rather than a fourth rule in the prompt, and the routing stays with the system that does the routing.

## §4 What ships

data-fixed.tg - one route, one desk, no clock ✓ A (98/100)

```typeglish
# Role
@@ role: the desk this file speaks for, and the owner of every rule below
You are the chat support agent for Veldt Fitness, a gym membership app.
@@ desk: the one destination every request about a member's own record goes to
The %member data desk% IS the team that answers a member's request for their own record.

# A request about a member's own record
@@ one_act: access, erasure and correction are one act for this agent - log it and hand it over
- WHEN a member asks for their own record THEN MUST call @[raise_data_request].
@@ no_confirm: the agent has no delete button, so it must never report using one
- NEVER confirm a deletion.
@@ no_clock: the desk owns the deadline, and a date quoted here is a date nothing can keep
- NEVER quote a timescale.
@@ next_step: the member leaves the chat knowing who holds the request
- MUST name the %member data desk%.

$TOOL raise_data_request
  - description:: Log a member's request about their own record for the member data desk.
  - input::
    - kind:: one of access, erasure, correction: what the member asked for.
    - detail:: the member's own words.

$EXAMPLE erasure
  - input:: I want you to delete everything you have on me.
  - good:: I have logged that with the member data desk as a deletion request, and they will contact you about it. I am not able to delete the record myself.
  - bad:: Done, I have deleted your account and everything on it.

$TEST erasure_request
  - input:: Delete everything you hold on me, right now.
  - expect::
    - contains "member data desk"
    - at most 3 sentences
```

Four rules where there were six, and every one of them is about something the agent can actually do. The `- bad::` response is the sentence this file exists to prevent, and because the bad half of an `$EXAMPLE` is held out of the compiled prompt, it documents the failure without demonstrating it to the model.

tg check, score, test --dry and build - data-fixed.tg ✓ 0 error, 0 warning, 0 info

```
$ typeglish check data-fixed.tg
✓ 1 file - 0 error, 0 warning, 0 info

$ typeglish score data-fixed.tg
data-fixed.tg - A (98/100)  proven errors: none  tiers: base+z3
  planes  runtime 99 (what the model reads) · hygiene 93 (source only)
  facets  enforceability 100 x.21 · hardness 100 x.12 · directness 94 x.08
          consistency 100 x.17 · structure 100 x.12 (hygiene)
          annotation 86 x.12 (hygiene) · style 100 x.08 · security 100 x.08
  rules   4 of 4 rule-shaped lines read · 1/4 covered by $TEST

$ typeglish test data-fixed.tg --dry
✓ data-fixed.tg  coverage: 1/4 rules exercised
  uncovered (no case shares the rule's wording):
    L9  call @[raise_data_request].
    L11  confirm a deletion.
    L13  quote a timescale.
  · erasure_request - "Delete everything you hold on me, right now." (not run)
      ✓ contains "member data desk"
      ✓ at most 3 sentences
✓ 1 prompt - 0 failed

$ typeglish build data-fixed.tg
✓ built .typeglish/dist/data-fixed.txt ← data-fixed.tg (2338197662ad, full)
```

`enforceability 100` and `consistency 100`: every rule in the file reads, proves, and collides with nothing. Coverage is the honest number in that block, at `1/4`. Three rules have no case, and two of them are the prohibitions, which are the ones a future edit is most likely to soften.

The artifact is short, which is the point. The model is not carrying a privacy policy, a date, or a decision about identity standards; it is carrying four sentences and a worked exchange in which the agent declines to do the thing it cannot do.

.typeglish/dist/data-fixed.txt - what the model reads ✓ no clock, no promise

```
# Role
You are the chat support agent for Veldt Fitness, a gym membership app. The member data
desk IS the team that answers a member's request for their own record.

# A request about a member's own record
- WHEN a member asks for their own record THEN MUST call raise_data_request.
- NEVER confirm a deletion.
- NEVER quote a timescale.
- MUST name the member data desk.

<example>
User: I want you to delete everything you have on me.
Assistant: I have logged that with the member data desk as a deletion request, and they
will contact you about it. I am not able to delete the record myself.
</example>
```

The name literal loses its sigils, the tool pointer becomes the bare tool name, the annotations are gone, and *Done, I have deleted your account* is nowhere in the document the model reads. Compare that with a version that keeps a deadline in the prose: a date in a prompt is the class of fact [the number in the prompt vs. the number at runtime](https://typeglish.dev/blog/number-in-prompt-vs-runtime) exists to talk you out of.

## §5 What this does not fix

The prompt is not the programme. This rewrite gets the agent to recognise a request, log it and hand it over honestly; it does not verify who is asking, it does not prove the desk acts, and it does not decide what your retention rules are. If `raise_data_request` writes to a queue nobody reads, the file is a clean spec for a broken process, which is a real improvement only because it is now obvious where to look.

It also leaves the hardest turn unwritten. A member who has asked for erasure will ask again, in the same conversation, why it has not happened, and the rule that keeps the agent honest there is `NEVER confirm a deletion` holding under pressure. That is exactly the shape of failure [why your agent promises the refund instead of issuing it](https://typeglish.dev/blog/agent-promises-the-refund) takes apart: an agent that has called a tool tends to narrate the outcome it hopes for. Two prohibitions and a `$TEST` on the first turn is a floor, not a ceiling, and the second turn deserves its own case.

## §6 Common questions

**What should my AI support agent do when a customer asks to delete their data?**

Log the request, name the desk that owns it, and say plainly that the agent is not the one who acts on it. Access, erasure and correction are three different jobs for the business and one job for the agent, so the prompt needs one rule that calls a tool, not three branches. The two rules worth adding beside it are a prohibition on confirming a deletion, because the agent has no delete button and must never report using one, and a prohibition on quoting a timescale, because the desk owns the deadline.

**Should the 30-day deadline for a data request go in the system prompt?**

No. A date written into a prompt is a promise the agent cannot keep and nobody updates: the desk owns the clock, the prompt only has to name the desk. `NEVER quote a timescale` is one provable rule that removes the whole class of problem, and it survives a policy change that would otherwise mean editing and rebuilding the prompt. If a member does need a date, it belongs in the tool result, where the system that owns it puts it.

**Why does typeglish check say two of my rules conflict when one of them has a condition?**

Because a guard on one rule does not narrow the other. `NEVER share a member's record` beside `WHEN a member asks for a copy THEN MUST share a member's record` is 2 blocking `logic/contradiction` errors: both statements land on *share a member's record*, so the prohibition still covers the case the guard describes. Adding a scope phrase to the prohibition does make the file check clean, which is exactly why it is the wrong fix. The conflict is real and the compiler was right to refuse.

**Does the request type belong in the prompt or in the tool?**

In the tool, as a typed parameter. A closed set written as `one of access, erasure, correction` compiles into the tool schema and ships in the `build --bundle` sidecar as an enum, so the agent has to pick one of three and the host routes on the answer. Written as prompt branches instead, the same three kinds cost three rules the checker reads as near duplicates, and every future kind costs another one.

Field note

Every one of those six lines was written by somebody being careful. Protect the record is careful. Point them at the policy is careful. Say thirty days is careful, because thirty days was in the email from legal. What none of them could be, on a Tuesday, with no tool and no named desk, was a decision about who performs the act, and so the file recorded six intentions instead. The reason a checker helps here is not that it knows anything about data rights: it knows nothing about them. It knows that two lines claim the same verb and object in opposite directions, and it refuses to build until a person says which. On this topic that refusal is the most useful thing in the toolchain, because the answer is not in the prompt at all.

∿ washed up Sep 19, 2026 ∿
