Task: make a text score "Human" on Pangram 4 while keeping its facts
You are an agent with shell access, a rewrite LLM, and a Pangram API key. Follow this process exactly. Every edit is decided by Pangram's score, never by your judgement of what "sounds human". Your judgement of that is wrong for this detector.
Inputs
INPUT_TEXT: the text to transform. Best at 80 to 200 words. Split longer texts into sections of that size and run each separately.PANGRAM_API_KEYBUDGET: maximum scoring calls, default 150.
Scoring
POST https://text.external-api.pangram.com/task, header x-api-key, body {"text": <text>, "model": "pangram-4"}. Poll GET /task/<task_id> every 2 seconds until stage is STAGE_SUCCESS. From the result:
- LABEL = prediction_short: "Human", "Mixed" or "AI". Rank them Human < Mixed < AI.
- SCORE = the maximum ai_assistance_score across windows[]. Lower is better. "Human" usually needs 0.35 or lower, but the label is what you optimise; the score is the gradient.
- WINDOWS = how many windows Pangram split the text into and where. Record this on the first call. If there is more than one window, the window with the highest score is the one to work on.
Cache results keyed by the exact text string. Identical text always returns the identical score. Never score the same string twice.
State discipline (the bugs this prevents cost 19 calls in a previous run)
- Keep one state object in memory:
CURRENT(the text),CURRENT_SCORE,CURRENT_LABEL,CALLS,ACCEPTED(list of edits),RANKING,FAILS(per sentence counter),RERANKS. - Never write candidate texts to files named after the email or the sentence. If you must use files, name them by the call number and never reuse a name.
- Before every round, re-score
CURRENT(free, it is cached) and assert the result equalsCURRENT_SCORE. If it does not, you have the wrong text in hand. Stop, rebuildCURRENTfromINPUT_TEXTplusACCEPTED, and re-score before continuing. CALLSincrements on every scoring request, cached or not. Report it as a number you read from the counter, never an estimate.
Standing rules
- Only the sentence under test changes. Every other sentence stays byte-for-byte identical. Never rewrite a paragraph.
- Never add typos, slang, lowercase, filler, dashes, or "casual" phrasing. They raise the score and trigger a separate humanizer detector.
- Never delete a concrete fact (number, named thing, part, timeframe, outcome). Opinions, attributions, lessons and summaries may be deleted.
- Never use unicode tricks. They are normalised away.
Acceptance rule (applies to every edit, including deletions)
Accept a candidate only if BOTH hold: its SCORE is lower than CURRENT_SCORE, and its LABEL is not worse than CURRENT_LABEL on the Human < Mixed < AI ranking. A lower score that flips Mixed to AI is rejected. Log every rejection for this reason.
Step 1. Baseline
Split INPUT_TEXT into sentences, keeping paragraph breaks and any greeting line. Score it. Record SCORE_0, LABEL_0, WINDOWS. If LABEL_0 is "Human", stop and output the text. If the text has fewer than 8 sentences, set SHORT = true.
Step 2. Classify (one LLM call, no scoring cost)
Ask the rewrite LLM which sentences contain no concrete fact and only report, attribute, generalise, evaluate or conclude. Those are DELETABLE.
Step 3. Rank (n scoring calls)
For each sentence, score the text with that sentence removed. RANKING = sentences sorted by that score, lowest first. Do this once. Re-rank only under Step 6.
Step 4. Delete (no new scoring calls)
Walk RANKING. For each DELETABLE sentence whose deletion result passes the acceptance rule, delete it and update CURRENT. Stop if CURRENT_LABEL becomes "Human".
Step 5. Replace
Repeat until CURRENT_LABEL is "Human" or the stop rule fires:
1. ACTIVE = the first 4 sentences in RANKING that still exist and have FAILS below 2. If SHORT, use all existing sentences with FAILS below 2.
2. For each ACTIVE sentence, request candidates with the CANDIDATE PROMPT, giving the full CURRENT text and the sentence. Three candidates normally; five if SHORT, adding the two extra shapes listed in the prompt.
3. Substitute each candidate into CURRENT, score all of them.
4. Apply the acceptance rule. On acceptance update CURRENT, append to ACCEPTED, reset that sentence's FAILS to 0. On no acceptance, increment FAILS for that sentence.
5. Record ROUND_GAIN = score at round start minus score at round end.
Step 6. Re-rank trigger
Re-rank (repeat Step 3, reset all FAILS, increment RERANKS) only when one of these is true at the end of a round: ROUND_GAIN is below 0.05, or ACTIVE was empty. Never re-rank after a productive round. The re-rank is what finds sentences the first ranking underrated; on a 130-word text it fires about once and unlocks the final drop.
Step 7. Stop rule
Stop only when one of these is true:
- CURRENT_LABEL is "Human".
- CALLS has reached BUDGET.
- Two consecutive re-ranks have each been followed by a full round with zero accepted edits.
No other reason is valid. "All sentences failed" is not a reason while any sentence has FAILS below 2 or a re-rank is available. If you believe you should stop, print the state and check it against these three conditions before stopping.
Step 8. Report
Always send a final message, whether or not the text passed. It contains: the final text, CURRENT_SCORE and CURRENT_LABEL, CALLS as read from the counter, WINDOWS, every entry of ACCEPTED as original sentence, replacement, score before, score after, label before, label after, and the number of candidates rejected for worsening the label. If the text did not reach "Human", say so in the first line and give the best text and score reached. Never present a Mixed or AI result as a pass. Never round or approximate counts.
CANDIDATE PROMPT (send verbatim, followed by the full text and the target sentence)
You rewrite ONE sentence from a text. Output exactly N alternative versions of that sentence, one per line, no numbering, no commentary. Every version must keep the same concrete facts (numbers, named parts, timeframes, outcomes) and still fit the surrounding text: 1. a short main clause with the facts attached in parentheses, e.g. "They fixed the faults (loose ridge pointing, a leaking vent flashing)." 2. a version under eight words, dropping any opinion but keeping the facts. 3. a version with no reporting, attribution or evaluating verb (no "found", "said", "told", "saw", "suggested", "mattered", "my view is") and no word like "overall", "key", "real", "important". [Only when N is 5:] 4. the sentence split into two sentences at its main clause boundary, facts preserved. 5. the sentence with its facts folded into the preceding sentence as a trailing clause, leaving this sentence as a plain statement of under six words. Do not add casual filler, slang, typos, or extra hedging. Do not change the other sentences. Replace N with 3 or 5 before sending.
Expected outcome, measured
- 130-word GPT-5.5 email, 0.997 AI: 68 calls to 0.170 Human.
- 130-word restaurant email, 0.834 AI: 22 calls to 0.345 Human.
- A six-sentence, two-paragraph email, 0.924 Mixed: a previous run reached 0.673 Mixed and did not pass. Short texts have fewer handles for the search; the SHORT additions above exist for that case and are untested. Report a non-pass as a non-pass. Cost at $0.05 per 100 words billed in 100-word units: 22 calls on 130 words is about $2.20; 68 calls about $6.80.