Prompting & Context
Talking to the model well is the single highest-leverage skill in the whole course — and unlike a keyboard shortcut, it transfers to every tool you’ll ever touch. Learn to say exactly what you want, hand over the right context, and steer with examples, and every model gets dramatically more useful.
A model is like a super-smart helper who just walked into the room and knows nothing about your problem yet. A prompt is what you tell it. If you mumble “fix it,” it has to guess what “it” is. If you say “the login button is grey when it should be blue, here’s the CSS,” it knows exactly what to do. Better question in, better answer out.
What a prompt really is
☺ Like you’re 10: Remember how the model finishes sentences one word at a time, always picking the most likely next word? A prompt is the beginning of the story you hand it. Change the beginning and you change every word that follows.
Under the hood, a language model does one thing: given some text, it predicts the next chunk of text, then the next, then the next (we unpack this in How models work). Your prompt is the text it conditions that prediction on. There is no separate “settings panel” where you configure the model’s behaviour — the prompt is the configuration. Everything you want — the topic, the tone, the format, the constraints — has to live in the words you send.
It helps to see a prompt as having two ingredients that get concatenated before the model ever runs:
- Instructions — what you want done. “Summarise this,” “find the bug,” “write a test.”
- Context — the material the answer depends on. The code, the error message, the data, the rules, the examples. Without it the model falls back on generic training-data knowledge, which is often plausible but wrong for your specific situation.
Modern chat models also receive a system prompt — a persistent instruction set the tool (Copilot, Claude, GPT, Gemini) prepends to steer role and behaviour — and a running conversation history. All of it is just more text stacked in front of the next-token prediction. The mental model to keep: the model only knows what’s in the window right now. It cannot see your screen, your repo, or your intentions unless those made it into the text.
The anatomy of a good prompt
☺ Like you’re 10: Ordering a pizza by shouting “food!” gets you something random. Saying “one medium pizza, half pepperoni, thin crust, cut in squares, ready in 20 minutes” gets you exactly what you pictured. A good prompt fills in all those blanks so nobody has to guess.
A strong prompt usually contains five parts. You won’t always need all five, but naming them makes it obvious what a weak prompt is missing:
| Ingredient | What it answers | Example fragment |
|---|---|---|
| Goal | What outcome do you want? | “Write a function that validates an email address.” |
| Context | What does it need to know? | “We’re in a TypeScript React app; emails come from a form field.” |
| Constraints | What must be true or avoided? | “No external libraries; must handle empty input; return a boolean.” |
| Examples | What does good look like? | “a@b.com → true, a@b → false, "" → false.” |
| Output format | How should the answer be shaped? | “Return only the function, no prose, with JSDoc.” |
The difference is not subtle. Here is the same request as a vague prompt and a specific one:
VAGUE ✗
"write me an email validator"
→ The model guesses a language, invents an API shape, maybe pulls
in a regex library, and returns three paragraphs explaining it.
You now have to redo half of it.
SPECIFIC ✓
"Write a TypeScript function isValidEmail(input: string): boolean.
Constraints: no external libraries; treat empty string as invalid;
reject addresses with no dot in the domain.
Examples: 'a@b.com'→true, 'a@b'→false, ''→false.
Return only the function with a one-line JSDoc comment — no prose."
→ You get exactly the function, in the right language, with the
edge cases you named already handled. First try.Notice the specific version didn’t require more expertise — just more decisions made up front. Every ambiguity you resolve is a guess the model no longer has to make (and a guess is where wrong answers come from). This same anatomy applies whether you’re typing into Copilot Chat, Claude, or a GPT prompt box — the box is different, the recipe is identical.
If a competent human colleague would have to ask you a clarifying question before starting, the model needs that answer in the prompt. Pre-answer the obvious questions.
Context is king — give the right stuff, not everything
☺ Like you’re 10: If a friend asks how to get to your house, you give them your street and the turns — not a map of the entire city. Too much stuff buries the part that matters, and they get lost anyway.
Beginners hear “context matters” and conclude “more context is better,” so they paste the whole file, the whole repo, the whole log. That backfires for three reasons:
- Every model has a finite context window. There’s a hard limit on how much text fits (we cover this in How models work). Dump too much and older, relevant material falls out the back.
- Signal gets diluted. The one function that matters is now buried in 2,000 lines of unrelated code. The model has to find the needle before it can help, and it can guess wrong about which part you care about.
- It’s slower and costlier. More tokens in means more latency and, on metered APIs, more money — for worse answers.
The skill is curation: give the relevant context, densely. For a bug, that’s usually the failing function, the exact error message, and the test that fails — not the entire module. When the relevant context genuinely is large or you don’t know which slice matters, that’s exactly the problem retrieval (RAG) exists to solve: fetch the few relevant chunks automatically instead of stuffing everything in by hand. Agentic tools do a version of this for you — Copilot’s agent mode and Claude Code read only the files they decide are relevant rather than the whole repo.
| Instead of dumping… | Give the model… |
|---|---|
| The entire 1,500-line file | The one function plus the types it uses |
| “It’s broken” | The exact error text and the input that triggered it |
| “Make it match our style” | Two or three examples of the style you mean |
| The full 10,000-line log | The stack trace and the 20 lines around the failure |
More context is only better if it’s relevant. Irrelevant context is worse than none — it actively pulls the model’s attention toward the wrong thing. Aim for high signal-to-noise, not maximum word count.
Show, don’t tell: few-shot examples
☺ Like you’re 10: It’s way easier to copy how someone folds a paper airplane by watching them do one than by reading a paragraph about folding. Show the model one finished example and it copies the pattern.
Describing a format in words is slippery — “make it concise,” “use a friendly tone,” “JSON-ish.” The model has to interpret those, and interpretations vary. Examples remove the ambiguity. Handing the model a couple of input→output pairs and asking it to continue the pattern is called few-shot prompting (zero examples is zero-shot; one is one-shot). It’s one of the most reliable steering tools you have, and it works identically across Claude, GPT, Gemini, and Copilot because it’s a property of how these models learn from patterns in context, not a vendor feature.
ZERO-SHOT (told, not shown) — inconsistent results "Classify these support tickets by urgency." FEW-SHOT (shown) — locks the format "Classify each ticket's urgency. Follow this pattern exactly: Ticket: 'Site is down, no one can log in' → urgency: HIGH Ticket: 'Typo on the About page' → urgency: LOW Ticket: 'Checkout fails for some EU customers' → urgency: MEDIUM Ticket: 'Password reset email never arrives' → urgency: ?"
Two or three examples are usually enough. Because the model matches the pattern, examples steer format and style far more precisely than any adjective can — the labels, the arrow, the capitalisation, the granularity all get copied. A few tips that make examples work harder:
- Make examples representative of the tricky cases, not just the easy ones — include the edge case you keep getting wrong.
- Be consistent across examples: if one uses
HIGHand another useshigh, you’ve taught the model that both are fine. - Show the shape you want the output in — if you need JSON, your examples should be JSON.
Ask for a plan first; iterate in small steps
☺ Like you’re 10: Before building a huge LEGO castle, you check the picture on the box so you don’t glue the wrong pieces together. Asking for a plan first is checking the picture — it’s way cheaper to fix a plan than to un-build a castle.
For anything non-trivial, don’t ask the model to do the whole job in one shot. Ask it to describe its plan first, read the plan, correct any wrong assumptions, then let it execute. A wrong direction caught at the plan stage costs you one sentence; caught after 200 lines of generated code, it costs you a rewrite.
"Before writing any code, list the steps you'd take to add rate-limiting to our API, and note any assumptions you're making. Wait for me to confirm before implementing."
Then work in small, coherent turns: one focused change per turn. There are concrete reasons this beats a mega-request:
- You catch wrong turns cheaply. A small diff is easy to review; a giant one hides mistakes.
- Each turn is easier to steer. “Now add error handling” is a clean instruction; “add error handling, logging, retries, and tests” invites the model to do all four half-well.
- Context stays clean. One coherent thread per change beats a tangled conversation where the model is juggling five half-finished ideas.
This “plan → confirm → small steps” rhythm is exactly how agentic tools are designed to be driven — it’s the same discipline behind the agent loop: reason, act, observe, adjust. You’re just doing the “confirm the reasoning” part by hand at the points that matter.
Professor Owl: Today we’ll teach Benny the Beaver to build a birdhouse. Watch what happens with a fuzzy instruction versus a clear one.
Foxy: Can I just say “build something”? He’s clever — he’ll figure it out, right?
Ellie the Elephant: He’ll guess — a boat, a dam, a dining table — and probably guess wrong. What he needs is context. I remember we wanted a red birdhouse, sized for two birds, with a round door.
Benny the Beaver: Perfect — now I know exactly what to build. Goal: a birdhouse. Constraints: red, two birds, round door. On it!
Timmy the Turtle: And before we call it done, let’s check the birdhouse matches the instructions — red, two birds, round door. If it doesn’t, we tell Benny what to adjust.
Patterns that transfer across tools
☺ Like you’re 10: Once you learn to ride one bike, you can ride any bike — the pedals and handlebars work the same. These prompting patterns are like that: learn them once, and they work in every AI tool you pick up.
The reason prompting is worth investing in is that the patterns are portable. They aren’t Copilot tricks or Claude tricks or GPT tricks — they’re consequences of how all these models work, so they carry over. Here are the workhorse patterns:
| Pattern | What it does | Example |
|---|---|---|
| Role / persona | Sets voice, expertise, and priorities the answer is written from | “You are a senior security reviewer. Audit this endpoint for injection risks.” |
| Step-by-step | Asks the model to reason through the problem before answering, which reduces careless jumps | “Think through the edge cases one by one, then give your answer.” |
| Output format | Pins the exact shape of the result so it’s usable without cleanup | “Respond as a JSON object with keys summary and risks.” |
| Few-shot | Demonstrates the pattern with examples instead of describing it | See the classification example above. |
| Constraints / negatives | Fences off what to avoid, not just what to do | “Don’t use external libraries. Don’t change the public API.” |
How the same pattern shows up in three different tools tells the whole story — you write the same kind of prompt, the tool just wires it in differently:
| Tool | Where the pattern lives |
|---|---|
| GitHub Copilot | Chat messages, plus repository custom instructions that act as a persistent system prompt for the project. |
| Anthropic’s Claude | The message you type, a system prompt, and project-level memory files that carry standing instructions across turns. |
| OpenAI’s GPT | The user message, a system/developer message, and “custom instructions” that persist your preferences. |
Different labels — custom instructions, system prompt, memory — same idea: a place to put the standing context and role so you don’t retype it every turn. Learn the pattern once and you’re fluent everywhere. (When you start writing standing instructions for a whole project, that’s the on-ramp to customizing your setup and later building agents.)
Be specific about the goal, hand over the relevant context, and show the output format with an example. Those three habits fix the large majority of bad answers — before you reach for any clever technique.
Debugging a bad answer (Foxy the detective)
☺ Like you’re 10: When a friend gives you a weird answer, a good detective doesn’t get mad — they ask “wait, did I even ask the question clearly?” Most bad answers come from a fuzzy question, not a dumb helper.
When the model returns something wrong, the beginner reflex is “this tool is dumb.” Foxy the detective knows better: most bad answers trace back to the prompt, not the model. Before you retry blindly, diagnose. Almost every bad answer falls into one of three buckets:
- Missing context. The answer is generic, invents details, or references things that don’t exist in your project? The model didn’t have what it needed. Fix: add the specific code, error, data, or rule it was missing.
- Ambiguous goal. The answer is technically fine but solves a slightly different problem, or picks an option you didn’t want? Your request had a fork in it and the model took the wrong branch. Fix: state the goal and constraints more precisely; pre-answer the ambiguity.
- Wrong tool for the job. You asked a chatbot to run code it can’t run, or fetch a live fact it can’t see, or edit files it has no access to? No prompt fixes a capability gap. Fix: switch to a tool with the right powers — an agent that can execute, a setup with retrieval for current facts, or MCP tools that connect to your systems.
A short diagnostic checklist, in the order Foxy runs it:
| Ask yourself… | If “no,” the fix is… |
|---|---|
| Did the model have every fact the answer depends on? | Add the missing context (code, error, data, rules). |
| Was there exactly one reasonable interpretation of my goal? | Remove the ambiguity; state the constraint you assumed. |
| Did I show an example of the output I wanted? | Add one or two input→output examples. |
| Is this even something a model can do without tools? | Switch to a tool with the right capability. |
| Did I ask for too much in one turn? | Break it into smaller steps; ask for a plan first. |
Run that list and you’ll fix the prompt far more often than you’ll need to blame the model. That’s the detective’s edge: better questions, better answers — every time, in every tool.
Take a recent “bad” answer you got from any AI tool. Run Foxy’s checklist against your original prompt: which bucket was it — missing context, ambiguous goal, or wrong tool? Rewrite the prompt to fix that one thing and send it again. Notice how much of the improvement came from your question, not the model.
(1) In one sentence, what is a prompt actually doing to the model’s next-token prediction? (2) Name the five ingredients of a well-formed prompt. (3) Why can adding more context make an answer worse? (4) When you get a bad answer, what are the three buckets Foxy checks — and which one can’t be fixed by rewording the prompt?
Check your answers
- What a prompt does: It’s the opening text the model conditions its next-token prediction on — the prompt is the configuration, so it steers every word that follows. There’s no separate settings panel; the topic, tone, format, and constraints all have to live in the words you send.
- The five ingredients: Goal (the outcome you want), Context (what it needs to know), Constraints (what must be true or avoided), Examples (what good looks like), and Output format (how the answer should be shaped). You won’t always need all five, but naming them shows what a weak prompt is missing.
- Why more context can hurt: Only relevant context helps — extra text overflows the finite context window, dilutes the signal so the model has to hunt for the part that matters, and costs more latency and money. Irrelevant context is worse than none because it actively pulls the model’s attention toward the wrong thing.
- Foxy’s three buckets: Missing context, ambiguous goal, and wrong tool for the job. The first two are prompt problems you can reword your way out of; “wrong tool for the job” is a capability gap that no rewording fixes — you switch to an agent, retrieval, or MCP tools instead.