{
  "question": "How do I prove which model version, prompt and settings produced a specific AI output?",
  "slug": "how-to-prove-which-model-version-prompt-and-settings-produced-an-ai-output",
  "url": "https://www.rightshold.com/answers/how-to-prove-which-model-version-prompt-and-settings-produced-an-ai-output",
  "short_answer": "Build a content-addressed run record at the moment the response comes back: the model ID the provider says actually answered (not the alias you asked for), a SHA-256 of the exact prompt bytes (system prompt, messages, tool schemas), a SHA-256 of the canonical settings object (temperature, top_p, max tokens, seed, tool_choice, response format), a SHA-256 of the exact output, and the provider's response id and backend fingerprint where one is returned. Because each part is named by its hash, anyone holding the original prompt, settings and output can recompute the hashes and see whether they match; change one byte and the match fails. Then get that record signed and timestamped by someone other than you, so it can't be quietly rebuilt later. This proves which configuration was recorded with which output, and when. It does not prove the provider really served that model, and it can't make the run repeatable. record_ai_run signs such a record onto Rightshold's ledger; verify_ai_run lets anyone check it for free.",
  "checklist": [
    "Record the model the provider reports in the response, not only the one in your request. OpenAI's chat completion object returns model and, where available, system_fingerprint; Anthropic's Messages response returns model; Gemini's GenerateContentResponse returns modelVersion and responseId. If you requested an alias (for example a -latest name), the reported value is what pins the version.",
    "Hash the prompt as sent, not as templated in your code: serialize the full request messages (system prompt, user turns, tool results already in context) plus tool definitions to one byte string and take SHA-256. Keep the bytes; the hash is only useful if you can produce the original.",
    "Put every generation setting into one settings object (model requested, temperature, top_p, max tokens, seed, stop sequences, tool_choice, response_format or JSON schema, reasoning or thinking budget) and hash its canonical form with sorted keys, so key order can't change the hash.",
    "Hash the exact output bytes you returned to the user or the next step, after any post-processing you apply. If you post-process, record the raw output hash too and say which one is which.",
    "Keep the provider's request or response id and created time next to the hashes. They let you or the provider correlate the run later while logs still exist.",
    "Record the code version that built the prompt (git commit of the template and any retrieval config). A prompt hash without the template version tells you that something changed, not what.",
    "Seal the record once, at return time: sign it and get an independent timestamp, so a record rebuilt after a dispute is distinguishable from one made when the answer came back.",
    "Write down the limits next to the record: a caller-reported record can't prove which weights served the request, and seeds are best effort, so a re-run may legitimately differ."
  ],
  "sections": [
    {
      "heading": "Why 'we used model X' isn't enough",
      "points": [
        "Aliases move. Anthropic's models overview says that for models before the 4.6 generation the short alias points to a dated snapshot ID (from 4.6 on, every ID is a pinned snapshot), and Gemini documents -latest style names that are updated over time. A config file that names an alias doesn't say which version answered on a given day; the model value in the response does.",
        "Backends change under a fixed ID. OpenAI documents system_fingerprint as the backend configuration fingerprint and tells you to compare it with seed to understand why outputs might differ. Anthropic's September 2025 postmortem describes three infrastructure bugs that degraded some responses for weeks without any model ID change. A record that carries the response-side identifiers is the best you can do from the outside.",
        "Prompts drift too. Templates, retrieved context, tool schemas and system prompts are edited far more often than model versions. If only the user's question is logged, two outputs with the same 'prompt' can come from very different requests."
      ]
    },
    {
      "heading": "What content-addressed means here, and how someone checks it",
      "points": [
        "Each part of the run is identified by the SHA-256 of its exact bytes: prompt_sha256, output_sha256 and a hash of the canonical settings object. The record then carries those hashes plus the model and provider names, and the record itself is hashed and signed.",
        "A reader with the originals recomputes each hash. If the prompt, settings or output they were given hashes to the recorded value, it is the same content that was recorded; any edit, even whitespace, fails. A reader without the originals learns nothing about the content, so the record can be public while prompts stay private.",
        "Keep the originals somewhere durable. The record proves a match; it doesn't store the text. Losing the prompt bytes means nobody can ever show which prompt produced the output, even though the hash is on file."
      ]
    },
    {
      "heading": "What this proves and what it doesn't",
      "points": [
        "Proves: this exact output was recorded together with this prompt, these settings and this reported model, no later than the signed issued time, and none of it has changed since.",
        "Doesn't prove: that the provider actually ran the named weights (only the provider can attest that), that the output is correct, or that re-running will reproduce it. For first-hand capture, Rightshold's agreement mode calls the models itself and records what it received.",
        "For a single answer's timing question (what did the model say on a given day) the shorter guide on proving what a model said at a specific time is enough; this page is about tying the output to the full configuration that produced it."
      ]
    }
  ],
  "checks": [],
  "ask_rightshold": {
    "start": "https://www.rightshold.com/start?ref=seo",
    "mcp_endpoint": "https://www.rightshold.com/mcp",
    "ask": "Record a signed run receipt tying this output to the reported model version, the hash of the exact prompt bytes and my generation settings.",
    "mcp_call": {
      "tool": "record_ai_run",
      "arguments": {
        "model": "claude-sonnet-4-5-20250929",
        "provider": "anthropic",
        "prompt_sha256": "<sha256 of the exact request messages + tool schemas>",
        "output_sha256": "<sha256 of the exact output bytes>",
        "params": {
          "requested_model": "claude-sonnet-4-5",
          "temperature": 0,
          "max_tokens": 1024,
          "tool_choice": "auto",
          "template_commit": "<git sha>",
          "response_id": "<provider response id>"
        },
        "ran_at": "2026-11-07T17:00:00Z"
      }
    },
    "also": [
      "Needs an API key. Prompt and output are hashed (text sent in plain is hashed on arrival and never stored). params is stored as params_sha256 over sorted-key canonical JSON, so keep the exact params object: a reader recomputes its hash and compares it with the receipt.",
      "verify_ai_run is free and needs no key: send the receipt id plus the prompt or output text to confirm they match the recorded hashes, or send the receipt and signature to check the Ed25519 signature offline.",
      "The receipt is written to Rightshold's append-only ledger and its blocks are anchored to Bitcoin through OpenTimestamps. In recorded mode it is marked reported_by caller: it shows what you recorded and when, not that the provider served that model."
    ],
    "scope": "Rightshold records the hashes and fields you send, signs them and lets anyone check them later. It doesn't call your model in recorded mode, can't attest which weights a provider served, and doesn't judge whether an output is correct. Not legal advice."
  },
  "sources": [
    {
      "title": "OpenAI API reference: The chat completion object (model, system_fingerprint)",
      "url": "https://platform.openai.com/docs/api-reference/chat/object"
    },
    {
      "title": "OpenAI API reference: Create chat completion (seed)",
      "url": "https://platform.openai.com/docs/api-reference/chat/create"
    },
    {
      "title": "Anthropic: Models overview (model IDs and aliases)",
      "url": "https://platform.claude.com/docs/en/about-claude/models/overview"
    },
    {
      "title": "Gemini API reference: GenerateContentResponse (modelVersion, responseId)",
      "url": "https://ai.google.dev/api/generate-content"
    },
    {
      "title": "Anthropic: A postmortem of three recent issues (Sept 2025)",
      "url": "https://www.anthropic.com/engineering/a-postmortem-of-three-recent-issues"
    },
    {
      "title": "RFC 8785: JSON Canonicalization Scheme (JCS)",
      "url": "https://www.rfc-editor.org/rfc/rfc8785"
    },
    {
      "title": "OpenTimestamps client",
      "url": "https://github.com/opentimestamps/opentimestamps-client"
    },
    {
      "title": "Verified AI Runs on Rightshold",
      "url": "https://www.rightshold.com/verified-ai-runs"
    }
  ],
  "related": [
    {
      "title": "How to prove what an AI model said at a specific time",
      "url": "https://www.rightshold.com/answers/how-to-prove-what-an-ai-model-said-at-a-specific-time"
    },
    {
      "title": "How to make LLM eval results reproducible and tamper-evident",
      "url": "https://www.rightshold.com/answers/how-to-make-llm-eval-results-reproducible-and-tamper-evident"
    },
    {
      "title": "How to replay an AI agent run deterministically from a recorded call order",
      "url": "https://www.rightshold.com/answers/how-to-replay-an-ai-agent-run-deterministically-from-a-recorded-call-order"
    },
    {
      "title": "Verified AI Runs",
      "url": "https://www.rightshold.com/verified-ai-runs"
    }
  ],
  "computed_from": "Curated guidance; license verdicts computed from Rightshold's license profiles at render time. Not legal advice.",
  "updated": "2026-11-07"
}