Agentic AI

Why Generating a Podcast Script Is Harder Than Generating Code

Two grader slots side by side: the one labelled CODE holds an instrument, the one labelled PROSE is empty

Same model. Same harness. Same tracing, same caching, same retry discipline.

Point it at a codebase and it converges. Point it at a research paper and ask for a few minutes of spoken narration, and it does not.

We have been running both loops inside PaperCast since the summer. The gap is not model capability and it is not prompt craft. It is one structural thing that code has and prose does not.

The Short Version

A compiler is a free reward model.

When an agent writes code, the environment grades it instantly, perfectly, and at zero marginal cost. Type errors, failing tests, a non-zero exit code — each is a ground-truth label that arrives in under a second and never disagrees with itself. The agent can generate, get graded, and revise over and over before a human looks at anything.

When an agent writes a podcast script, nothing grades it. There is no test suite for “this paragraph sounds like a person explaining something.” So you write the grader yourself, by hand, in code.

That hand-written grader is the thing that breaks. What follows is two months of watching it break in the same places, and of fixes that were each correct and each not enough.

The Same Defect, Twice

Early on, a job narrating a review paper shipped with most of its sentences opening on the source itself. Translated from the Mandarin, it read:

This review describes ...
This review reports ...
The paper's authors state ...

The slides faithfully gave every one of them the same prefix, because the cuts were downstream of the prose. The diagnosis was good: two prompt rules had collided. One asked that every fact carry its owner. But in a review, the owner of nearly every fact is the review — so “carry the owner” degenerated into one universal frame.

The important detail was not the defect. It was that our checker returned nothing on that draft. It passed on the first attempt, so the revision loop never ran. The one signal that did fire pointed at the wrong edit entirely.

So we built a detector for it: sentences opening on source-plus-reporting-verb, flagged when enough of them share one owner. Careful thresholds, so that several different parties each named once — which is exactly what good attribution looks like — would not trip it. Tests, a prompt rule to match, shipped.

Fifteen days later, a financial-news job narrating an interview came back like this:

The article's central point is ...
The article also explains ...
The article therefore stresses ...
The article also mentions ...
The interview closes on a question ...

Same defect. Same blind spot. Our purpose-built detector saw nothing, because it required a determiner — the equivalent of “this article” — and newsroom Mandarin simply does not write it that way. The rule had been fitted to the exact phrasing of the first failure and it recognised nothing else.

One defect, two sources, two weeks apart, and a detector built specifically to catch it that could not see the second one.

The Fix That Proved the Problem

We had also written a plain-English prompt rule for this, in the financial-news style document:

Do not open consecutive sentences with “according to reports” — repeated attribution reads as evasion, not rigour.

The model complied exactly. It stopped writing “according to reports” and started writing “the article” instead.

That is Goodhart’s law in a single hop. The rule named a token; the defect was a habit. We banned the token and the habit found another one.

So we widened the detector. Added the bare nouns, added the reporting verbs the list was missing, added a new detector for a second problem in the same script — sentences spent entirely on what the source could not establish, the “not independently audited, not a verifiable forecast” register that turns a briefing into a compliance notice. Re-run against the failing script, it caught everything. Tests green, committed.

That same afternoon, the person who owns the product sent back an example of what good output should look like. We ran it through the checker we had just shipped.

The new detector fired on it, at the highest severity, on two of its best sentences. Translated:

  A high price is not the same as a bubble.
  But paper wealth is not cash.

Those are not hedges. “Is not the same as” is how Mandarin draws a distinction, and drawing distinctions is the entire job of an explainer. We had fitted a regex to one job’s failure and it immediately misclassified the best prose we had.

It got worse on inspection. The same gold example broke our rhetorical-question limit, ran a title well past our character cap, and tripped our banned-hype list on the word “revolutionary” — used correctly, to describe technologies investors perceive that way.

Several of our rules were wrong, and we found out by accident, from a single example someone happened to send us.

A Rule That Was Fixed, Then Compressed Away

