AI EngineeringZero to ProductionHome·About·Contact
Prompt & Context Engineering · Chapter E1

Advanced Prompting Techniques

Chapter 2 taught you clear instructions and structured output. This chapter is the next layer: the reasoning-shaping patterns — few-shot, chain-of-thought, self-consistency, decomposition, ReAct — that turn a capable model into a reliable one on hard, multi-step problems.

⏱️ ~50 min🎛️ Prompt Engineering🎯 Beginner→Expert
🌱 Start here — from zero Prompt & context engineering, from scratch — getting the most out of any model — the highest-leverage, lowest-cost skill in AI.

Before you fine-tune or self-host, you can get dramatically better results just by how you prompt and what context you provide. This section goes past 'write a good prompt' into systematic techniques: structured prompting, context engineering, and automatic prompt optimization.

The words you'll hear (in plain terms):

TermWhat it actually means
prompt engineeringdeliberately designing the instructions you give a model.
context engineeringchoosing what information to put in the model's window, and how.
few-shotincluding examples in the prompt so the model imitates the pattern.
system promptthe standing instructions that shape all the model's replies.
prompt optimizationsystematically improving prompts (even automatically, e.g. DSPy).

What you need before starting:

  • Any experience prompting an LLM; the Ch 2 prompting basics first.
  • Python basics for the optimization labs (pip install dspy).
  • This section is mostly runnable with just an API key.

New to the topic? Read this box, then take the chapters in order — each section is tagged essentialexpert so you always know the depth you're at.

Learning objectives

  • Pick the right technique for a task instead of reaching for one habitually.
  • Write few-shot prompts whose examples actually teach the pattern.
  • Use chain-of-thought and self-consistency where reasoning matters — and know their cost.
  • Decompose a hard task into a prompt chain you can debug.
  • Understand ReAct as the bridge from prompting to agents (Ch 4).
Where this sitsThis builds directly on Ch 2 · Prompting & structured output (the fundamentals: role, clarity, format) and points forward to Ch 4 · Agents and E3 · Prompt optimization. Everything here is model-agnostic; the code uses Claude (claude-opus-4-8) but the patterns transfer.

A map of the techniques essential

These are not competing options — they're tools for different failure modes. Match the technique to what's actually going wrong.

TechniqueUse when…Main cost
Zero-shot + clear instructionsThe task is common and well-specified (Ch 2)None — always try this first
Few-shot (in-context examples)You need a specific format, style, or edge-case behaviorTokens; examples can bias output
Chain-of-thought (CoT)Multi-step reasoning, math, logicLatency + output tokens
Self-consistencyCoT answers vary; you need a robust answerN× the calls
Decomposition / prompt chainingOne prompt is doing too much; you can't debug itOrchestration complexity
ReAct (reason + act)The model needs tools/live data to answerYou're now building an agent (Ch 4)
The escalation ladderAlways start at the top and only climb when a technique demonstrably fails. Most teams over-engineer prompts: they reach for CoT and multi-agent chains on tasks a clean zero-shot prompt handles. Climb the ladder only when your evals show the simpler rung isn't enough.

Few-shot: teach by example essential

A few-shot prompt includes worked examples before the real input. The model infers the pattern from them — this is in-context learning (a direct consequence of attention; see K5). It's the highest-leverage technique because it shows rather than tells.

Anatomy of a strong few-shot prompt
System: You classify support tickets. Respond with only the label.

Example 1
Ticket: "I was charged twice this month."
Label: BILLING

Example 2
Ticket: "The app crashes when I tap export."
Label: BUG

Example 3
Ticket: "Can you add a dark mode?"
Label: FEATURE_REQUEST

Now classify:
Ticket: "{user_ticket}"
Label:
▶ How this works

