Skip to content
Yvo de Rooij.
All writingPrompting

The three prompt patterns I actually use in production

After shipping AI in four companies where wrong answers cost real money, I stopped reaching for clever prompt engineering and started reaching for three patterns. Here they are, with copy-ready skeletons and a before-and-after for each.

7 min read
  • Prompting
  • Production
  • Patterns
Revised 2 times, last on 5 September 2026· show
  • 30 Sep 2025Removed the section about chain-of-thought prompting. By late 2025 the frontier models reason without being asked, and the old 'let's think step by step' incantation became noise.
  • 5 Sep 2026Rewritten as a working guide: each pattern now has a copy-ready skeleton, a before-and-after example and a decision rule, plus a Monday checklist.

After shipping AI in four companies where wrong answers cost real money, I stopped reaching for clever prompt engineering and started reaching for three patterns. That's it. Three. Everything else is decoration.

These patterns are boring. They are also the ones that survive contact with production, which is the only test that matters. For each one I will give you the problem it solves, a skeleton you can paste, a before-and-after, and a rule for when to use it.

The idea underneath all three: your prompt is not a conversation with the model. It is the body of an API call that happens to be written in English. Once you believe that, most prompt advice sorts itself into "engineering" and "folklore".

1. Structured output as the interface

The problem. Every time I am tempted to "just parse the response", I remind myself that the model will produce JSON-adjacent-but-not-quite-JSON at least 0.5% of the time, and 0.5% is enough to break a pipeline at three in the morning.

The pattern. Ask for A response that conforms to a strict schema (JSON with types) rather than free-form prose you have to parse heuristically. OpenAI calls it response_format; Anthropic gets it via tool use., always, using the provider's native schema support. Treat the response the way you would treat a REST response: a typed payload, validated at the boundary, never parsed with a regex and a prayer.

The skeleton.

Example prompt
You extract <what> from <input type>.
Return a single JSON object with exactly these fields:
- <field>: <type>, <constraint>
- <field>: <type>, <constraint>
If a field cannot be determined from the input, set it to null. Never guess.
Return only the JSON. No prose before or after it.

