This course assumes that you know the Kladde from K2: C#, Git and pull requests, tests with xUnit. It shows how you use GitHub Copilot in everyday work so that the code does not get worse. This first lesson clarifies what Copilot is, where your input goes, where the limits are and who stands behind the result. Only after that do you learn in W3.1.2 how to write good prompts.
A note on the honesty of this course first. Copilot does not answer predictably: the same question can get different answers today and tomorrow. So the course never shows "the" answer from Copilot, but writes "a possible answer" and teaches what to check in it. Surfaces and commands that were only read against the documentation when this was written and not run against Copilot carry the note "not run against Copilot". Plans, credits and models change faster than a course: so there are no numbers here about them, only the questions you put to the documentation.
| Module | Lesson | What you build |
|---|---|---|
| W3.1 | W3.1.1 Understanding Copilot | a set-up editor and your list "Never accept without review" |
| W3.1 | W3.1.2 Prompts and context | prompts that deliver usable code for the Kladde |
| W3.2 | W3.2.1 Agent mode, MCP and the command line | small tasks in agent mode and in the CLI |
| W3.2 | W3.2.2 Instruction files, review and tests | an instruction file for the Kladde, graded tests |
| W3.2 | W3.2.3 Privacy, exclusions and organization | exclusion patterns and prompt rules for a team |
What GitHub Copilot is
GitHub Copilot is an assistant that uses a large language model to suggest code, answer questions about code and carry out tasks. It comes in several forms, and a different question applies to each: Who decides what happens, and what leaves your machine?
| Form | What it does | Who decides |
|---|---|---|
| Inline suggestions | suggest the next lines as you type | you accept or discard every suggestion |
| Chat | answers questions and generates code in the editor's side panel | you take what you want |
| Agent mode | decides on its own which files it changes, and runs commands | you approve commands, by default before every run |
| Copilot CLI | works on the command line | according to the documentation, changes no files without explicit consent |
| Cloud agent | works on a task on github.com, creates a branch and a pull request | you review the pull request |
| Code review | reads a pull request and comments | does not replace a human approval |
To place what the documentation says about the forms (read on docs.github.com and Microsoft Learn, without date or version):
- Inline suggestions and chat. Suggestions are only taken over when the user accepts them. The chat is meant for questions about programming, not for arbitrary topics.
- Agent mode in the editor. It is called "Agent" and is chosen in the chat's mode menu (in Visual Studio, according to the documentation, from version 17.14). It decides on its own which files it changes and runs commands; according to the documentation, you approve commands by default before they run. Every prompt uses credits. W3.2.1 goes into this.
- Cloud agent. It runs on github.com ("Copilot in the cloud") in a sandbox or in GitHub Actions, one branch and one pull request per task, with read permissions only on the repository it works in. W3.2.1 covers this as well.
- Code review. Copilot can review a pull request; the documentation names levels (Lite, Balanced as the default, Max in public preview). It reads instruction files (W3.2.2) and skips dependency files, logs and SVG. A review by Copilot does not count toward the required approvals unless something else is configured.
- Summaries of pull requests. Copilot can write them; it skips files with more than 400 changes.
Two points on billing, without numbers: The documentation names several plans and a credit system. Chat, CLI and cloud agent use credits, code completions do not. How many credits your plan includes and what happens when they run out you read in the current documentation and ask your administration. The course does not say, because it can be different tomorrow.
How a prompt comes about and where it goes
When you ask a question in the chat, the editor does not send just your text. According to GitHub's documentation, the prompt goes together with context to the model:
- your question or instruction,
- the content of the open files and, if you have selected something, the selection,
- the name of the repository,
- the chat history so far,
- instruction files of the repository, if there are any (W3.2.2).
After that, according to the documentation, filters run over input and output (content filters). An optional web search through Bing exists only if the administration has enabled it. If someone chooses a model through their own key ("BYOK", Bring Your Own Key), prompt and answer go to the provider chosen there, and its terms apply (W3.2.3).
What follows from this matters more than any diagram:
- Everything that is in the context can leave the machine. An open file with a key, a test file with real customer data: neither belongs in the prompt and, as long as Copilot uses the file as context, neither belongs in the open editor. The rules for this are in W3.2.3; for today this holds: secrets and personal data do not belong in a prompt.
- The context determines the answer. What Copilot does not see, it does not know. W3.1.2 builds on this.
- The chat history counts as context. A long history with false starts is bad context.
What the documentation does not answer. Two questions that the data protection office will ask were not on the pages read: whether prompts are used to train models, and how long chats in the editor are kept. The course claims nothing about this. The answers are in GitHub's Trust Center and in the terms of your plan; read them there, for your plan, and note the answer with the day you read it.
Limits of large language models
A language model produces text that is probably fitting; it does not check for truth. Three consequences matter for working with code.
It invents. The model continues with what sounds plausible: a method that does not exist, a parameter that is named differently, a package that never existed. This usually shows up at build time (the compiler reports it). More dangerous are answers that compile and do the wrong thing.
It is outdated. The model knows the state of its training, not today's. New versions, changed interfaces and security advisories it may not know. If Copilot tells you a package is "current" or a vulnerability "fixed", check it at the source (documentation, NuGet, security advisory).
It is not deterministic. The same question can deliver different answers. A result that was right once is no proof that it is right again. That is why you check the answer, not the way it came about: tests, compiler, review.
An example from the Kladde
Since K1 the Kladde has a value object TimeRange with the rule for when two time ranges overlap. Two appointments, one of which ends at 10:00
a.m. and the next begins at 10:00 a.m., do not overlap. The rule in the Kladde:
public bool Overlaps(TimeRange other) => Start < other.End && other.Start < End;
Imagine you ask Copilot in the chat: "Write a method Overlaps for TimeRange." A possible answer (not run
against Copilot like this, but as an example of a typical form of error) would be:
public bool Overlaps(TimeRange other) => Start <= other.End && other.Start <= End;
The method compiles, it looks right, it works for almost all inputs. It is wrong at exactly one place, the
edge: two appointments "9 to 10 a.m." and "10 to 11 a.m." count as overlapping with <=. In the Kladde, booking the second
appointment would be rejected with the code appointment.time.overlaps and 409, although nothing collides (K2, lesson 2.4.7). No compiler and no
look at the code shows this reliably. A test shows it:
[Fact]
public void TwoRangesThatOnlyTouchDoNotOverlap()
{
DateTimeOffset ten = new(2000, 1, 1, 10, 0, 0, TimeSpan.Zero);
TimeRange morning = new(ten.AddHours(-1), ten);
TimeRange next = new(ten, ten.AddHours(1));
Assert.False(morning.Overlaps(next));
}
The lesson is not "Copilot writes wrong code". The lesson is: You know the edge cases, not the model. A test that you write before accepting costs minutes and catches this form of error. W3.2.2 goes deeper: generated tests that check nothing.
Responsible use: who is liable?
GitHub's application cards for inline suggestions and chat say it clearly: users bear all the risks of the generated code. That means security vulnerabilities, bugs and the infringement of intellectual property. In practice this means:
- You accept the code, so it is yours. Your name is on the pull request, not Copilot's. A review does not ask who wrote the line, but whether it is right.
- You review it as if a stranger had written the code, someone you do not know and cannot question: Does anyone understand every line? Are there tests for edge cases? Are inputs validated? Are there secrets, paths or assumptions that hold only for an example?
- You ask about what you do not understand. A chat that explains code is a tool for reviewing. What you cannot explain after the explanation, you do not accept.
- You use the chat for the task it is meant for: programming. Questions outside of that are, according to the application card, not the intended use.
Matches with public code
A language model can generate code that resembles or equals code from a public repository. Copilot has a filter for this. According to the documentation:
- The filter compares a snippet of about 150 characters of code around the suggestion with public code.
- Depending on the setting, a suggestion with a match is blocked or shown with source and license.
- Matches are rare according to the page (under one percent of suggestions).
What the filter cannot do: It does not guarantee that a suggestion is free of third-party rights. It compares only a snippet, only with public code. The decision how your team deals with matches is not a technical one: it belongs in the rules of your organization and, in doubt, to the legal department. What the setting is called and who may change it depends on the plan (account or organization): you look for it in Exercise 2.
Setting up Copilot in the editor
The course does not assume a particular editor; the exercises name Visual Studio Code and, where it differs, Visual Studio. For both:
- A GitHub account with Copilot access. The access comes from a plan of your own or from the organization that gives you a seat. Which plan applies is a question for your administration, not for this course.
- Install Copilot in the editor and sign in. The steps are described in your editor's documentation (not run against Copilot). Where Copilot appears afterward (status bar, chat) is in the same documentation.
- Look at the settings before you start: whether suggestions appear while you type and for which languages, whether a suggestion that matches public code is blocked or shown, and which policies your organization sets.
- Choose the repository you practice in: not the Kladde on
main, but a branch of your own or a practice project.
You learn suggestions and chat best on a small, familiar task whose result you can check. The Kladde lends itself to that: you know its rules from K1 and K2.
Exercise 1
Set up, accept, reject. Set up Copilot and practice dealing with suggestions.
- Create a branch:
git switch -c feature/copilot-practice. - Set up Copilot in your editor as described in the documentation (not run against Copilot).
- Open a test file of the Kladde in which you already have tests for
TimeRange, or createTimeRangeCopilotTests.cs. Write the name of a new test method, for exampleARangeThatEndsWhereTheOtherStartsDoesNotOverlap, and wait to see whether Copilot suggests a body. - Accept a suggestion that you understand completely. Do not leave it in place before you have read it.
- Reject a suggestion (discard it or keep typing) and write that line yourself.
- Run
dotnet testand read the exit code.
How you check: You have experienced at least one accepted and one rejected suggestion and can say why. The test runs, and you know which edge it checks. If Copilot shows nothing, check the sign-in, the settings and your organization's policy.
Solution 1
There is no single correct answer from Copilot; the body of the test differs from time to time. For every accepted suggestion, check these points:
- Does the test check the edge (end equals start) or only two ranges far apart?
- Does it access only members that really exist in
TimeRange? An invented member is reported by the compiler. - Is the expectation right: touching is not overlapping,
Assert.False? - Is there no time or random number in the test that makes it flaky? (K2, lesson 2.7.2 on tests for rules.)
An example of a good test is in the section "An example from the Kladde". Once you have checked the result, commit with a
message like test(core): edge case of TimeRange.Overlaps. Your name is under it, not Copilot's.
Exercise 2
Find the filter for public code. Find the setting that controls what happens to suggestions that match public code.
- Search GitHub's documentation for the filter for matches with public code, and note where the setting is for your plan (account settings or organization).
- Open the setting. If it is under your organization's control, note that you may not change it, and who may.
- Note today's state (blocked or with source and license) and the day of the check.
- Write in two sentences what effect you expect if you change the setting, and what the filter does not promise.
How you check: You can say where the setting is, who changes it and which value applies. You know that the filter compares a snippet of about 150 characters with public code and does not promise freedom from third-party rights.
Solution 2
What exactly the setting is called and where it is changes with the surface and the plan; the course therefore names no menu path (not run against Copilot). Proceed like this: find the documentation, find the setting, note the value and the day. If your organization has set the value, that is the answer to "What applies to me?". With "Block", suggestions that match a public snippet are missing, without you seeing it; with "Show" you get source and license and decide. In both cases the review stays with you: a filter replaces neither a license check nor a review.
Exercise 3
The list "Never accept without review". Write yourself a list that you put next to the keyboard in everyday work.
- Create the file
docs/copilot-checklist.mdin the practice branch. - Write at least eight lines. Each line names a kind of code or statement that you accept only with a particular check, and the check.
- Cover these areas: security (inputs, sign-in, secrets), data (queries, migrations, deleting), time and time zones, edge cases of rules, packages and versions, license, permissions, statements about documentation.
- Add three things at the end that you never write into a prompt.
How you check: Every line has a check that you can carry out (test, compiler, documentation, review), not just "be careful". Someone else on the team could apply the list.
Solution 3
An excerpt that shows the form. Your list may look different:
# Never accept without review
| What | Check before accepting |
| --- | --- |
| SQL or EF Core queries that change or delete | Read the query, run it against a test database, check the migration |
| Code that processes input | What happens with empty, too long, wrongly encoded? Write a test for it |
| Sign-in, permissions, tokens | check against the provider's documentation, never from the model's memory |
| Time, time zones, daylight saving time | Tests with fixed clocks; name the edges (midnight, changeover) yourself |
| Rules with limits (overlap, deadlines) | Edge tests before accepting |
| New packages or versions | Does the package exist? Who maintains it? License? Advisories about vulnerabilities? |
| Statements "this is current/fixed" | Open the source and read the date |
| Code that cannot be explained | do not accept; have it explained first, then check |
Never in a prompt: credentials and keys, personal data of real people, content that a contract with customers does not
allow passing on.
The list is no proof that the code is good; it is a reminder of the checks that you would otherwise forget. It grows when you find a mistake that Copilot produced: add the form of error, not the individual case.
What you can do now
- You tell inline suggestions, chat, agent mode, Copilot CLI, cloud agent and code review apart and know who decides in each case.
- You describe what context the editor sends with the prompt, and name what the documentation leaves open about training and about retention.
- You name the three limits: it invents, it is outdated, it is not deterministic, and you check an answer against edge cases instead of the first impression.
- You explain that you stand behind generated code, and place the filter for matches with public code correctly.
- You have set up Copilot, accepted one suggestion and rejected one, and have a list of what you never accept without review.
Further reading
- What is GitHub Copilot?: an overview of Copilot's features.
- Responsible use of GitHub Copilot inline suggestions: application card for inline suggestions.
- Responsible use of GitHub Copilot Chat in your IDE: application card for the chat.
- GitHub Copilot Trust Center: questions on privacy, training and retention.
- GitHub Copilot Fundamentals, Part 1: learning path on Microsoft Learn.
- Responsible AI with GitHub Copilot: module on Microsoft Learn, the first in the Fundamentals Part 1 learning path.