Back to case studySource

TECHDRISHTI · NINE FIELD REPORTS

The evolution, bug by bug

Nine real failures found while building the pipeline, each with what was claimed, what actually broke, the fix, and how it was verified. Where a real before/after artifact survives, it's quoted directly rather than paraphrased, an empty API response, a wrong query the model actually sent, a Hindi sentence it actually wrote.

On these quotes. They're pulled from this project's own build log, test fixtures, and one raw experiment output captured at the time each bug was live, not re-created after the fact for this page.
FIELD REPORT 01

The pipeline that occasionally said nothing at all

THE CLAIM
Stage 1 had two jobs bundled into one call: decide whether an article was even worth writing about, and, if so, work out what still needed researching to enrich it.
WHAT WE FOUND
Both jobs shared the same 4,096-token budget as the model's own hidden reasoning. When reasoning ran long, it could consume that whole budget before either job produced an answer, so a genuinely bad article could slip through unrejected, with zero research questions attached to enrich it, and the exact same prompt, run three times, produced three different outcomes, one of them a completely empty response.
THE ACTUAL FAILURE

finish_reason: "length", but content was empty: the entire 4,096-token completion budget had gone to invisible reasoning_content before the model ever wrote SKIP or KEEP.

THE FIX
Split the single call into two phases: a narrow skip-gate that decides only keep or reject, and, only for what survives that gate, a separate research phase that works out the entities and the gap queries needed to enrich the piece (itself split further into an analysis call and a JSON-transcription call, with reasoning off throughout). Inside the skip-gate itself: ask for the model's stated REASON before its SKIP verdict. With reasoning off, it commits to answers strictly in the order asked, so verdict-first meant guessing before any reasoning existed.
VERIFIED
Reordering alone took the skip-gate from 0/5 correct to 10/10 correct across two real articles.
FIELD REPORT 02

Entities that were never wrong, just never seen

THE CLAIM
The first 800 characters of a scraped article were enough to find the people, products, and institutions in it.
WHAT WE FOUND
On a real eye-perfusion device story, the device's own name, the lead researcher, and the institution behind it all sat past character 800, everything before that was generic scene-setting. The model had nothing to extract but “device” and “researchers.”
BEFORE — entities extracted (800 chars)

“device”, “researchers”

AFTER — same article, 2,000-char window

“ECaBox”, “Shannon Tessier”, “Barcelona Institute of Science and Technology”

THE FIX
Raised the truncation window to 2,000 characters, matching what the editorial-strategy stage already used successfully on the same articles.
VERIFIED
3 repeat runs on the same article pulled the real named entities every time, versus generic nouns every time before.
FIELD REPORT 03

A model that kept citing a rival that isn't in the story

THE CLAIM
Telling the model in plain English not to invent unlisted competitor names would stop it from doing that.
WHAT WE FOUND
Reviewing a 2026 model release, it kept comparing it to “GPT-4 Turbo” (a name never mentioned anywhere in the source), the identical wrong query, 3 runs straight. A more careful second rewrite of the same instruction still failed 2 of 3 runs.
THE HALLUCINATED QUERY, VERBATIM

“Leanstral 1.5 vs. GPT-4 Turbo performance on PutnamBench” — GPT-4 Turbo is never named anywhere in the source article; the real comparison point the source actually gives is Opus 4.6.

THE FIX
Stopped asking nicely. Added a code-level filter that checks every comparison-shaped query against the article's own extracted entities and source text, and silently drops it if the named rival was never actually there.
VERIFIED
3 fresh runs, zero hallucinated competitors reached search, including one run where the model tried anyway and the filter caught it first.
FIELD REPORT 04

Choosing which kind of wrong to live with

THE CLAIM
Detecting whether two headlines describe the same event is a matter of picking the right similarity threshold.
WHAT WE FOUND
Word-overlap and TF-IDF both missed genuine duplicates worded differently: a real pair about the same story scored 0.236, indistinguishable from confirmed false positives. Switching to sentence embeddings fixed that, but created a new failure: two unrelated Anthropic stories (a product launch, a funding round) scored 0.645, higher than an actual duplicate pair.
THE DECISION
Kept the embeddings anyway. A reader seeing the same story published twice was judged worse than one distinct story occasionally folding into another's write-up, a deliberate trade, not an oversight.
VERIFIED
Threshold tuned to 0.44 against the full known set of true/false positives collected during testing; the one accepted exception is documented, not hidden.
FIELD REPORT 05

The token cap wasn't the problem

THE CLAIM
Articles were coming out short because of Sarvam's 4,096-token completion cap.
WHAT WE FOUND
Real usage measured at ~468 tokens (about 11% of the cap). The actual cause was the editorial plan itself, which asked for “3-4 paragraphs, 1-2 sentences each.”
THE FIX
Rewrote the planning and writing prompts, and kept rewriting them as later runs found new ways to under-write. The current version no longer trusts “write more” as an instruction: it sets an explicit word-count target for every section of the article and for the piece as a whole, puts a floor under how many real sentences a single paragraph is allowed to be, and explicitly tells the writer not to treat the plan's one-line paragraph instruction as a length ceiling, expand it with the actual facts, mechanism, and stakes behind it instead of restating it. A separate editorial-quality pass, fact before interpretation, attribution for opinions, consistent hedging, no filler adjectives, no repeated ideas, runs before the model is allowed to finalize, so length is a side effect of writing a genuinely complete article, not a target chased on its own.
VERIFIED
The same real article grew from 930 to 2,075–2,269 characters under the first version of this fix, using only ~14% of the token cap; later revisions kept the same headroom while adding the section-by-section targets and editorial pass above.
FIELD REPORT 06