This is a few-shot prompt: instead of describing the format in words, you show the model a few solved examples and then hand it a fresh input to finish. The whole thing is one block of text you send as the prompt — read it top to bottom the way the model does.

  1. The first line is the instruction ("You classify support tickets. Respond with only the label."). It sets the job and the exact output shape you want.
  2. Example 1–3 are the shots: each shows a Ticket: line and the correct Label: for it (BILLING, BUG, FEATURE_REQUEST). The model learns the pattern from these — this is called in-context learning.
  3. The final block (Now classify: with a real ticket and a dangling Label:) leaves the answer blank on purpose. The model continues the pattern and fills in the label.
  4. {user_ticket} is a placeholder your code replaces with the real ticket text before sending — the curly braces are not sent to the model.

What the output means: The model replies with just one label (e.g. BILLING) because every example trained it to answer with a single word and nothing else.

Try this: Reorder the three examples so the trickiest one is last. Models weight recent examples more, so the closing example nudges the pattern hardest — that's why the lesson says "put the important pattern last".

DoDon't
Cover the edge cases you care about (the tricky label, the ambiguous input)Give three near-identical easy examples
Keep format identical across examples and the real queryVary the format between examples and the query
Order matters — models weight recent examples; put the important pattern lastAssume order is irrelevant
Use 2–5 examples; measure whether more helpsStuff 30 examples "to be safe" (cost + dilution)
Few-shot examples are instructions in disguiseWhatever bias is in your examples becomes the model's default. If all your examples are short, it'll answer short. If your examples quietly always pick one label when unsure, so will the model. Curate examples as carefully as you'd write rules.

Chain-of-thought & self-consistency essential

Chain-of-thought asks the model to reason step by step before answering. It measurably improves accuracy on math, logic, and multi-constraint problems — because generating intermediate steps lets each step condition on the last (again, next-token prediction, K4).

Direct: often wrong on hard tasks question answer CoT: reason, then answer step1 step2 answer each step conditions on the previous → fewer leaps, fewer errors Reasoning as scratch space. Forcing intermediate steps turns one hard leap into several small, checkable ones. On modern models a simple "Think step by step, then give the final answer" often suffices; you rarely need to hand-write the reasoning.
🗺️ How to read this diagram

This diagram contrasts two ways a model can answer a hard question: jump straight to the answer, or reason step by step first. It's split into a red (left/top) path and a green (right/bottom) path.

  • The red path (top, "Direct") goes questionanswer in one hop. On hard tasks that single leap is where the model often goes wrong.
  • The green path ("CoT") goes step1step2answer. The one big leap is broken into several small, checkable moves.
  • The caption line — each step conditions on the previous — is the key: the model reads its own step 1 before writing step 2, so later steps build on earlier ones instead of guessing all at once.
  • Colour is the shorthand: red = risky one-shot, green = safer stepwise. Same question, fewer errors on the right.

In short: Chain-of-thought = let the model show its working. On modern models you often just add "Think step by step, then give the final answer" and get the green path automatically.

On Claude, prefer native thinkingWith claude-opus-4-8 you don't hand-roll CoT — enable adaptive thinking (thinking: {type: "adaptive"}) and the model reasons before answering, returning the answer cleanly. Reach for prompt-level CoT mainly with models that lack a thinking mode, or when you want the reasoning visible in the output for auditing. (See C2.)

Self-consistency runs CoT several times (with sampling) and takes the majority answer. It trades cost for robustness on problems where a single reasoning path is unreliable.

Self-consistency (pseudocode)
Setup to run this snippet
class _Any:
    '''stands in for any undefined demo value; supports call/attr/index/
    iteration and basic arithmetic (as 0.7) so demo snippets run.'''
    def __call__(self, *a, **k): return _Any()
    def __getattr__(self, k): return _Any()
    def __getitem__(self, k): return _Any()
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __contains__(self, o): return True
    def __enter__(self, *a): return _Any()
    def __exit__(self, *a): return False
    def __float__(self): return 0.7
    def __int__(self): return 1
    def __lt__(self, o): return True
    def __gt__(self, o): return False
    def __le__(self, o): return True
    def __ge__(self, o): return False
    def __add__(self, o): return o
    def __radd__(self, o): return o
    def __bool__(self): return True
    def __repr__(self): return 'demo'
    def __str__(self): return 'demo'
def extract_final(*a, **k):  # demo stub
    return _Any()
