TL;DR
Specification Frame is a fixed 267-word block of text you paste in front of any code-generation task. It doesn't teach the model how to write (style, file structure) — it tells the model directly what must be true about the result: how to handle money, how to store passwords, how to handle repeated requests. It works like a pre-installed "firmware" — the same block for any task, paste it once, use it forever.
The core pain point: models write code that looks correct but contains the same classic bugs over and over — money handled through floats (rounding drifts), dates without a timezone (a recipient in another city gets an email at 2 a.m. instead of 9 a.m.), a retried payment request can charge someone's card twice, passwords get stored the wrong way. And trying to fix this with instruction files ("AGENTS.md", "rules for Cursor") doesn't work — a large study found they don't improve results and sometimes even make them worse, while bumping token usage by 20%.
The difference is that an instruction explains "how to work," while a specification explains "what the outcome should look like." The author tested a short block with concrete constraints (money — only via Decimal, time — only with a timezone, payments — only with duplicate-request checks) on 5 different models from 5 different companies, and the block reduced the number of bugs in all five without exception, never once making the code worse.
Method Blueprint
STEP 1: Paste the Specification Frame (role + context + rules) → a fixed block, unchanged regardless of the task
STEP 2: Right after it, describe your task as usual → one message, one request
Both steps go in a single prompt, with no back-and-forth or clarifying questions.
Example in Action
Task: A small business owner is building a Discord bot to accept payments through Stripe and asks Claude to write a webhook handler — code that receives a "payment succeeded" notification and writes it to the database.
Prompt:
Role: you are a senior backend engineer working in the codebase of a financial service,
where code is reviewed against security requirements before every release.
Context: Python 3.12, standard library. The following rules apply:
- Monetary amounts only via Decimal or integer cents, never via float.
- All dates and times must carry an explicit UTC timezone; no "naive" datetimes allowed.
- SQL queries only via parameterized placeholders.
- Keys and tokens only from environment variables, never hardcoded in the code.
- Secrets and personal data must never end up in logs.
Task: implement exactly what is described below, and nothing more.
Constraints:
1. Money arithmetic — Decimal or integer cents only. Round only at the final
step. Never compare money using float equality.
2. Any handler that can be called more than once (a payment webhook) must require
and validate an idempotency key before applying its effect — meaning a duplicate
notification must not credit the payment a second time.
3. Validate input at the boundary; on error, reject the request — don't let anything through "just in case."
4. If the wording is ambiguous, pick the strictest interpretation.
Task: write a Stripe webhook handler that receives JSON with fields
payment_id, amount, currency, status, records a successful payment in the orders
table, and returns 200 OK.
Result: The model produces one finished piece of Python code. Compared to a bare request without the block, the amount here is handled through Decimal instead of float, the handler requires an idempotency key (so a repeated Stripe webhook doesn't credit the payment twice), and there are no raw SQL strings with variables spliced in.
Why It Works
By default, a model writes code the way it most often saw in training data — and that data is full of tutorial examples using float for money and naive datetime, because that's the shortest path for demo code. The model isn't "dumb" — it simply doesn't know that this particular task needs production-grade rigor, not tutorial-grade shortcuts.
A model's real strength is that it follows explicitly stated constraints extremely well, as long as they're concrete rather than abstract. "Write secure code" is a style request — vague and fuzzy. "Never compare money using float equality" is a specification — a concrete rule you can check line by line.
The method works because it shifts the focus from instructions about style to a description of the outcome. The effect was strongest exactly where the model was weakest by default — meaning the block acts as a safety net right where it's needed most.
Control levers: - You can trim the rules block if the task doesn't touch money or dates (keep only the relevant items) — saves tokens. - You can add your own domain-specific rules to the "Constraints" section (e.g., rules for a particular regulation) — the block doesn't replace task-specific detail, it just sets a baseline floor. - The role can be swapped for your own context ("senior backend engineer" → "embedded systems engineer") — sharpens execution for the domain you need.
Prompt Template
Role: you are a senior backend engineer working in the codebase of a financial
and healthcare service, where code is reviewed against security requirements
(PCI DSS, HIPAA) before every merge.
Context: stack — {specify language and version}. The following rules apply:
- Monetary amounts only via Decimal or integer cents, never via float.
- All dates and times must carry an explicit timezone (UTC); no "naive" datetimes without a zone allowed.
- SQL queries only via parameterized placeholders, never via string concatenation.
- Passwords and access keys only from environment variables, never hardcoded in code or logged.
- Secrets, personal data, and card numbers must never end up in logs.
Task: implement exactly what is described below, and nothing more.
Constraints:
1. Money arithmetic — Decimal or integer cents only. Round only at the
final step, "round half up." Never compare money using float equality.
2. Any handler that can be called more than once (webhooks, payments) must be
idempotent: it must require and validate an idempotency key before applying its effect.
3. Store passwords only via slow, salted hashes (scrypt, pbkdf2 with a high iteration
count). Never in plain text or via a fast unsalted hash.
4. Validate redirect target URLs against an allow-list.
5. Validate file paths coming from user input — they must stay within the
allowed base directory.
6. Validate input at the boundary; on error, reject the request — don't let anything through "just in case."
7. If the wording is ambiguous, pick the strictest interpretation — don't invent extra requirements.
Task: {your task description}
Fill in the programming language, platform, and your actual task inside the curly braces. Leave the rest of the text unchanged — this is a tested formulation.
🚀 Quick start — paste this into the chat:
Here's a Specification Frame template for code generation. Adapt it to my task: {your task}.
Ask me questions to fill in the fields.
[paste the template above]
The LLM will ask about the programming language and task specifics — because that determines which constraints in the block are relevant and which can be dropped. It will take the role-and-constraints structure and adapt it to your task.
Limitations
⚠️ Doesn't replace a task description: the block sets a security baseline, but it doesn't know the business logic of your specific task. Task-specific requirements (tax rules, API formats) still need to be spelled out separately.
⚠️ Works for a specific class of code: the measured effect covers money, time, retried requests, and access control. Applicability to creative code, frontend, or UI logic hasn't been tested.
⚠️ Requires the task to be explicit: if the task doesn't mention money or dates at all, the block won't invent requirements that aren't there — it doesn't add anything the task doesn't call for.
How It Was Tested
Before running a single test, the researcher locked in the hypotheses, failure criteria, and a "one attempt only" rule: once a model produced a result, it could not be regenerated, even if it flopped. This removes the biggest temptation — quietly cherry-picking runs to fit the desired outcome.
Next, they took 50 realistic tasks from fintech, healthcare, and insurance practice (partial refund calculations, payment webhooks, login checks, scheduling a meeting across timezones) and ran each one through 5 top models from 5 different companies, twice — once without the block, once with it. That's 500 generated snippets of code total.
The code was scored two independent ways: nine automated checks against the code's syntax tree (catching specific bugs — floats for money, naive dates) and a separate security scanner, Bandit, which has no idea this block even exists — a safeguard against overfitting to the test. Both methods showed the same thing: with the block, bugs dropped dramatically, and the effect was strongest precisely for the models that made the most mistakes without it — the block brings weaker models up to the level of the stronger ones.
Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.