The disclaimer problem was not new either. It had been diagnosed properly once before, from an external review of a real generated script: factually disciplined, weak as spoken storytelling. The model had been asked for a population, a comparator, and a causal strength that a manufacturing paper does not have, and it filled the hole with hedges — each defensible alone, together a compliance review.

The fix was genuinely good. It made the qualification budget countable: state the scope once, early, plus at most one further limitation, and only where it changes how a result should be read. Everything else rides inside the wording of the claim. Six hedges are not more accurate than one; past the third the listener stops hearing any of them. A new defect family was added so the reviewer had a name for it.

Two things then quietly undid it, and the second happened the same day the rule was written.

First, the new family was judged by a model, not by a rule — and the model reviewer costs a call per draft, so it ships switched off by default. A defect with a name nobody is paid to look for is a defect with no detector.

Second, and worse: our system prompts had grown long enough to be a latency problem, since a reasoning model spends thinking in proportion to what it holds. So we wrote shortened versions, with an explicit and sensible criterion — keep every rule that changes the output, drop the worked reasoning, the counter-examples, and the detail a model can infer. The short version became the default.

That work landed on the same day the scope rule went into the long document, and “Say the scope once” did not survive the cut. It had a long explanation and a worked pair of good and bad examples attached to it, which made it look exactly like the elaboration the compression was meant to remove. It is a rule that changes the output. It got dropped anyway.

So a rule written that morning never reached the path most jobs actually take.

Nobody could tell, staring at tens of thousands of characters of instruction, which parts were load-bearing. That is not a lapse in judgement. It is the same missing-oracle problem one level up: we had no way to test whether removing a rule made the writing worse, so we compressed on intuition and lost one.

Four days later the hedges came back, in a different genre, and were caught by nothing.

When the Grader’s Vocabulary Is the Limit

A customer once complained about a cover title. Their words, roughly: the title is not wrong, but it describes a general property of the field, and it would fit any paper on the subject.

They were right, and the cause was structural rather than a wording slip. The deck already knew its thesis and threw it away. The job’s own stored summary named exactly the angle the customer wanted. The cover, however, was generated by headlining the script’s first segment — and a first segment is setup, so a faithful headline of it is a general statement about the field by construction. The model titling the cover was never shown what the paper established. It did its job correctly and produced a generic title.

The part worth stealing is what happened at the review layer. Our judge had a rubric listing the ways a cover title fails: fragment, teaser, hook. True-but-generic was not on the list. So the judge picked the nearest available label and proposed a fix — a longer version of the same generic title.

A closed taxonomy bounds what the grader can report. Our defect vocabulary is deliberately closed, for good reasons: an identifier that means two different things ruins any count you take across jobs. But the cost is that a failure with no name is invisible, and the grader will confidently mislabel it as the nearest thing it does have a name for. That is worse than silence, because it generates a plausible instruction to do the wrong thing.

Three Smaller Ones, Same Shape

The loop compared drafts that had been graded differently. To save a model call, the expensive reviewer only ran when the cheap deterministic rules found nothing blocking. So the first draft was read by rules alone, and later drafts by rules and the reviewer — then all of them were ranked against each other. The unread draft looked cheapest, because nobody had looked for its problems. One job shipped an early draft while a later draft’s reviewer had written the user’s exact complaint, word for word, and lost.

The repair call did not have the ban list. For weeks, a rewrite triggered by a banned-word finding was performed without telling the model which words were banned. It could reintroduce one and oscillate until the pass budget ran out. The unit test was green throughout — it proved the instruction string was built, not that anything sent it.

We ban words one observation at a time. A piece of business jargon was recently added to the global default list. It was checked against the existing corpus first, which is more discipline than most such additions get. The check found one real hit. One instance, one permanent global rule — and that is the honest arithmetic behind most of the list.

Why the Rules Overfit

Look at what the quality layer had become by this point:

  • hundreds of lines of deterministic checker
  • dozens of distinct defect families in a closed routing vocabulary
  • word lists running to scores of banned openers, hype terms, and attribution verbs
  • an editorial system prompt longer than most of the scripts it produces