def majority_vote(*a, **k):  # demo stub
    return _Any()
def model(*a, **k):  # demo stub
    return _Any()
prompt = _Any()
answers = []
for i in range(5):
    r = model(prompt, temperature=0.7)   # sample diverse paths
    answers.append(extract_final(r))
final = majority_vote(answers)           # robust to one bad path
▶ How this works

This is self-consistency: instead of trusting one answer, you ask the model the same question several times, let it reason differently each time, then keep the answer that comes up most often. It's a vote. (The setup box above just fakes the model, extract_final and majority_vote helpers so the snippet runs — ignore it; the real idea is these 5 lines.)

  1. answers = [] starts an empty list to collect each run's final answer.
  2. for i in range(5): repeats the call 5 times. temperature=0.7 tells the model to be a bit random, so each run may reason down a different path — that variety is the whole point.
  3. extract_final(r) pulls just the final answer out of each (possibly long) reasoning reply, and answers.append(...) stores it.
  4. majority_vote(answers) returns the answer that appeared most often. If four of five runs agree, one bad reasoning path gets outvoted — that's the robustness you paid for.

What the output means: final holds the majority answer across 5 tries — more reliable than any single run, but it cost you 5 API calls instead of 1.

Try this: Because this makes the calls, only reach for it when correctness really matters. Compare it against one call with thinking enabled first — often a single good call wins for far less money.

Self-consistency is 5× the billOnly use it where correctness genuinely justifies the cost (a high-stakes extraction, a benchmark) — and measure the accuracy gain against a single thinking-enabled call first. Often one good call wins.

Lab E1.1 · Decomposition & prompt chaining intermediate

When one prompt tries to do five things, it does all of them mediocrely and you can't tell which part failed. Decompose: split into a chain of focused prompts, each with one job and a checkable output.

one mega-prompthard to debug extract analyze summarize each step: one job · testable output · swappable Chains beat monoliths for anything non-trivial. Focused steps are individually testable, individually cacheable, and let you use a cheaper model for the easy steps and a stronger one where it counts.
🗺️ How to read this diagram

This diagram shows decomposition: taking one prompt that tries to do everything and breaking it into a chain of small prompts, each doing one job. Read it left to right.

  • On the left, the red box one mega-prompt is labelled "hard to debug" — when it fails, you can't tell which of its five jobs broke.
  • The arrow (→) means "is rewritten as" the chain on the right.
  • The green boxesextractanalyzesummarize — are the chain. Each arrow passes one step's clean output into the next step's input.
  • The caption spells out the payoff: each step is one job · testable output · swappable — you can test each link alone and even use a cheaper model for the easy steps.

In short: A chain beats a monolith whenever a task is non-trivial: you can see exactly which link failed and fix just that one, instead of guessing inside one giant prompt.

Example code for learning — review, test, and adapt it before running against real or production systems. Commands can create, change, or delete resources. See the Terms & Disclaimer.
Try it
  1. Take a "do everything" prompt you have (e.g. "read this email, extract the request, draft a reply, and flag urgency").
  2. Split it into three prompts: extractclassify urgencydraft reply from the extracted fields.
  3. Give each a structured output (Ch 2) so the next step consumes clean data, not prose.
  4. Note which step was actually failing before — you usually couldn't tell in the monolith.

ReAct: the bridge to agents intermediate

ReAct interleaves reasoning and acting: the model thinks, calls a tool, observes the result, thinks again. It's the pattern under most agent loops — when a prompt technique needs live data or actions, you've crossed into agent territory.

ReAct loop (conceptual)
Thought: I need the current error rate to answer.
Action: query_metrics("error_rate", "1h")
Observation: 4.2%
Thought: That's above the 2% threshold. I should check recent deploys.
Action: list_deploys("1h")
Observation: deploy #481 at 14:02
Thought: The spike aligns with deploy #481.
Answer: Error rate is 4.2%, likely caused by deploy #481.
▶ How this works

