Back to blog
ChatGPT11 min read

How to Get Consistent Output Every Time

Getting consistent AI output is not a temperature setting. It takes a fixed system prompt, a schema, worked examples, and a validator, plus knowing exactly where that still falls short.

NH
Nafiul Hasan
Founder, Prompt Architects

TL;DR: Consistent AI output doesn't come from a sampling setting. Anthropic's newest models reject a non-default temperature outright, and Google's newest API drops sampling controls from its schema while still naming temperature as an example elsewhere. What actually holds up is structural: a fixed system prompt, a schema, worked examples, and validating the output yourself.

Why do you get a different answer every time you run the same prompt? That question is about sampling, batching, and model drift, and it has a real, documented answer that this post isn't going to repeat. This post starts from a different question: given that the model samples and you can't fully turn that off, what do you actually build so the difference stops costing you anything? The honest answer involves less tuning than most guides suggest, and it involves building something once instead of re-fighting the same output every time you run the prompt.

Why can't you just set the temperature to zero?

Because on several current models you cannot set it at all, and even where you can, it never meant what people assumed. Anthropic's own migration guidance for its newest models is unambiguous: setting temperature, top_p, or top_k to any non-default value returns an error, full stop, and the same guidance adds that using temperature 0 for determinism "never guaranteed identical outputs" even on the models where it was accepted. Prompting is what Anthropic now recommends in its place.

Google's story is stranger, and worth knowing if you're building against its newer surface. The current Interactions API's own GenerationConfig schema, the actual object you send on a request, does not define temperature, top_p, top_k, or either penalty parameter anywhere. But Google's own overview page for that same API describes interaction-scoped settings as "generation_config (including thinking_level, temperature, etc.)" — naming temperature as if it were live. The schema is what the API actually accepts; the overview prose is a claim the schema doesn't back up. Both are Google's own pages, fetched the same day. Neither one is wrong exactly, they just disagree, and the schema is the one that decides what your request does.

If you want the mechanism behind why a model samples at all, and why identical settings still drift between runs, that's post 218's territory, not this one.

Is there a seed you can rely on for images?

No, and this is a gap almost nobody states plainly. Google's image-specific configuration object, ImageConfig, has exactly two documented fields: aspectRatio and imageSize. There is no seed field on it. A seed field does exist, but on the separate, shared GenerationConfig object used for text generation, described there as used "in decoding" with a randomly generated value if you don't set one. That seed field never appears anywhere on Google's own image-generation guide, so there's nothing published connecting it to image reproducibility at all.

Other vendors are just as unhelpful here or worse. Runway's own OpenAPI file contradicts itself across four different sentences about whether its seed is guaranteed to reproduce a result. OpenAI's current image model publishes no seed parameter. There is no published image-reproducibility contract from any major vendor right now. If a workflow depends on regenerating the same image later, plan around that gap rather than around a setting that doesn't exist yet.

OpenAI's Structured Outputs guide, Anthropic's structured-outputs and Opus 5 migration docs, and Google's Interactions API reference and overview page. Fetched 3 September 2026.
FeatureOpenAIAnthropicGoogle (Interactions API)
Schema-enforced structured output
Older free-text JSON mode still offeredYes, no schema guaranteeNot applicableDeprecated path
Sampling parameters in this endpoint's own schemaFull setNone accepted on newest modelsNone defined
Vendor's own docs agree on thatNo, overview page names temperature anyway

What actually makes AI output consistent?

Four things, none of which is a slider. Every one of them is structural: you build it once, and it holds across runs even though the model's exact wording still moves.

  1. A fixed system prompt, pasted in unchanged, so you stop introducing your own variance by rewording the same instruction slightly differently each time.
  2. A schema, so the shape of the answer is guaranteed even when the phrasing inside it isn't.
  3. Three to five worked examples, which pin the target format more reliably than a written description of that format ever does on its own.
  4. A validation step, run in code against the actual response, so a malformed answer gets caught and retried instead of shipped because it looked plausible on a skim.

None of these are new ideas. What's new, relative to the set-temperature-to-zero advice still repeated everywhere, is that they're the only levers left once a vendor removes the sampling knob entirely, and they were the more reliable fix even before that happened.

Does a fixed system prompt actually help?

Yes, and the value is less about writing better instructions than about removing the variance you introduce yourself. If you retype your standards slightly differently every time, keep it brief this run, keep it short the next, be concise the one after that, you've handed the model three different-shaped instructions across three runs, and the output moves to match. A system prompt you paste in unchanged removes that source of drift entirely; whatever is left over comes from the model, not from you accidentally rewording your own request.

Anthropic's own guidance for structuring prompts recommends wrapping distinct content types in consistent, descriptive tags, <instructions>, <context>, <input>, precisely because a model can parse a well-labeled fixed structure more reliably than prose that changes shape slightly between runs. The fix is the same one that makes a template reusable in the first place, and the same discipline behind naming your role, task, and format explicitly rather than describing them loosely: write it once, in a form with clearly marked variable slots, and stop hand-editing it per use.