The planner that got token-starved by its own good judgment

THE CLAIM
The editorial-strategy stage, the planner that hands the writer its paragraph-by-paragraph instructions, was one call: reason through the story's core narrative, key facts, and category, and hand back the finished plan, all in the same response.
WHAT WE FOUND
On a real front-page story, that plan came back as a bare, contentless stub instead of a real set of instructions, and the article silently published without one. Reproducing it live: the call had used its entire completion budget, but the visible answer was barely 600 characters, cut off mid-object. Nearly all of that budget had gone to invisible reasoning tokens before the call ever got around to writing the plan itself.
THE ACTUAL FAILURE

prompt_tokens: 978 (a normal, real prompt), completion_tokens: 4096 (hit the hard cap exactly), but the visible content was only 594 characters, far too short for a complete JSON object.

THE FIX
Split the planner into two calls, the same shape already proven elsewhere in the pipeline: the first reasons through the editorial strategy out loud, in plain text, with reasoning explicitly turned off, so its visible output is the actual thinking rather than something competing with hidden reasoning tokens for the same budget; a second call transcribes that finished thinking into the strict JSON schema the writer consumes. The writer itself stays a single call; this split happens entirely inside planning, before the writer ever runs.
VERIFIED
Reran the same real inputs 3 times: zero of 16 captured API calls hit the token cap afterward, versus both broken calls hitting it exactly before.
FIELD REPORT 07

A fix that looked done, then broke on the very next live call

THE CLAIM
Telling the model to always name the real entity instead of “this”/“it” would stop research queries from referring to context a stateless research agent never sees.
WHAT WE FOUND
A live test built specifically to check this, not a unit test, reproduced the identical bug class on the next real call: a query asking “how does this differ” with no entity named anywhere in it, dispatched to an agent with no memory of the sibling question it was quietly relying on.
BEFORE — the agent's real response

“The term 'the vulnerability' could refer to several distinct security issues... it is impossible to definitively select one interpretation... Please clarify which system, CVE, or scenario you're referring to.” It then guessed at unrelated CVEs: a GitHub Actions self-hosted runner injection, a GitLab CI/CD token leak, a Jenkins agent RCE, an Azure DevOps token leak, none of them the real vulnerability.

AFTER — same query, GAP1 attached as context

Answered correctly and specifically: the actual crafted-issue payload wording, the real 5-step attack sequence, and how it differs from a genuine access-control bypass.

THE FIX
Attach the article's own opening question as background context to any later query that still dangles a “this”/“it” with no named entity, rather than guessing which entity it means or dropping the question outright.
VERIFIED
Ran the same real GAP queries through the actual research agent twice, with and without the fix, and diffed the answers side by side: without it the agent gave up and guessed at unrelated CVEs, with it the agent answered specifically about the real vulnerability. A second opinion, given the comparison blind, independently called it a working fix.
FIELD REPORT 08

The writer that copied its own instructions instead of following them

THE CLAIM
Telling the writer to follow each paragraph instruction “exactly as specified” would make it execute the plan, not repeat it.
WHAT WE FOUND
On a real article, the model wrote the plan's own instruction wording back as if it were the article itself, not an explanation of it, an explanation that never actually happened.
BEFORE — real captured output

“उपकरण के पीछे की तकनीक की व्याख्या करें। वर्णन करें कि यह कैसे काम करता है।” (“Explain the technology behind the device. Describe how it works.”) — literally the instruction, not an explanation.

AFTER — same article, fixed prompt

“यह उपकरण परफ्यूजन तकनीक का उपयोग करता है, जो आंख की धमनी के माध्यम से ऑक्सीजन युक्त तरल पहुँचाता है।” (“This device uses perfusion technology, delivering oxygenated fluid through the eye's artery.”)

THE FIX
Added an explicit instruction-vs-content distinction to the prompt, with this exact WRONG/CORRECT pair shown to the model, plus a rule: if a sentence about to be written contains a verb telling the reader what to do (व्याख्या करें, वर्णन करें), that's the instruction leaking through, not the article, rewrite it as a direct statement of fact instead.
VERIFIED
Reproduced on a fixed test fixture (same real Stage 1+2 output, reused across every trial): the old prompt bled through on 1 of 3 runs; the new prompt was clean 8 of 8 runs.
FIELD REPORT 09

Stray English commentary the reader was never supposed to see

THE CLAIM
A prompt telling the model to write entirely in Hindi means every line it produces is Hindi.
WHAT WE FOUND
The model would sometimes preface or annotate its Hindi article with English meta-commentary about the writing task itself, sentences narrating what it was about to do rather than part of the article, written in English and left sitting in the output.
THE PATTERN CAUGHT

English-only lines starting with “Let me”, “Here's”, “I'll”, or “Note:”, the model narrating its own writing process instead of just writing the article.

THE FIX
Added a code-level post-processing filter, not just a prompt instruction, that strips any English-only line matching this pattern before an article is ever saved or published, a backstop rather than trusting the prompt alone to prevent it.
VERIFIED
Runs automatically on every article Stage 3 produces, as part of the same cleanup pass as the decimal-aware sentence trimming used elsewhere in the pipeline; a stray line is removed silently rather than reaching a reader.