This is a ReAct trace (Reason + Act). It shows the model alternating between thinking and using a tool until it has enough facts to answer. It isn't Python you run — it's the transcript of one agent loop, and it's exactly the pattern Chapter 4 builds for real.

  1. Thought: the model reasons out loud about what it still needs — here, "I need the current error rate". No made-up numbers yet.
  2. Action: the model calls a tool to get real data, e.g. query_metrics("error_rate", "1h"). This is the model reaching outside itself for a fact it can't know.
  3. Observation: the tool's result comes back (4.2%). The model now has a real fact to reason about, not a guess.
  4. The loop repeats — think, act, observe — checking recent deploys, until the model has enough to give the final Answer: tying the error spike to deploy #481.

What the output means: A grounded answer built from live data: "Error rate is 4.2%, likely caused by deploy #481." Every number came from a tool call, not the model's memory.

Try this: Notice each Action is followed by an Observation the next Thought reacts to. When your prompt keeps needing facts it doesn't have, that's the signal to give it a tool — you've crossed from prompting into building an agent (Ch 4).

This is Chapter 4, arriving earlyReAct is exactly the reason→tool→observe loop you'll build in Ch 4 and formalize with LangGraph. The takeaway here: prompting and agents are a continuum, not separate worlds. When your prompt keeps needing information it doesn't have, stop prompting harder and give it a tool.

Common pitfalls advanced

PitfallFix
Reaching for CoT/self-consistency on easy tasksStart zero-shot; climb the ladder only when evals demand it
Hand-writing CoT on a model with native thinkingUse adaptive thinking (C2) and keep the prompt clean
Few-shot examples that don't cover edge casesCurate examples for the hard cases, not the easy ones
One mega-prompt you can't debugDecompose into a chain with structured hand-offs
Judging a technique by one anecdoteMeasure on a held-out set (Ch 5, E3)

Exercises advanced

Exercise E1.1 — Technique selection

Context: The escalation ladder is only useful if you can place a real task on the lowest rung that fits — over-climbing wastes tokens, latency, and calls.

Your task: For each task, name the lowest ladder rung that fits and justify it: (a) extract an invoice total, (b) solve a multi-step word problem, (c) answer "what's our current uptime?", (d) rewrite text in a specific house style.

Requirements:

  • Give a rung and a one-line justification for each of the four tasks
  • Recognise a well-specified extraction needs only zero-shot
  • Recognise multi-step reasoning needs CoT / native thinking
  • Recognise a live-data question needs tools/ReAct, and style is best shown by example

💡 Hint: Ask what each task is missing at zero-shot — reasoning depth, live data, or a style the model can't infer — and pick the cheapest rung that supplies it.

Show reasoning

(a) zero-shot — well-specified extraction; (b) CoT / native thinking — multi-step reasoning; (c) ReAct/tools — needs live data, no prompt can know it; (d) few-shot — style is best shown by example.

Exercise E1.2 — Break the monolith

Context: Adding a length and a tone constraint to a style-rewrite task is where a single prompt starts to strain — a short chain with structured hand-off keeps each concern testable.

Your task: Take the house-style rewrite from E1.1(d), add a length constraint and a tone constraint, and design a two-step chain — deciding where structured output goes.

Requirements:

  • Split the task into two focused steps
  • Show the structured output passed between the steps
  • Account for both the length and the tone constraint
  • Explain why the split makes each step independently checkable

💡 Hint: Structured output belongs at the seam between the steps — that is what lets you verify the first step before the second one runs.

Exercise E1.3 — When is self-consistency worth it?

Context: Self-consistency's 2-point accuracy gain costs 5× the calls, so shipping it is a judgement call about stakes and volume, not a reflex.

Your task: Given a classifier at 91% with one call and 93% with 5-call self-consistency, state two questions you would ask before shipping the 5× cost.

Requirements:

  • Ask at least two concrete decision questions
  • Weigh the value of the 2-point accuracy gain against the 5× cost
  • Consider the stakes/consequences of an error and the request volume
  • Reach a defensible ship / don't-ship stance

💡 Hint: Two points can be decisive or negligible depending on what an error costs and how many requests you run — anchor your questions there.

