Prompt engineering patterns that actually work
Role framing, few-shot, chain-of-thought, ReAct, and the anti-patterns that quietly wreck reliability.
Why this matters
Prompt engineering in 2026 is not "be a helpful assistant." It is a small set of structured patterns β Chain-of-Thought, ReAct, Reflexion, Few-shot, Self-consistency β that lift accuracy by 20-60% on hard tasks for free. Every senior agent you build composes these patterns inside framework code.
Learning objectives
- Use the 7 high-leverage prompt patterns and know when each one wins.
- Write a system prompt that is robust against off-topic and adversarial inputs.
- Measure the lift each pattern gives on your own task with a small eval set.
1. Anatomy of a great system prompt
A production system prompt has 6 sections. Memorise the order:
1. Role / persona (who is the model?)
2. Goal (what is success?)
3. Capabilities & tools (what can it do?)
4. Constraints (what must it never do?)
5. Output format (how must it respond?)
6. Examples (1-3 few-shot demos)Worked example:
You are an SQL analyst at a fintech company.
GOAL
Translate user questions into safe, performant SQL for our Postgres warehouse and explain results in plain English.
CAPABILITIES
You can call the tool `run_sql(query: str)` and `lookup_schema(table: str)`.
CONSTRAINTS
- NEVER write UPDATE, DELETE, INSERT, DROP, ALTER, GRANT, or REVOKE.
- If a query would scan more than 1 million rows, ask the user to narrow it.
- Refuse politely if the question is unrelated to our data.
OUTPUT FORMAT
First a 1-line plan, then the SQL fenced in ```sql ... ```, then the result, then a 2-line summary.
EXAMPLES
User: top 5 cities by revenue last quarter
Plan: aggregate revenue per city for Q-1, top 5
```sql
SELECT city, SUM(amount) AS revenue
FROM orders
WHERE created_at >= date_trunc('quarter', now()) - INTERVAL '1 quarter'
AND created_at < date_trunc('quarter', now())
GROUP BY city ORDER BY revenue DESC LIMIT 5;Summary: Mumbai led at βΉ4.1Cr, followed by Bengaluru and Delhi.
Why this works: every section gives the model an explicit handle the LLM can grip, instead of guessing.
---
## 2. The 7 high-leverage prompt patterns
### Pattern A β Zero-shot
Just ask. Works on easy tasks. Default starting point.
```text
Classify the sentiment of: "The flight was cancelled, again."Pattern B β Few-shot (criminally underused)
Add 2-5 examples in the prompt. Lifts accuracy 20-40% almost everywhere.
Classify sentiment as positive, negative, or neutral.
Text: "Loved the food."
Sentiment: positive
Text: "Service was slow but ok."
Sentiment: neutral
Text: "Never coming back."
Sentiment: negative
Text: "{user_input}"
Sentiment:Tip: include hard / borderline examples, not easy ones, so the model learns the boundary.
Pattern C β Chain-of-Thought (CoT)
Ask the model to think step-by-step before answering. Massively reduces errors on math, logic, multi-step questions.
Question: A train leaves Mumbai at 6:00 going 80 km/h. Another leaves Pune at 6:30 going 100 km/h on the same track. Mumbai-Pune is 150 km. When do they meet?
Think step by step before giving the final answer.For modern reasoning models (o1, o3-mini, claude-opus-4.7-thinking, gpt-5.5-thinking) the chain-of-thought happens internally and you do not need the trigger phrase β the API exposes a reasoning block.
Pattern D β Tree-of-Thought (ToT)
Explore multiple reasoning branches, then pick the best. Used for hard planning. Programmatically: ask the model to generate 3 candidate plans, score each, pick the highest.
You are solving: "Plan a 3-day Tokyo trip under $1500."
Step 1: generate 3 different *strategies* (budget, mid-range, luxury-on-points).
Step 2: for each strategy, write a full day-by-day plan.
Step 3: score each plan 1-10 on: cost, fun, feasibility.
Step 4: return the winning plan.Pattern E β ReAct (Reason + Act)
The pattern that powers every agent. Interleave Thought, Action, Observation:
Thought: I need today's date to plan ...
Action: get_date()
Observation: 2026-06-07
Thought: Now I need exchange rates ...
Action: get_rate(from="USD", to="JPY")
Observation: 154.20
Thought: Final answer ...You will not write this raw β frameworks (LangGraph, CrewAI, OpenAI Agents SDK) implement it. But the prompts under the hood look exactly like this. Read the react paper once.
Pattern F β Self-consistency
Sample N answers (e.g. N=5 with temperature=0.7), take the majority answer. Cheap accuracy boost on math/logic. Used in production by Anthropic for some workloads.
import collections, asyncio
async def majority_answer(question, n=5):
answers = await asyncio.gather(*(ask(question, temp=0.7) for _ in range(n)))
return collections.Counter(answers).most_common(1)[0][0]Pattern G β Reflexion / self-critique
Generate a draft β ask the model (or a critic model) to find flaws β ask for a revision. The cheapest 10-30% quality boost on writing/coding tasks.
[Step 1: generate]
Write a 200-word LinkedIn post about agentic AI.
[Step 2: critique]
Review the above post against these rubrics: clarity (1-10), original insight (1-10), CTA strength (1-10). For each below 8, give 1 concrete fix.
[Step 3: revise]
Rewrite incorporating the fixes.In LangGraph you build this as a 3-node graph: generate -> critique -> revise -> END if score>=8 else loop.
3. Prompt hygiene rules (production must-haves)
- Use Markdown headers (
##) and clear sections. LLMs respect structure. - Put fixed text first, variable text last. Helps prompt caching and "lost in the middle."
- Use XML or JSON tags for important content blocks in long prompts:Anthropic models are particularly trained on XML-like tags.
<document>{...}</document> <user_question>{...}</user_question> - Be explicit about refusals. "If the question is outside the documents, say: 'I do not know based on the provided context.'"
- Banlists for outputs. "Do not mention competitors X, Y, Z. Do not provide medical, legal, or financial advice."
- End with what to do, not what not to do. Models follow positive instructions better.
- Anchor the output schema in the prompt and enforce it programmatically. Belt + suspenders.
4. Common prompt failure modes (and the fix)
| Failure | Cause | Fix |
|---|---|---|
| Model adds prose around JSON | "Just JSON" plea | Use response_format={"type":"json_object"} or structured outputs |
| Model lies / hallucinates citations | No grounding | RAG + "If unsure, say 'I do not know.'" |
| Model is verbose | No length cap | "Answer in β€50 words." + max_tokens |
| Model refuses normal request | Over-aligned | Re-frame: "As a helpful assistant for our internal team..." |
| Few-shot biases output | Example imbalance | Balance + shuffle examples |
| Multi-turn drift | History grows | Summarise older turns into a "context block" |
| Lost in the middle | Long context | Put critical info first or last; use RAG |
5. Measuring lift (do not skip this)
Whenever you change a prompt, measure. Build a tiny eval set (20-50 inputs with expected outputs) and compare.
from collections import Counter
def grade(predicted: str, expected: str) -> bool:
return expected.lower() in predicted.lower()
def run_eval(prompt_fn, dataset):
results = [grade(prompt_fn(x["input"]), x["expected"]) for x in dataset]
return sum(results) / len(results)
base_acc = run_eval(zero_shot_prompt, dataset)
fewshot_acc = run_eval(few_shot_prompt, dataset)
print(f"zero-shot: {base_acc:.2f}, few-shot: {fewshot_acc:.2f}")When you can say in an interview "I shipped few-shot, accuracy went from 0.62 to 0.81 on a 200-pair eval set," you are no longer a junior.
Hands-on lab (2 hours)
Pick a real task: classify customer-support tickets into billing, technical, account, other.
- Build a 50-ticket dataset (write tickets manually or use synthetic ones from an LLM).
- Implement five prompts: zero-shot, few-shot (5 examples), CoT, few-shot+CoT, reflexion.
- Run each on the dataset; record accuracy and per-call cost.
- Print a markdown table comparing accuracy vs cost.
- Pick a winner and explain the trade-off in your README.
This single project, done well, is a portfolio piece.
Common pitfalls
- Adding "you are an expert" five times. Once is enough; the rest is noise.
- Shoving every rule in. Long system prompts hurt. Test removing rules.
- Few-shots that look the same. Diversify topic + difficulty.
- Reflexion for everything. It doubles cost; only use where needed.
- CoT in production output. Hide reasoning from end-users (
hide_reasoning=true).
Self-check
- Why does putting critical info at the start AND end help in long contexts?
- When should you NOT use chain-of-thought?
- What is the difference between ReAct and Reflexion?
- Why is self-consistency expensive but accurate?
- Show a 2-shot prompt for extracting
{date, amount, vendor}from invoices.
References
- ReAct paper: Yao et al. 2022 (https://arxiv.org/abs/2210.03629)
- Reflexion: Shinn et al. 2023 (https://arxiv.org/abs/2303.11366)
- Tree of Thoughts: Yao et al. 2023 (https://arxiv.org/abs/2305.10601)
- Self-Consistency: Wang et al. 2022 (https://arxiv.org/abs/2203.11171)
- Anthropic prompt-engineering guide: https://docs.claude.com/en/docs/build-with-claude/prompt-engineering/overview
- OpenAI prompt-engineering guide: https://platform.openai.com/docs/guides/prompt-engineering
- Lilian Weng: "Prompt Engineering" (https://lilianweng.github.io/posts/2023-03-15-prompt-engineering/)
Sign in to save your progress and earn badges.