How Copilot Works
How GitHub Copilot Works
You do not need to be a machine learning researcher to use Copilot well. But understanding a few key ideas about how it works will immediately make you a better user of it — because most of the mistakes people make with Copilot come from misunderstanding what the model can and cannot see.
The underlying technology
GitHub Copilot is powered by large language models (LLMs) — the same class of technology behind ChatGPT and Claude. These models are trained on vast amounts of text, including enormous quantities of public code from GitHub, Stack Overflow, documentation sites, and other sources.
During training, the model learns statistical patterns: what tends to follow what. If a function is named validateEmail, the model has seen thousands of functions with that name and knows what they usually look like. If you write a comment that says "returns the nth fibonacci number", the model has seen that comment (or very similar ones) and knows what the function body usually looks like.
This is not reasoning or thinking in the human sense. It is sophisticated pattern completion at a massive scale.
What the model sees: the context window
Every time Copilot makes a suggestion, it sends a package of text to the model. This package is called the context window. What goes into it:
- The current file you are editing, especially the code around your cursor
- In some configurations, other open tabs (Copilot tries to pick the most relevant ones)
- Your
.github/copilot-instructions.mdfile if it exists (more on this in a later lesson) - In Chat mode: the conversation history plus any files or symbols you have explicitly attached
The model sees only what is in this context window. It does not browse your codebase on its own. It does not remember previous sessions. It does not know what happened yesterday. It works entirely with what you send it right now.
This has a critical implication: the quality of your output is directly proportional to the quality of your context.
Why context determines quality
Consider these two situations:
Poor context: You open a blank file and type function process(data) {. The model has no idea what data is, what this function is supposed to do, or what patterns your codebase follows. It guesses something generic.
Rich context: You have your types.ts open (which defines UserData), you have a similar function processOrder open in another tab, and you write:
typescript// Process a UserData object: validate required fields, normalize the email // to lowercase, and return a ProcessedUser. Throw ValidationError if required // fields are missing. function processUser(data: UserData): ProcessedUser {
Now the model knows the types, the pattern from processOrder, and the exact specification from the comment. The suggestion will be dramatically better.
Training data cutoff
The model has a knowledge cutoff date. It was trained on code and documentation up to a certain point in time. This means:
- It may not know about APIs or syntax introduced after its training cutoff
- It may suggest deprecated patterns from older versions of a library
- Framework-specific conventions that changed recently (e.g. Next.js App Router, React Server Components, Pydantic v2) may be outdated
When working with cutting-edge features or recently updated libraries, verify the suggestions against the current official documentation. Do not assume Copilot knows the latest API.
Completion vs chat: different context, different use
Inline completion uses a smaller context window optimized for speed. It mainly sees the current file and nearby open tabs. It is designed to be fast — suggestions arrive in under a second.
Copilot Chat uses a larger context and you control what goes in it by attaching files, symbols, and selections. It is slower but far more aware of your specific codebase.
Use inline completion when you want speed and the task is obvious from the current file. Use Chat when the task needs broader knowledge of your project.
The "hallucination" problem
Because the model is doing pattern completion rather than reasoning, it sometimes invents things that look correct but are not:
- A method that does not exist on an object (
array.filterByKey(...)— not a real method) - A parameter that was removed in a newer version of a library
- A configuration option that was never real, just plausible-sounding
This is called hallucination. It is not a bug to be fixed — it is a fundamental property of how these models work. The defense is always the same: read the output, run it, test it. Never ship code you have not read.
Summary
| Concept | What it means in practice |
|---|---|
| Pattern completion | Give clear context; the model matches patterns it has seen |
| Context window | Open relevant files; write descriptive comments and signatures |
| Training cutoff | Verify suggestions for recently changed APIs |
| Hallucination | Always read and test generated code |