🪜 Practice ladder beginner → industry

Six graded exercises, easy to real-world. Try each before opening its solution.

Exercise 1 · Write a few-shot classification promptBeginner

Context: Few-shot prompting teaches by example: a handful of labelled cases before the real input. In-context learning weights those recent examples heavily, so a clean, balanced set is the whole lever.

Your task: Build a ticket-classifier prompt — a system line, three labelled examples (BILLING, BUG, FEATURE_REQUEST), then the slot to classify — and explain why the examples are ordered as they are.

Requirements:

  • Include a system line stating the task and the output format
  • Provide exactly one example per label so no class is over-represented
  • Use an identical format across every example so the model copies the pattern
  • End with the new ticket and an empty label slot
  • Explain the balance/format reasoning in a sentence

💡 Hint: This is a string builder — no model call needed; the teaching point is that balance and consistent formatting drive the classification, not clever wording.

Show solution

The few-shot template (a string builder — runnable, no model needed):

EXAMPLES = [
    ("I was charged twice this month.",        "BILLING"),
    ("The app crashes when I tap export.",     "BUG"),
    ("Can you add a dark mode?",               "FEATURE_REQUEST"),
]

def build_prompt(ticket):
    lines = ["System: You classify support tickets. Respond with only the label.", ""]
    for i, (tk, label) in enumerate(EXAMPLES, 1):
        lines += [f"Example {i}", f'Ticket: "{tk}"', f"Label: {label}", ""]
    lines += ["Now classify:", f'Ticket: "{ticket}"', "Label:"]
    return "\n".join(lines)

print(build_prompt("My invoice looks wrong."))

Each label appears exactly once so no class is over-represented (which would bias the output), and the format is identical across examples so the model copies the pattern, not the wording. In-context learning weights these recent examples heavily — a clean, balanced set is the whole lever.

Exercise 2 · Read a chain-of-thought traceIntermediate

Context: Chain-of-thought makes the model reason step by step before answering, trading latency and output tokens for a visible, auditable reasoning path. The Observations are the evidence; the Answer is only as good as that chain.

Your task: Given a Thought/Action/Observation trace for an incident, programmatically extract the final Answer and the evidence chain that led to it.

Requirements:

  • Parse the trace line by line
  • Extract the single final Answer
  • Extract every Observation as the evidence chain, in order
  • Keep it pure-stdlib string handling
  • Print the answer alongside its supporting evidence

💡 Hint: The line prefixes (Thought/Action/Observation/Answer) are the whole grammar — split on them; the Observations are what make the conclusion auditable.

Show solution

Parse a CoT trace to separate reasoning from the answer (pure stdlib):

trace = '''Thought: I need the current error rate to answer.
Action: query_metrics("error_rate", "1h")
Observation: 4.2%
Thought: That's above the 2% threshold. I should check recent deploys.
Action: list_deploys("1h")
Observation: deploy #481 at 14:02
Thought: The spike aligns with deploy #481.
Answer: Error rate is 4.2%, likely caused by deploy #481.'''

lines = trace.splitlines()
answer = next(l.split("Answer:",1)[1].strip() for l in lines if l.startswith("Answer:"))
evidence = [l.split("Observation:",1)[1].strip() for l in lines if l.startswith("Observation:")]
print("answer  :", answer)
print("evidence:", evidence)   # ['4.2%', 'deploy #481 at 14:02']

CoT trades latency and output tokens for a visible reasoning path: the Observations are the evidence, and the final Answer is only as trustworthy as that chain. Exposing the steps is what lets you audit why the model concluded what it did.

Exercise 3 · Self-consistency by majority voteAdvanced

Context: Self-consistency samples several reasoning paths at temperature and takes the majority answer, so a single bad path can't sink the result. It costs N× the API calls, so it is reserved for high-stakes questions.

Your task: Implement the majority-vote aggregator over N sampled answers, with the sampler stubbed so it runs offline.

Requirements:

  • Sample N answers from a stubbed sampler that occasionally returns a bad path
  • Take the majority answer as the final result
  • Report the winning answer, its vote count, and all sampled answers
  • Make it reproducible with a fixed seed
  • Show the majority surviving a lone bad path