And the corpus all of it was fitted against, on the machine where it was written, was small enough to count on your fingers.

Every entry in every list was added in response to exactly one observed failure. That is not a quality system. That is a hand-written reward model being fitted by gradient descent, one sample at a time, with a human doing the backward pass from memory.

Each individual fix in this post was correct. Read the reasoning behind any of them and it holds up. They were also, every one, insufficient — because a rule fitted to one instance encodes the instance, not the defect. Below a few dozen diverse sources you cannot tell those apart. Not with a better prompt, not with a bigger model, not with a cleverer regex.

The Real Difference: Verifiable vs. Non-Verifiable

The post-training literature has a clean name for this split: tasks with verifiable rewards and tasks without.

Code, math, and structured extraction are verifiable. There is a function that takes an output and returns correct or incorrect, cheaply and deterministically. That function is what makes agentic loops work at all. Generate, grade, revise — the loop is only ever as good as the grader, and for code the grader is free.

Narration, summarization, tone, editorial judgement, “does this explain the mechanism clearly” — none of these are verifiable. The reward has to be learned or judged, and both cost money and both are noisy.

It also explains why chatbot iteration makes the problem worse rather than better. When you paste a paper into a chat window, read the output, and adjust the prompt, your feedback loop has a sample size of one. You are fitting to the example in front of you, with no held-out set, and no memory of the dozen constraints you added for the last dozen examples. The prompt grows monotonically and quality does not. Every practitioner who has tried to write a style guide this way has produced the same artifact: a document that works beautifully on the last three inputs and unpredictably on everything else.

What the Research Says

This problem is better studied than it looks, and the most useful paper is not about prompting at all.

Shankar et al., “Who Validates the Validators?” (EvalGen, UIST 2024) names the core phenomenon: criteria drift. People cannot write the grading rubric up front, because they discover their criteria by grading outputs. The rubric and the outputs co-evolve. Any workflow that asks you to specify quality first is structurally wrong — which is exactly what a long hand-written style document is. The companion SPADE work synthesizes data-quality assertions from prompt version history, which is roughly what PaperCast’s own distillation module does, arrived at independently and by accident.

Automated prompt optimization is a real and maturing field, and the direct answer to “how do I tune a prompt without chatting at it”:

  • DSPy (Khattab et al.) with the MIPROv2 optimizer — searches jointly over instructions and few-shot demonstrations rather than asking you to write either
  • ProTeGi (Pryzant et al., 2023) — “textual gradients”: an LLM critiques failures and you edit the prompt in that direction. This is PaperCast’s own draft-review-revise loop applied one level up, to the prompt instead of the draft
  • TextGrad (Yuksekgonul et al., 2024) — generalizes textual gradients into an autodiff-like framework over text
  • OPRO (Yang et al.) and APE (Zhou et al., 2022) — the LLM proposes new instructions from a trajectory of instruction-and-score pairs
  • GEPA (2025) — reflective prompt evolution, notable for reportedly matching or beating RL-style tuning at far lower rollout cost

Judging, because every optimizer above is search over a metric:

  • MT-Bench / LLM-as-a-judge (Zheng et al., 2023) established the baseline: strong but imperfect agreement with human preference on pairwise comparison, alongside documented position, verbosity, and self-enhancement biases
  • Length-controlled AlpacaEval (Dubois et al., 2024) shows verbosity is a large enough confound that it has to be removed explicitly
  • Prometheus (Kim et al., 2024) and G-Eval — rubric-conditioned scoring with open models

And the direction we find most interesting, because it attacks the “every source is different” problem head-on: per-instance rubrics. OpenAI’s HealthBench (2025) grades each conversation against physician-written criteria specific to that conversation rather than one global rubric. Related work on rubrics-as-rewards extends the idea into training signal. If the thing that varies is the standard, stop hard-coding the standard.

The Claim We’d Make

The optimizer is not the bottleneck. The scorer is.

Hand DSPy or GEPA a metric like our checker and it will do exactly what you asked: optimize the script into something that satisfies your regexes and sounds worse. You will have automated Goodhart’s law. We already saw the manual version when a token ban produced a synonym.

