Prompt Engineering
The cheapest, fastest lever for improving an LLM's behavior — no training required, just better instructions.
Zero-Shot, One-Shot, Few-Shot
- Zero-shot: ask the model to do a task with no examples, relying entirely on its pretrained knowledge and instruction-following ability.
- One-shot / few-shot: include one or a handful of example (input, output) pairs directly in the prompt before the real query. This works because the model conditions on the whole context — the examples establish a pattern it continues, without any weight updates.
Chain-of-Thought (CoT) Prompting
Instead of asking for a direct answer, prompt the model to "think step by step" before answering. For reasoning-heavy tasks (math, multi-step logic), this reliably improves accuracy — generating intermediate reasoning tokens gives the model more computation and more context to condition the final answer on, rather than forcing it to jump straight to a conclusion in one forward pass.
Self-consistency: sample multiple CoT reasoning paths for the same question and take a majority vote on the final answer — trades extra compute for higher accuracy. The real binomial math behind why this works whenever a single path beats a coin flip:
Tree-of-Thought: generalizes CoT by exploring multiple reasoning branches and backtracking, rather than committing to a single linear chain — more expensive, used for harder problems.
Reasoning Models vs. Prompted Chain-of-Thought
Everything above is a prompting technique — asking any model to write out its reasoning, which helps because it's more tokens of computation before the final answer, but the model was never specifically trained to do this well. A reasoning model (OpenAI's o-series, DeepSeek-R1, and similar) is a different thing entirely: a model additionally trained with RL (see Training Pipeline — GRPO) specifically to discover its own effective thinking strategies on math and code problems — backtracking, revisiting an assumption, trying an approach and abandoning it — rather than having a human write out what "good reasoning" should look like. The result at inference time is a model that spends a variable, often substantial amount of extra time and tokens on an internal reasoning process before committing to a final answer, without needing to be prompted to do so.
That extra inference-time compute is a real cost, not a free upgrade, which makes when to reach for one a genuine engineering decision:
- Worth it: problems with real, checkable structure where a first-pass answer is often wrong in a specific, findable way — a subtle bug, a multi-step proof, a logic puzzle. The gap between a non-reasoning and a reasoning model's accuracy is largest exactly here.
- Not worth it: factual lookups, straightforward formatting, casual/subjective questions, or anything where a first response is already reliably good — the extra latency (sometimes minutes, not seconds) buys accuracy you didn't need.
In production, this is usually a routing decision (see Routing & Supervisor Pattern): classify or detect whether a request is the kind that benefits from extended reasoning, and only pay the latency/cost premium for the requests that actually need it, rather than defaulting every request to the most expensive mode available.
Test-Time Compute Scaling: a Second Scaling Axis
What is it? Pretraining scale (more data, more parameters, more training compute — see Training Pipeline — Scaling Laws) was, for years, the only lever that reliably bought more capability. Reasoning models introduce a second, genuinely different one: test-time (inference-time) compute — spending more computation per request, after training is already finished, by letting the model think longer before answering.
How does it work? In practice this is a thinking budget: a token limit on the model's internal reasoning, configurable per request (Anthropic's API calls this budget_tokens — a target the model reasons against, not a strict floor it has to fill, with a documented minimum around 1,024 tokens). Turn it up, and the model gets more room to backtrack, double-check an intermediate step, and try more than one approach before committing to a final answer.
Why is it useful? It decouples "make the model smarter" from "retrain the model" — the same trained model gets measurably more accurate on hard reasoning problems just by giving it a bigger budget at inference time, no fine-tuning required. That's the entire reason it's treated as a distinct scaling axis, not just a knob.
What's the limitation? The relationship is logarithmic, not linear: Anthropic's own writeup states accuracy on math problems "improves logarithmically with the number of thinking tokens," and independent analysis of OpenAI's original o1 scaling chart found the same log-linear shape — exponentially more thinking compute buys roughly linear accuracy gains. Every one of those thinking tokens is also billed as real output, so past a point, a bigger budget mostly buys latency and cost, not correctness — the same routing discipline above applies here too, tuned per task rather than maxed out by default.
A related mechanism worth knowing: interleaved thinking lets a reasoning model think between tool calls in an agentic loop — reasoning about a tool's actual result before deciding what to call next — rather than only thinking once, up front, before the first action (see Agent Fundamentals — Tool Use). This is what lets a reasoning model course-correct mid-task instead of committing to a plan before it has any real feedback.
ReAct (Reasoning + Acting)
Interleaves reasoning steps with actions (tool calls) and observations: think → act → observe → think → .... This is the foundational pattern behind most tool-using agents (see Agents) — the model reasons about what it needs, calls a tool to get it, incorporates the result, and continues.
System Prompts & Structured Output
A system prompt sets persistent context/behavior for the whole conversation (role, tone, constraints) separate from the user's actual messages. For production applications, prompts often need to enforce structured output (JSON/XML) so downstream code can parse it reliably — done via explicit formatting instructions, few-shot examples of the format, or (increasingly) model features that constrain generation to match a schema directly.
Prompt Injection and Jailbreaking
Prompt injection: malicious text embedded in content the model processes (a webpage, a document, a tool's output) that tries to override the original instructions — a serious concern for any system where an LLM reads untrusted external content. Jailbreaking: techniques users apply directly to bypass a model's safety training. Defenses include strict separation of trusted instructions from untrusted data, input/output filtering, and models trained specifically to resist instruction override from non-privileged sources.
Failure Modes and Debugging
- Prompt sensitivity: small wording changes causing inconsistent outputs — mitigated with more explicit instructions, few-shot examples, and lower sampling temperature.
- The "lost in the middle" problem: models attend less reliably to information buried in the middle of a long context, even when it's technically within the context window — relevant to both prompting and RAG (see RAG). The documented shape of this effect:
This is one specific symptom of a broader phenomenon — see Context Engineering for context rot, the more general version of "more tokens in context, less reliable recall" that isn't just about position.
- Cost/latency optimization: shorter prompts, caching repeated prefixes, and choosing the smallest model that reliably handles the task all reduce production cost.
Next: Retrieval-Augmented Generation (RAG) — giving a model access to knowledge beyond what's in its weights.