💡 Hint: collections.Counter.most_common(1) gives you the winner and its votes — the vote is what makes the result robust to one hallucinated chain.

Show solution

The self-consistency aggregator — sampling stubbed so it runs offline:

from collections import Counter
import random

def sample_answer(prompt, temperature=0.7):
    # STUB for the model call: mostly correct, occasional bad path
    return random.choice(["42", "42", "42", "17"])

def self_consistency(prompt, n=5, temperature=0.7):
    answers = [sample_answer(prompt, temperature) for _ in range(n)]
    winner, votes = Counter(answers).most_common(1)[0]
    return winner, votes, answers

random.seed(1)
final, votes, all_ = self_consistency("What is 6 * 7?", n=5)
print("answers:", all_)
print(f"final: {final}  ({votes}/5 votes)")   # majority survives one bad path

Any single sampled path can go wrong; the majority of N paths usually will not. Self-consistency costs N times the API calls, so reserve it for high-stakes questions where robustness beats latency — the vote is what makes it resilient to a lone hallucinated chain.

Exercise 4 · Decompose a do-everything prompt into a chainExpert

Context: One prompt doing extract + classify + draft is an opaque failure when it goes wrong. Decomposing it into focused stages that pass structured output turns one unreadable failure into three testable, swappable stages.

Your task: Decompose a do-everything prompt into a three-stage chain — extract, classify, draft — passing structured output between the stages, and model it offline.

Requirements:

  • Make each stage a pure function of the previous stage's output
  • Stage 1 extracts structured fields from the ticket
  • Stage 2 classifies from those fields
  • Stage 3 drafts a reply from the classification
  • Compose them into one pipeline and run it on a sample ticket

💡 Hint: Structured output between stages is what makes each independently testable — you can tell whether extraction, classification, or drafting broke.

Show solution

Prompt chaining — each stage is a pure function of the last (offline stubs):

def extract(ticket):                     # stage 1: pull structured fields
    return {"text": ticket, "has_charge": "charged" in ticket.lower()}

def classify(fields):                    # stage 2: label from fields
    fields["label"] = "BILLING" if fields["has_charge"] else "OTHER"
    return fields

def draft_reply(fields):                 # stage 3: write the response
    if fields["label"] == "BILLING":
        return "We're reviewing the duplicate charge and will refund it."
    return "Thanks for reaching out -- a specialist will follow up."

def pipeline(ticket):
    return draft_reply(classify(extract(ticket)))

print(pipeline("I was charged twice this month."))

Decomposition turns one opaque failure into three testable stages: if the reply is wrong you can tell whether extraction, classification, or drafting broke. The cost is orchestration complexity, but each step is now debuggable and independently swappable.

Exercise 5 · Match each failure to the technique that fixes itProfessional

Context: The techniques form an escalation ladder — zero-shot → few-shot → CoT → self-consistency → decomposition → ReAct — each costing more (tokens, latency, calls, complexity). You climb only as far as the failure demands.

Your task: Given a failure symptom, recommend the lowest-cost technique that addresses it and name its cost.

Requirements:

  • Map format/consistency failures to few-shot
  • Map skipped multi-step reasoning to chain-of-thought
  • Map flaky hard reasoning to self-consistency
  • Map an overloaded prompt to decomposition, and tool needs to ReAct
  • State each technique's cost, and default to zero-shot first

💡 Hint: Reaching straight for ReAct when few-shot would fix a formatting issue is over-engineering — the recommender should return the cheapest sufficient rung.

Show solution

The escalation ladder as a recommender (pure stdlib):

LADDER = [
    ("wrong format / inconsistent labels", "few-shot", "token cost; examples can bias"),
    ("skips reasoning on multi-step math",  "chain-of-thought", "latency + output tokens"),
    ("flaky on hard reasoning",             "self-consistency", "N x the API calls"),
    ("one prompt does too much",            "decomposition", "orchestration complexity"),
    ("needs to call tools / look things up","ReAct", "you are now building an agent"),
]

