Why the same prompt gives you a different shape every time, and the fix that isn't a better prompt

You run the same prompt on a new record and the output comes back shaped differently each time: a field renamed or a section missing, and the numbers themselves sitting in a table one run and buried in a sentence the next.

Why rewording won't fix this

A model generates text one token at a time based on what is likely to come next, not from a fixed template it fills in. Longer, more detailed instructions lower the odds of drift but never remove them, because there is no hard boundary enforcing shape the way a form field does. The fix is a declared output schema, not firmer wording: validate what comes back and retry on mismatch.

Worked example: a claim summary

Say you are turning adjuster notes into a short claim summary: claim number, loss date, status, next action. Described as a paragraph, that is four facts loose in prose, with no fixed slot for any of them.

Described as a schema, with claim_number as a string, loss_date as a date, status as one of a fixed set of values, and next_action as a string, each fact gets exactly one place to live. A response missing one is a validation error your code catches before a person ever sees it.

Validate the shape, retry on failure, never pass through a near-miss.

const ClaimSummary = z.object({
  claim_number: z.string(),
  loss_date: z.string(),
  status: z.enum(["open", "pending_docs", "closed"]),
  next_action: z.string(),
});

function summarize(notes) {
  for (let attempt = 0; attempt < 3; attempt++) {
    const raw = callModel(buildPrompt(notes));
    const parsed = ClaimSummary.safeParse(raw);
    if (parsed.success) return parsed.data;
  }
  throw new Error("model did not return a valid claim summary after 3 attempts");
}

Ask for the schema, not a format description

Telling a model 'please use this exact format' in plain English competes with everything else in the prompt for attention. Handing it a schema, through the structured-output or function-calling support most model APIs now have, changes what is actually being asked, from 'try to look like this' to 'return data matching this definition'. That alone fixes most drift, and the retry step catches what's left.

What this buys you beyond consistency

Once output has a schema, you can diff two runs or store results in a normal database column. Either way, it feeds straight into the next step of a pipeline without a person checking the shape first. None of that is available when the output is 'mostly the same paragraph as last time'.

If the summary also needs to cite where in a long document each fact came from, the playbook on reading a long document covers that per section, and the two combine cleanly: chunk and cite first, validate the combined result against the schema second.

See also: Missed a clause in a long document

What stays manual

  • Choosing which fields belong in the schema in the first place.
  • Deciding what to do when validation fails three times in a row: flag it, don't guess.
  • Updating the schema when the underlying form or policy type changes.