Lesson 6 of 8 · 17 min read
Prompting and Context Engineering: Writing Effective Instructions and Supplying Context to Copilot
Before Copilot Chat can help with a task, the prompt itself has to carry enough information for the model to act on.
1. Composing Effective Copilot Chat Prompts
Before Copilot Chat can help with a task, the prompt itself has to carry enough information for the model to act on. GitHub's own prompt-engineering guidance for Copilot Chat, corroborated by GitHub's best-practices page, documents four techniques for composing clearer prompts. These are general-purpose Copilot Chat prompting techniques — distinct from the code-review-scoped custom-instruction composition guidance covered elsewhere in this course, which governs how you write files like .github/copilot-instructions.md, not how you phrase a Chat message. Do not treat the two as interchangeable.
1. Progressive specificity
Start with a broad request, then add one concrete constraint at a time rather than trying to specify everything up front.
Before:
Improve this function.
After:
Refactor calculateShippingCost in pricing/shipping.py to short-circuit when order.items is empty.
Then, once you see the result:
Now also handle the case where order.destination is None.
2. Leverage examples
Supply a sample input, output, or existing implementation so Copilot has a concrete target rather than an open-ended description.
Before:
Write a function that formats these dates.
After:
Write format_invoice_date(dt) that turns 2026-09-02T14:30:00Z into Sep 2, 2026, matching the format already used in invoices/templates.py.
3. Decompose complex tasks
Break a large request into smaller, sequential requests rather than asking for an entire feature in one prompt.
Before:
Add retry logic, logging, and a circuit breaker to the payment client.
After: three separate prompts — first the retry logic, then logging once retries work, then the circuit breaker once both are reviewed.
4. Eliminate ambiguity
Name the exact function, file, symbol, or library instead of a vague pronoun like "this" or "it," especially when working with less common libraries Copilot may not infer correctly from context alone.
Before:
Fix this, it's throwing an error.
After:
OrderService.submit() in orders/service.py raises KeyError when payload['currency'] is missing — add a default of 'USD'.
These four techniques are tools to reach for as a task calls for them, not a fixed checklist to run through on every Chat request — a quick loop-body completion needs none of them, while a genuinely ambiguous, multi-step request may call for two or three at once. Applying whichever techniques fit the task at hand is the foundation the rest of this chapter builds on: better wording first, then better-supplied context (Sections 2 and 3), then better mode choice and validation (Section 4).
2. Supplying Context and Managing the Chat Interaction
Wording the prompt well is only half the job — Copilot Chat also needs the right code in view. GitHub's prompt-engineering guidance, corroborated by its best-practices page's guidance on guiding Copilot toward better outputs, documents five habits for supplying context and managing an ongoing chat interaction:
- Open or highlight the relevant files. Open or highlight the file or code block you're actually asking about, so Copilot has it available as context when you prompt.
- Invoke chat participants for questions that span more than one file. Rather than pasting multiple files into a prompt by hand, ask Copilot to reason across the whole workspace or project directly — the exact keywords for doing this differ by IDE and are covered mechanically in the next section.
- Iterate on unsuccessful responses. If a response misses the mark, don't accept it and move on — modify the request with the missing constraint or referent, or restart the thread with a clearer prompt using the techniques from Section 1.
- Manage chat-thread history deliberately. Start a new thread per distinct task rather than letting one long thread accumulate unrelated context, and prune threads that are no longer relevant so stale context doesn't leak into new answers.
- Keep the surrounding codebase itself high-quality. Copilot reads your repository's naming, comments, modularity, and tests as input when producing suggestions — a well-organized, well-tested codebase gives it better material to work from than a tangled one, independent of how good any single prompt is.
These are conceptual habits. The exact syntax for opening files, invoking participants, and running quick commands in your specific IDE follows next.
3. Concrete Per-IDE Context-Injection Syntax
GitHub's operational how-to page for Copilot Chat in the IDE documents the concrete, current mechanical syntax for the context-supply habits from Section 2 — that is, the existence and names of these tokens, not a description of what each one does internally. This syntax is more likely to drift with product releases than the conceptual techniques in Sections 1–2 — treat the list below as a snapshot of documented names, and check current GitHub documentation for what each one actually does before relying on it.
VS Code chat variables
Type # in the chat box: #selection, #file, #editor, #codebase, #git.
Chat participants
Type @ in the chat box:
@workspace,@vscode, and@terminalin VS Code@projectin JetBrains IDEs
File references
Visual Studio and JetBrains both support #file notation.
Slash commands
Type / in the chat box for: /fix, /tests, /new, and /newNotebook.
This syntax is documented across VS Code, Visual Studio, JetBrains, and Eclipse — but that coverage is uneven. Eclipse falls within the documentation's stated scope, yet no Eclipse-specific token names are documented for it: none of the chat variables, participants, file-reference notation, or slash commands listed above are attributed to Eclipse. The slash-command list above has the same gap in a different shape — it is not attributed to any particular IDE in the course's evidence, so don't assume it's VS-Code-specific either, or specific to any other single IDE listed above. Use the reference above only for the IDEs and commands it actually names, and check current GitHub documentation before relying on a token for an IDE this section doesn't name it for.
Applying Sections 1 and 2 together — author-supplied orientation, not documented GitHub behavior
As one way to connect this token list back to the earlier techniques, you might scope a request with #selection or #file when applying Section 1's "eliminate ambiguity" technique, reach for @workspace or @project when applying Section 2's habit of invoking a participant for a question spanning more than one file, and try /tests or /fix once you've decomposed a task into a small enough step.
4. Choosing an Interaction Mode and Validating Suggestions
GitHub's best-practices documentation gives explicit, documented guidance on which interaction mode fits a task, and on validating what comes back before you use it. Present this as GitHub's own recommendation — it describes what GitHub advises, not a guaranteed or verified fact about how Copilot behaves internally.
Choosing a mode
- Inline completions are recommended for snippet completion and test generation — small, localized, in-place work where you're extending code you're already looking at.
- Copilot Chat is recommended for questions, larger sections of code, and persona-style prompting — for example, asking Copilot to "act as a senior C++ developer" reviewing a module. Chat is also the natural home for the prompt-composition and context-supply techniques from Sections 1–3, since it accepts a full written request rather than continuing code in place.
This is a guideline about which surface to reach for, not a restatement of what each mode is — the underlying interaction-mode taxonomy itself is covered elsewhere in this course.
Validating a suggestion before use
GitHub's documented guidance is not to accept a suggestion uncritically. Before using it:
- Review it for correctness against what you actually asked for.
- Ask Copilot to explain the suggestion if the reasoning isn't obvious.
- Check it for functional and security issues the way you would any other code change.
- Pair it with a linting or code-scanning pass rather than treating Copilot's own output as sufficient validation on its own.
Combined with the prompting and context technique from Sections 1–3, this validation habit closes the loop: word the request well, supply the right context, choose the surface suited to the task, and then check the result before it goes anywhere near production.
5. The Four Context-Supply Mechanisms
GitHub's canonical conceptual documentation defines context as the information Copilot gathers to produce more relevant responses. Everything in Sections 1–4 was about shaping and directing that information at the prompt level; this section names the four current mechanisms GitHub documents for supplying it structurally.
- Model Context Protocol (MCP) — integrates other systems and tools so Copilot can read from or act on them.
- Copilot Spaces — organizes and shares contextual information for Chat and team collaboration. This course's evidence does not establish Spaces' capability, plan availability, or usage detail beyond its name and role as one of the four mechanisms, so this course states only that Copilot Spaces exists as one of the four mechanisms and stops there — do not infer or assume any specific Spaces feature beyond its name.
- Repository indexing — draws on indexed, repository-specific knowledge so Copilot's responses can reflect the actual codebase rather than generic patterns.
- Content exclusion — restricts which files or paths Copilot may access, letting a team keep specific parts of a repository out of what Copilot reads.
These four — and only these four — are GitHub's named context-supply mechanisms. Custom instructions (repository-wide, path-specific, AGENTS.md, and related mechanisms) are a related, already-covered context capability, not a fifth item on this list; they simply aren't one of GitHub's four named mechanisms.
Of the four, MCP already has a home elsewhere in this course: its conceptual model, the current registry, its risk patterns, and how to configure an MCP server for a project are all owned by Chapter 5. This chapter only recaps that MCP is one of the four context mechanisms and does not re-teach configuration.
Separately, custom instructions are fully owned by Chapter 4, which also covers how to compose review-scoped instructions. This chapter recaps, by cross-reference only, that custom instructions exist as a related context-supply capability you may already have configured — without counting them among GitHub's four named mechanisms above.
Repository indexing and content exclusion are new to this course and are taught here at exactly the level GitHub's documentation supports: what each does, not how to configure it. If your work requires configuring indexing or exclusion in detail, treat that as outside this chapter's scope and consult current GitHub documentation.
6. Reference Project: Assembling Context and Prompting Technique
The reference project's next change deserves the same deliberate setup Sections 1 through 4 taught for any Copilot Chat request: scope the prompt, supply the right context, and pick the surface suited to the task — decided in advance, not improvised mid-change. Doing this planning as a standalone step before you touch the change itself is what turns Sections 1–4's techniques into a habit rather than a one-off exercise: you assemble a context inventory and a prompt as a complete artifact first, and only then execute the change against it.
Two things already on the reference project feed directly into that artifact. Custom instructions (Chapter 4) are one of the context-supply capabilities already configured on the project, separate from Section 5's four named mechanisms. And your recorded Chapter 5 MCP state — whichever of Chapter 5's three outcomes applies to you — determines how you'll describe MCP's status in the context inventory; check your own Chapter 5 notes before you start.
This section does not restate the procedure; Activity 4 carries the actual steps and produces the finished, ready-to-use context inventory and prompt for the reference project's next change.
Activity 1: Prompt Rewrite Drill
Goal: Practice applying GitHub's four documented prompt-composition techniques to turn vague prompts into clearer Copilot Chat requests.
Steps:
- Take three vague or ambiguous prompts about the reference project — the kind that lean on an unnamed "this," ask for everything in one shot, or give Copilot no concrete example of the desired output — and rewrite each one.
- For every rewrite, apply at least one of the four techniques from Section 1: progressive specificity, supplying an example, decomposing into smaller sequential requests, or naming the exact referent instead of a vague pronoun.
- Annotate each rewrite with which technique(s) you used and why the original was ambiguous.
Expected outputs:
- Three rewritten prompts, each with a technique annotation.
Hints:
- Start broad and add one concrete constraint rather than trying to specify everything at once.
- Replace "this" or "it" with the exact function, file, or symbol you mean.
Checkpoint: Each rewrite names a specific technique from Section 1 and demonstrably removes a vague pronoun or unstated scope present in the original — a reviewer should be able to point at the exact phrase that changed and the technique that motivated the change.
Activity 2: Context-Supply and Chat-Management Drill
Goal: Practice surfacing relevant code and managing the chat interaction using current per-IDE syntax.
Steps:
- If your IDE is in Section 3's documented set (VS Code, Visual Studio, or JetBrains, using its documented token names): in your IDE, open a relevant reference-project file and scope a Chat request to it using
#fileor#selection— Section 3 documents that these tokens exist, not what each one does, so confirm the current behavior in GitHub's own documentation before relying on it. - If your IDE is VS Code or JetBrains: ask a question that spans multiple files by invoking
@workspace(VS Code) or@project(JetBrains), again checking current GitHub documentation for what the participant actually does in your IDE. If your IDE is Visual Studio: scope a multi-file question using#fileinstead, and record that this course's evidence documents no chat participant for Visual Studio. - If your IDE is outside Section 3's documented set, or is Eclipse (for which no specific token names are documented): record in writing that this course's evidence documents no per-IDE context-injection syntax for your editor, and skip the two steps above.
- Deliberately send one under-specified request, note why the response fell short, then iterate by modifying the request rather than accepting the result.
- Start a new chat thread for an unrelated task and note the point at which you'd prune an older, stale thread.
Expected outputs:
- For VS Code or JetBrains: a log of at least three chat interactions showing correct
#file/#selectionor@workspace/@projectusage — the token names as listed in Section 3 — plus one documented iteration cycle: original request, why it fell short, and the modified follow-up. - For Visual Studio: a log of at least three chat interactions showing correct
#file/#selectionusage, a written record that this course's evidence documents no chat participant for Visual Studio, and the same documented iteration cycle. - For an IDE outside that documented set, or Eclipse: a written record that this course's evidence documents no per-IDE context-injection syntax for your editor, plus the same documented iteration cycle and a note on chat-thread management.
Hints:
- Section 3 also lists
#codebase,#git,/fix, and/testsas documented token names — trying one of these for a repository-wide, history, or fix/test task is a starting suggestion to verify against current GitHub documentation, not a documented behavior of the token itself.
Checkpoint:
- For a documented IDE, the logged syntax matches the current documented set of token names for your IDE from Section 3, with their behavior confirmed against current GitHub documentation rather than assumed — for Visual Studio, that includes the recorded absence of a chat participant rather than an invented one. For an IDE outside that set, or Eclipse, you've recorded in writing that no per-IDE context-injection syntax is documented for your editor.
- The log shows at least one full iteration cycle on an unsuccessful response, not just a single successful exchange.
Activity 3: Mode Selection and Suggestion Validation Checklist
Goal: Practice choosing an appropriate interaction mode per task and validating a resulting suggestion rather than accepting it uncritically.
Steps:
- For four short tasks — completing a loop body, generating tests for a function, explaining a module the way a senior developer would, and answering a design question that spans multiple files — state which mode, inline completion or Chat, fits best and why, using Section 4's guidance.
- Take one real Copilot suggestion produced on the reference project and run it through the validation checklist from Section 4: review it for correctness, request an explanation, check it for functionality and security issues, and pair it with a lint or code-scanning pass.
Expected outputs:
- A mode-choice justification for each of the four tasks, plus one validated suggestion with correctness/security notes and lint or code-scan results attached.
Hints:
- Persona-style prompting ("act as a senior X developer") is documented as a Chat technique, not an inline-completion one.
Checkpoint:
- Each justification cites the specific task property — snippet/test generation versus a question, a larger section, or persona-style prompting — that drove the choice.
- The validation checklist was actually run, with lint or code-scan output attached alongside the correctness and security notes, not just described.
Activity 4: Assemble Context and Prompt for the Next Reference-Project Change
Goal: Synthesize prompt composition, context-supply technique, IDE syntax, and mechanism awareness into one concrete, self-contained context-and-prompt artifact for the reference project's next change.
Steps:
- Identify a small, real next change for the reference project that builds on its existing history.
- Check your Chapter 5 notes and record which of its three MCP states applies to you:
- Attached and exercised on both surfaces, with its approval behavior observed.
- Attached only on the interactive surface, with the approval contrast reasoned rather than observed because no unattended surface was available.
- Recorded as an "MCP access blocked — organization policy not enabled" state, if Chapter 5's organization-policy check wasn't satisfied.
- Separately, record that the project's custom instructions (Chapter 4) are already composed and applied, and note that they are a related context capability rather than one of Section 5's four named mechanisms.
- If your IDE is in Section 3's documented set (VS Code, Visual Studio, or JetBrains, using its documented token names): open or highlight the files relevant to the chosen change and pick a chat participant/variable name from Section 3's list — treat any token-to-scope pairing as a starting suggestion to verify in current GitHub documentation, not as documented behavior. If your IDE is outside that set, or is Eclipse (for which no specific token names are documented): open or highlight the relevant files as your IDE supports, and record that this course's evidence documents no per-IDE context-injection syntax for your editor.
- Compose the prompt itself, applying progressive specificity, examples, decomposition, or explicit referents as appropriate.
- Note, by name only, which of the four context mechanisms from Section 5 (MCP, Copilot Spaces, repository indexing, content exclusion) are relevant to this change and which are not currently in use — without asserting any Copilot Spaces capability beyond its name.
- Do not execute the change yet — the assembled context and prompt are the complete artifact this activity produces.
Expected outputs:
- A written, assembled prompt for the chosen change.
- A short context inventory naming all four Section 5 mechanisms and, separately, which existing Chapter 4 configuration is being reused, plus your recorded Chapter 5 MCP state carried forward as-is.
- A one-line justification for why Chat (not inline completion) suits this task.
Hints:
- Reuse, don't redo — the custom instructions already exist on the project from earlier work, and step 2 already established your recorded Chapter 5 MCP state; carry it forward rather than re-deriving it. Only the MCP server, when attached, is one of Section 5's four named mechanisms.
- If Copilot Spaces isn't part of your project's current setup, it's enough to note it as an available-but-unused mechanism.
Checkpoint:
- The assembled prompt demonstrably applies at least two of the four Section 1 techniques — a reviewer should be able to point to specific phrases showing progressive specificity, examples, decomposition, or explicit referents.
- The context inventory names exactly the four mechanisms from Section 5 (MCP, Copilot Spaces, repository indexing, content exclusion) without folding custom instructions into that count, and asserts no unverified Copilot Spaces capability, plan, or usage detail.
- The artifact is complete and immediately usable for the reference project's next change without further prompting-technique work, whether or not Section 3 documents context-injection syntax for your IDE — for an IDE outside that documented set, or Eclipse, completeness does not depend on a chat-participant/variable syntax having been selected.
Reference Project Continuity — Chapter 6
Starting state. The shared reference project enters this chapter already carrying: initial setup and a first Copilot-assisted change, a Copilot plan selected for the project's team scenario, the pull request produced by the Chapter 3 workflow, reviewed in Chapter 4 either with Copilot code review and scoped custom instructions or with the Path B manual-review fallback. It also carries one of Chapter 5's three recorded MCP outcomes:
- Attached and observed — an MCP server attached and exercised on both the interactive and an unattended surface, with its approval-behavior contrast observed.
- Attached and reasoned — an MCP server attached only on the interactive surface, with the contrast reasoned rather than observed because no unattended surface was available.
- Blocked — if Chapter 5's organization-policy check wasn't satisfied, a recorded "MCP access blocked — organization policy not enabled" state with no server attached.
Check your own Chapter 5 notes for which of the three applies.
What this chapter adds. Learners rewrite ambiguous prompts about the reference project's own code (Activity 1), practice context-supply and chat-thread management directly on the project's files and history using current per-IDE syntax (Activity 2), justify mode choices and run a real suggestion through a validation checklist (Activity 3), and finally produce one complete, ready-to-use context inventory and composed prompt for the project's next real change (Activity 4). That inventory names all four of Section 5's context-supply mechanisms — MCP, Copilot Spaces, repository indexing, content exclusion — and states which are already active, available-but-unused, or not configured, carrying forward your recorded Chapter 5 MCP state as established above rather than re-deriving it; separately, and without folding it into that four-item count, it notes that the project's existing custom instructions (Chapter 4) are being reused as-is.
Ending state. The reference project's history now includes a documented prompt-composition and context-supply artifact: a set of rewritten prompts, a logged context-supply drill, a validated suggestion, and a complete context inventory and prompt ready to use for the project's next change. The inventory correctly distinguishes GitHub's four named context-supply mechanisms from the project's already-configured custom instructions, and carries forward your recorded Chapter 5 MCP state rather than assuming a server was successfully attached, so nothing further is required before that change begins — the artifact is self-contained and internally consistent.