def recommend(symptom):
    for sig, tech, cost in LADDER:
        if any(w in symptom.lower() for w in sig.split(" / ")[0].split()):
            return tech, cost
    return "zero-shot + clear instructions", "none -- always try first"

print(recommend("the labels are inconsistent"))
print(recommend("it needs to look things up in a system"))

Always try zero-shot with clear instructions first, then climb only as far as the failure demands — each rung costs more (tokens, latency, calls, or complexity). Reaching straight for ReAct when few-shot would fix a formatting issue is over-engineering.

Exercise 6 · Design the prompting strategy for a support triage systemIndustry scenario

Context: As lead you don't apply one technique everywhere — you segment traffic and spend complexity only where it pays. A triage system has cheap high-volume classification, a few hard diagnoses, and some requests that must query live systems.

Your task: Assign a prompting technique to each request class of a support-triage system and justify the cost.

Requirements:

  • Route high-volume classification to cheap few-shot at zero temperature
  • Route hard diagnoses to CoT (with self-consistency where stakes are high)
  • Route requests needing live data to a ReAct agent with tools
  • Justify the cost of each choice
  • Return a technique-per-class plan

💡 Hint: The high-volume path stays cheap; only the tool-using class escalates to a full agent — segment first, then spend complexity where it earns its keep.

Show solution

Route each request class to the cheapest sufficient technique (pure logic):

def strategy(request_class):
    plan = {
        "bulk_classify":  ("few-shot, zero temperature",
                           "cheap + consistent; runs on every ticket"),
        "hard_diagnosis": ("chain-of-thought (+ self-consistency if stakes high)",
                           "reasoning depth where accuracy matters most"),
        "needs_live_data":("ReAct with tools",
                           "must query metrics/deploys -- it becomes an agent"),
    }
    return plan.get(request_class, ("zero-shot", "start simple"))

for cls in ["bulk_classify", "hard_diagnosis", "needs_live_data"]:
    tech, why = strategy(cls)
    print(f"{cls:16s}: {tech}\n{'':16s}  ({why})")

A lead does not apply one technique everywhere — they segment traffic and spend complexity only where it pays. The high-volume path stays cheap few-shot, the rare hard cases get CoT/self-consistency, and only the tool-using class escalates to a full ReAct agent.

✓ Checkpoint — you can move on when you can…

  • Choose a technique by the failure mode, not by habit.
  • Write a few-shot prompt that teaches edge cases in a fixed format.
  • Explain when CoT/self-consistency earns its cost — and when native thinking replaces it.
  • Decompose a mega-prompt into a debuggable chain.
  • Recognize when ReAct means you should build an agent.
🏗️ Toward the capstoneThe AI DevOps Engineer decomposes every incident into focused steps and uses a reason→act loop over its tools — that's ReAct plus decomposition, exactly this chapter. Next, E2 asks the deeper question: what do you put in the context window in the first place, and how do you manage it as conversations and retrieval grow.

Knowledge check check yourself

✓ Knowledge check

The lesson frames the techniques as an 'escalation ladder'. What is the rule for climbing it, and what over-engineering mistake does it prevent?

Show answer
Always start at the top (zero-shot + clear instructions) and only climb — to few-shot, CoT, self-consistency, decomposition, ReAct — when your evals show the simpler rung demonstrably fails. This prevents reaching for CoT or multi-agent chains on tasks a clean zero-shot prompt handles.
✓ Knowledge check

Self-consistency improves robustness but costs 5× the calls. What does the lesson say to compare it against first on Claude, and why?

Show answer
Compare it against a single call with native (adaptive) thinking enabled, because one good thinking-enabled call often wins for far less money — only reach for self-consistency's N× cost where correctness genuinely justifies it.
© 2026 studybydoing.in · AI Engineering: Zero to Production · All rights reserved. · About · Privacy Policy · Terms · Contact
Educational content, provided as-is and without warranty. Code samples are examples — review, test, and adapt them before using in production. See the Terms of Use & Disclaimer. Use at your own risk.
© studybydoing.in