Prompts are interfaces
A prompt you reuse is software with a contract. The five-part shape behind every prompt we ship: role, inputs, rules, strict output, self-check.
Abdulkader Tamer6 min read
Most prompts are written like text messages. You type what you want, the model answers, you tweak a word, it answers again. That’s fine for a one-off question. It falls apart the moment you want to run the same task twice and get something you can compare, hand to a teammate, or paste into a doc without cleaning it up first.
The shift that fixed this for us was simple: treat a prompt you reuse as an interface, not a message. An interface has a contract. It says what goes in, what comes out, and what’s guaranteed in between. A function signature does that. An API spec does that. A good prompt should too.
When we built the Operator Prompt Pack — 40 prompts for code review, ops, writing and research — every single prompt follows the same five-part shape. Not because templates are pretty, but because each part fixes a specific way prompts fail.
1. Role — who the model is while doing this
A role isn’t a magic spell (“you are a world-class genius…”). It’s a way to set defaults: what to care about, what to ignore, what order to work in. “You are a senior engineer reviewing a pull request” means something concrete: correctness before style, failure scenarios over opinions.
The useful part of a role is usually the second sentence — the priorities. Ours for code review lists them explicitly: correctness, security, data loss, performance, maintainability, and style last. Without that, models drift towards whatever is easiest to comment on, which is usually naming and formatting.
2. Inputs — named slots, nothing assumed
Every input is a variable in double braces: {{DIFF}}, {{SYMPTOM}}, {{LOGS}}. This does two things.
First, it tells the person using the prompt exactly what to paste. The most common reason for vague output isn’t a weak model — it’s missing context. An empty slot is visible; a missing paragraph in a free-form prompt isn’t.
Second, it tells the model what it’s allowed to rely on. If the prompt only has {{INTENT}}, {{STACK}} and {{DIFF}}, the model has no business inventing what the rest of your codebase looks like. Our rule for people using the pack is: fill every variable, and if you truly have nothing, write none. “None” is information. Silence isn’t.
3. Rules — the constraints that stop generic output
This is where most of the quality comes from. Rules are the things you’d otherwise correct by hand after every answer:
- “Every finding needs a concrete failure: when X happens, Y breaks because Z.”
- “Quote log lines exactly when you reference them.”
- “Prefer reversible actions.”
- “No jargon the client didn’t use.”
Good rules are checkable. “Be concise” isn’t a rule, it’s a mood. “Max 4 sentences” is a rule. If you can’t look at an answer and say whether it followed the rule, rewrite the rule.
4. Output — an exact format
This is the part that makes a prompt an interface. If the output shape is fixed — numbered sections, a table with named columns, a one-line verdict at the top — then:
- you can scan it in seconds, because you know where everything is;
- you can compare two runs (or two models) side by side;
- you can paste it straight into a ticket, a postmortem doc or a PR description;
- and if you later wire the prompt into a script or an agent, you can parse it.
A fixed format also quietly improves reasoning. When the model has to fill “evidence for” and “evidence against” for every hypothesis, it can’t skip the “against” column.
5. Check — a short self-review before answering
The last line of every prompt is a check the model runs on its own draft. It’s always specific to the task and always about the most common failure:
- Code review: “Did every blocking issue include a failure scenario? Drop any that don’t.”
- Debugging: “Is any hypothesis contradicted by the symptom as stated? Remove it.”
It’s cheap, and it targets exactly the thing you’d otherwise catch yourself on the second read.
Two examples
Here’s a shortened version of the pull request review prompt from the pack. Notice how little of it is “instructions” and how much is contract:
You are a senior engineer reviewing a pull request. Find problems that
would hurt users or the team, in this order: correctness, security,
data loss, performance, maintainability. Style only if it hides a bug.
Inputs
- What the change is supposed to do: {{INTENT}}
- Language / framework: {{STACK}}
- The diff:
{{DIFF}}
Rules
- Only comment on lines in the diff, or code the diff clearly breaks.
- Every finding needs a concrete failure: "when X, Y breaks because Z".
- Suggest the smallest fix. Don't rewrite the change.
Output
1. Verdict: APPROVE / APPROVE WITH NITS / REQUEST CHANGES — one line why.
2. Blocking issues: file:line · problem · failure scenario · smallest fix.
3. Non-blocking (max 5), one line each.
4. One thing the author did well (specific).
Check before answering: did every blocking issue include a failure
scenario? Drop any that don't.
And a log-triage prompt, adapted from the ops section. Different job, same skeleton:
You are reading logs to find what matters.
Inputs
- What I'm investigating: {{QUESTION}}
- Logs:
{{LOGS}}
Rules
- Quote log lines exactly when you reference them.
- Ignore repeated noise unless its rate changes at the incident time.
Output
1. Timeline: the 5–10 events that matter, in order, with timestamps.
2. Error groups: pattern · count · first seen · last seen · likely meaning.
3. The first abnormal event (often the cause, not the loudest error).
4. What's missing from these logs that I'd need to be sure.
Check: is the "first abnormal event" actually earlier than every error
group it explains? If not, pick again.
The third output section in that one — “the first abnormal event, not the loudest error” — is the whole point of the prompt. That’s a lesson from debugging real systems, written down once and applied every time.
Version your prompts like code
Once a prompt is an interface, it should be versioned like one. Every prompt in the pack carries a version (v1.0), and changes go in a changelog. If a prompt’s output format changes, anything downstream that depended on it — your doc template, your script, your teammate’s habits — deserves to know.
It also keeps you honest. “I tweaked the prompt and it feels better” isn’t a change. “v1.1: added a rule against suggesting rewrites, because v1.0 kept proposing them” is.
What this changes in practice
Writing prompts this way is slower the first time. It’s much faster every time after, and it’s the difference between “the AI is hit or miss” and “this works, here’s the version we use”. It also makes prompts shareable: a teammate can pick one up without a walkthrough, because the inputs and outputs are written on the tin.
If you want the full set built this way — 40 prompts across code, ops, writing and research, each with a role, inputs, rules, an exact output format and a check — the Operator Prompt Pack is in the store. And if you want this method applied to your own team’s tasks, that’s what our Prompt System package is for.