Why does structured output beat asking nicely for JSON?

Because a polite request and a schema are enforced completely differently. OpenAI states the difference plainly: its Structured Outputs feature "ensures the model will always generate responses that adhere to your supplied JSON Schema," while its older JSON mode "will not guarantee the output matches any specific schema, only that it is valid and parses without errors." One guarantees shape. The other only guarantees the result won't crash your parser.

Both other majors have moved the same direction. Anthropic's current structured-output path is output_config.format, now out of its earlier beta status, and it recommends this over hand-formatted prefill for anything that needs guaranteed compliance. Google's own move is more interesting: its older responseSchema field is now marked deprecated on its API reference, with the documented replacement being the newer Interactions API's response_format object, which takes a schema directly.

The reason this matters more than it sounds: a schema doesn't make the prose identical between runs, and it isn't supposed to. It makes the fields identical, which is almost always the part your downstream code, or your reader, actually depends on. Wording is allowed to drift. A missing key or a renamed field is not.

How many examples do you actually need?

Fewer than people assume, and more isn't automatically better. Anthropic's own prompting guidance is specific: "Include 3–5 examples for best results." It recommends choosing them to mirror your actual use case and to be diverse enough that the model doesn't pick up an unintended pattern from samples that are too similar to each other. Few-shot examples pin format in a way that a written description of the format usually can't match on its own, because an example shows the exact shape rather than describing it in words the model still has to interpret.

The practical habit: keep your 3 to 5 examples wrapped in their own tags, separate from the live instruction, so they're obviously examples and not part of the actual request. That's also what makes them reusable: the same example set works across dozens of live requests once it's saved, rather than being retyped into the prompt by hand each time.

Should you trust the output, or check it?

Check it. This is the step that gets skipped most often, and it's the one that actually catches the failures the other three don't. A schema validator either accepts a response or it doesn't; it has no incentive to sound confident about a result that's actually wrong. Asking the model to grade its own output is a weaker version of the same idea and should be treated as a hint, not a test, since the same sampling variance that produced the inconsistent output in the first place is also present in the model's opinion of that output.

In practice this means running the response through actual schema validation in code instead of eyeballing whether it looks plausible, and rejecting or retrying anything that fails rather than shipping it anyway because a human skim didn't catch the problem. This is the step that turns a response that is usually correct into one that is verified correct every time it ships.

### CONSISTENCY TEMPLATE — fill in {{brackets}}, save this, reuse it unmodified

SYSTEM PROMPT (paste unchanged every time):
You are a {{role}} producing {{output_type}} for {{audience}}.
Always follow the OUTPUT CONTRACT below exactly.

OUTPUT CONTRACT:
Return exactly these fields, in this order: {{field_1}}, {{field_2}}, {{field_3}}.
If a value is unknown, use the string "unknown". Never invent a value.
Format: {{format, e.g. "JSON matching the attached schema"}}.

EXAMPLES (3-5, wrapped so the model can't confuse them with the live request):
<examples>
<example>
  input: {{sample input 1}}
  output: {{sample output 1, in the exact target shape}}
</example>
<example>
  input: {{sample input 2}}
  output: {{sample output 2}}
</example>
<example>
  input: {{sample input 3}}
  output: {{sample output 3}}
</example>
</examples>

VALIDATION (run this against every response before you use it):
1. Parse the response against {{schema name / field list}}.
2. Reject and retry once if any required field is missing or the wrong type.
3. Log field-level differences between runs; don't just log pass/fail.

The instructions and the examples are the part worth saving somewhere you can pull up without retyping it. A prompt library with saved variables is exactly this idea built into a tool instead of a text file you have to remember where you put, and if the shape you need is already JSON, a ready-made schema generator gets you to a valid one faster than writing it by hand.

Worth being direct about where this sits in a typical toolchain: saving a prompt for reuse is usually a paid step, not a free one. Prompt Architects' own free tier, for example, covers five prompt enhancements a day but keeps Save Prompts, Refine Mode, and Shorten Mode on paid plans. That's a normal line for a vendor to draw. The point isn't which tool you use to store the template; it's that a template worth reusing is worth actually saving somewhere, rather than being the thing you reconstruct from a half-remembered draft every time the same task comes up again.

The short version

Consistent output isn't something you get by finding the right number to type into a settings field, and on some current models that field isn't even reachable anymore. It's something you build once: a fixed system prompt, a schema that pins the shape, three to five examples that pin the format, and a validator that checks the result instead of trusting it. Save that combination as a reusable prompt template rather than reconstructing it from memory each time, and most of what currently reads as an inconsistent AI turns into a difference in wording you were never depending on in the first place.

Free Chrome Extension

Stop rewriting prompts. Start shipping.

Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 4.8★ on the Chrome Web Store.

Create An Account

Frequently asked questions

Free Chrome Extension

Stop rewriting prompts. Start shipping.

Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 4.8★ on the Chrome Web Store.

Create An Account