So the work does not disappear. It moves from writing rules to labelling preferences — and that is a much better place for it, because:

  • You cannot reliably write the rulebook. We have now disproved our own several times, sometimes twice for the same defect.
  • You can reliably say “A is better than B” in seconds.
  • Pairwise labels are far less noisy than numeric scores, and a useful batch of them costs one person an afternoon.

What We’re Implementing in PaperCast

In order, because each step is worthless without the one before it.

1. Build the corpus first. A few dozen sources spanning the actual range — papers, interviews, filings, blog posts, short and long — split into a dev set we iterate on freely and a held-out set we look at rarely. This is unglamorous and it is the highest-value item on the list. Every other step multiplies by it. Had it existed, the determiner-shaped hole in our detector would have surfaced the week it was written.

2. Stop discarding the best signal we generate. PaperCast has a human approval gate: the script is shown to a person before any slide is rendered or any audio is paid for. When that person rewrites a draft, they produce a gold pair — model output beside human rewrite — carrying an implicit reason. It is the most valuable data the product makes.

Today the edit is written straight over the stored script. The “before” survives only in the trace store, joinable by job ID, and only if tracing happened to be on. Some of our scripts already carry a human-edited flag, which means we have already thrown gold pairs away.

The same applies to the dismissal button on our review panel. A dismissed finding is a false-positive label, already being collected, and currently used only to demote a noisy family once it crosses a threshold. Those dismissals are the only evidence we have of detectors like the one that misfired on “is not the same as.”

3. Build the judge before the optimizer, and validate it against a human. Pairwise, not pointwise. Label a batch of pairs by hand, then measure the judge’s agreement with those labels. If the judge does not agree with you clearly and consistently, stop. No amount of prompt optimization helps when you are climbing a hill made of noise. This is the gate almost everyone skips, and skipping it is how teams ship an eval suite that measures nothing.

4. Replace rules with exemplars wherever an exemplar will do. Our own engineering notes already record this lesson from a different subsystem: two instructions and a worked example beat one rule line every time. We learned it while fixing narration language and never applied it to editorial style. One gold script carries more usable signal than all the rules written around it. Put an exemplar or two in the prompt, retrieved by source type, and delete the rules the exemplar already demonstrates.

This also fixes the compression problem. You cannot safely shorten a rulebook you cannot test — but you can always keep the exemplar.

5. Keep the taxonomy open at the edges. A closed vocabulary is right for counting and routing, and wrong as the only thing the reviewer may say. The reviewer needs a way to report a defect it has no name for, held separately from the counted families, so a new failure mode arrives as a new observation instead of a confident mislabel.

6. Then run an optimizer. PaperCast’s distillation module already sorts every learned lesson into tiers, where the top tier is “a prompt-document proposal, never an automatic mutation.” That is the right shape. The architecture anticipated this step; it just has no optimizer behind it yet.

7. The structural bet: per-source rubrics. Before writing, one cheap call produces a short rubric for this source — what a good explainer of this particular thing has to accomplish. Write against it, judge against it. It attacks the root complaint directly: style and elements vary by source, so one global rulebook is always wrong somewhere. This is also the honest answer to the review-paper failure and the manufacturing-paper failure, both of which were a global rubric applied to a source it did not fit.

The Honest Limit

Some of this does not converge, and we should say so.

There is no version of this where the human disappears. The realistic end state for a product that writes prose for other humans is a good approval gate with a person behind it. That is not a failure of the system design; it is the correct design for a task with no oracle.

The question worth asking is not how to remove the human from the loop. It is what those thirty seconds at the gate actually produce. Right now, approving a script teaches the system nothing, and editing one teaches it nothing. Every judgement our best reviewer makes evaporates on write — which is why, two months in, we are already rediscovering the same defects with new nouns.

Fixing that is worth more than another thousand lines of regex.


PaperCast turns a research paper into a narrated explainer video end to end — discovery, an approvable script, designed slides, narration, and a subtitled MP4. Read more about it here.