Pair the prompt with a schema on the API side (tool use, response_format, or your framework's equivalent) and validate the object before anything downstream touches it. The prompt describes the shape; the schema enforces it; the validator catches the rest.

Before. "Read this paragraph and tell me the company and the revenue." You get a friendly sentence, sometimes a bullet list, occasionally a table. Your parser has a good week and then a very bad one.

After. The block below, which you can run live on this page:

Extract the company name and Q3 revenue from this paragraph as a JSON object with fieldscompany(string) andrevenueMillions(number)."Acme Corp reported Q3 revenue of $12.4M, up 18% year over year."Return only the JSON, no surrounding prose.

```json { "company": "Acme Corp", "revenueMillions": 12.4 } ```

The rule. If the output goes anywhere other than a human's eyes, it is structured. No exceptions. If a human reads it and also a system consumes it, return structured output and render the prose from it.

2. Role priming with concrete negatives

The problem. "You are a helpful assistant" is not a system prompt. It is a wish. Helpful assistants are confidently wrong, because nothing in "helpful" tells them where the edges are.

The pattern. Name what the assistant is not supposed to do, with concrete examples, and say what to do instead. The negatives do more work than the positives, because they carve the shape of the job out of everything the model could plausibly say.

The skeleton.

Example prompt
You are a <specific role> who helps <specific people> with <specific task>.

You do not <thing the model will otherwise drift into>.
You do not <second thing>.
You do not invent <the kind of fact that is expensive to get wrong>. If you are not sure, say "I don't know" and say what would settle it.
If the user asks about <adjacent topic>, redirect them to <the thing you actually support>.

Answer in <format and length>.

Before. "You are a helpful database assistant." Ask it about a JSON column and you get three paragraphs on why you might consider a document database.

After. Run this one:

You are a senior PostgreSQL engineer. You help developers write efficient PostgreSQL queries.You do not suggest ORMs.
You do not recommend migrating to MongoDB.
If the user asks about NoSQL, redirect them to PostgreSQL's JSONB features.User: I have a JSON column with nested data. What's the cleanest way to query a nested field?

# Querying Nested JSON in PostgreSQL For a JSON column with nested data, here are the cleanest approaches: ## Using JSONB (Recommended) If you're using **JSONB** (which you should for new projects), use the `->` and `->>` operators: ```sql -- Get the nested value as JSONB SELECT data->'user'->'profile'->'name' as name FROM my_table; -- Get the nested value as TEXT SELECT data->>'user'->>'profile'->>'name' as name FROM my_table; ``` ## Filtering on Nested Fields ```sql -- Find records where nested field equals a value SELECT * FROM my_table WHERE data->>'user'->>'email' = 'user@example.com'; -- Using JSONB comparison (more efficient) SELECT * FROM my_table WHERE data->'user'->>'email' = 'user@example.com'; ``` ## Using jsonb_extract_path() for Complex Paths ```sql -- More readable for deeply nested paths SELECT jsonb_extract_path(data, 'user', 'profile', 'name') as name FROM my_table; -- As text SELECT jsonb_extract_path_text(data, 'user', 'profile', 'name') as name FROM my_table; ``` ## Best Practices - **Use JSONB, not JSON** — JSONB is faster, supports indexing, and has more operators - **Create a GIN index** for frequent queries: ```sql CREATE INDEX idx_data_gin ON my_table USING GIN (data); ``` - **Extract to columns** if you query the same nested field repeatedly — it's faster than JSON extraction What's your specific use case? I can suggest more targeted optimizations.

I learned this the hard way at Rabobank, where a polite "helpful assistant" prompt kept confidently inventing API endpoints that did not exist. Adding three lines of "do not invent API paths; if you are not sure, say so" cut the hallucination rate to near zero. Three lines. Not a fine-tune, not a bigger model.

The rule. For every job, write down the two or three most expensive wrong answers the model could give. Each one becomes a "You do not" line with an instruction for what to do instead. Revisit the list every time you see a new failure in the logs; the negatives are the part of the prompt that grows.

3. Few-shot examples as the spec

The problem. Some tasks are hard to describe and easy to show. Classification and extraction almost always fall in this bucket: you can write a rubric, the model will nod, and then it will drift.

The pattern. Write two to five input/output pairs and paste them into the prompt. Not instructions. Two to five demonstrations beat a paragraph of rules every time. The model is a pattern-completion engine; feed it patterns, not specifications.. The examples are the specification, and they double as your first eval set.

The skeleton.

Example prompt
Classify each <input> as one of: <label A>, <label B>, <label C>.

Input: <realistic example of A>
Output: <label A>

Input: <realistic example of B, ideally one that looks a bit like A>
Output: <label B>

Input: <realistic example of C>
Output: <label C>

Input: <the actual input>
Output:

Before. "Classify this customer email as billing, technical, or escalation." Works on the ten emails you tested, drifts on the eleventh, and nobody can say why.

After. The same instruction with one example per label, where the examples are chosen to sit near the boundaries: a billing email that mentions an error message, a technical email from an angry customer. The drift disappears, because the model now knows where the edges are instead of guessing them.

The rule. Pick examples from real inputs, not invented ones, and pick the awkward ones. Easy examples teach the model nothing it did not already know. Keep the pairs in a file next to the prompt; they are the seed of your eval set, and when the task changes you update the examples before you touch the instructions.

What I don't do any more

I do not use The model's randomness knob. 0 picks the single highest-probability token; higher values widen the distribution. In production I use 0.3 for a sane middle: enough variance to avoid robotic phrasing, not enough to hallucinate. 0. I use 0.3. Determinism is a lie at scale; what you want is consistent shape (hence structured output) with reasonable variance in wording.

I do not pre-write the entire response structure in the prompt. Over-fitted prompts break the moment the input shifts. Write the minimum that gets you reliable output, then stop.

I do not stack clever techniques. Every extra instruction is another thing that can be misread. If a pattern is not paying its way in the evals, it comes out.

These three patterns cover perhaps 80% of production work. The other 20% is ordinary engineering: retries, rate limits, caching, evals. Those are not prompt problems, and no prompt will fix them.

What to do on Monday

  1. List every place a model's output is consumed by code rather than a person. Convert each one to structured output with a schema and a validator at the boundary.
  2. For your most important prompt, write down the three most expensive wrong answers it could give. Add a "You do not" line for each, with what to do instead.
  3. For every classification or extraction task, collect two to five real, awkward examples per label. Paste them in. Save them as the start of an eval set.
  4. Set temperature to 0.3 and stop arguing about it.
  5. Delete one clever instruction from your longest prompt and check whether anything gets worse. Repeat until something does.
Glossary
Structured output
Getting the model to return a strictly-typed object (JSON-with-schema) rather than prose you have to parse after the fact.
Few-shot
A prompting technique where you include 2-5 examples of the desired behaviour inline, to demonstrate the task rather than describe it.
Temperature
The model's randomness knob. 0 = always the same tokens, 1 = more creative. In production I use 0.3 for a sane middle.

Written by Yvo de Rooij, independent AI consultant and builder in Amsterdam.

Start a conversation