For the past year, I have used GitHub Copilot at work and on personal projects. The shift from vibe coding to agentic engineering is what changed the way I work.
A code agent is Copilot working toward a goal with tools that can inspect files, edit code, and run commands. I stopped treating it as a clever prompt responder and started treating it as part of my engineering process.
I began with Copilot Chat in VS Code, moved to the CLI, and now do most of my work in the Copilot App. Handing Copilot complete tasks taught me that a good prompt is not enough. It also needs the architecture, rules, and validation commands that make the repository understandable. Once I stored that knowledge with the code, each new session started from a much better place.
That is agentic engineering in practice. The repository provides the context, the agent and its tools do the work, automated checks provide evidence, and a human decides whether the result is ready. The same model works across Copilot surfaces, although the controls differ between the App and CLI.
If you are new to code agents, do not configure everything at once. Complete one small task first, then add custom agents, skills, MCP, or Spec Kit when the need becomes real.
Anatomy of a Copilot task
Several pieces come together whenever Copilot handles a task.
The building blocks of a Copilot task.
Copilot provides the agent harness, the runtime around the model that manages context, tools, permissions, sessions, and execution. The repository then adapts that harness to the way the team builds software.
Before acting, Copilot builds context from my prompt, the files I attach or mention, relevant repository content, and the instructions that apply to the files being changed. Better context reduces guessing, but it does not make generated code automatically correct. I still review every proposed change.
The next decision is who should do the work. I can select a custom agent, or Copilot can choose one whose description matches the task. If no specialist fits, the main Copilot agent handles the request. That default is enough for a first task. I choose a specialist when the responsibility is clearly architecture, implementation, review, testing, or documentation.
For routine work, I leave the model at its default. I use a stronger model or more reasoning only when the problem justifies the extra cost and time. The App provides a model picker, while the CLI uses /model.
I also choose how independently the agent should work. Interactive mode keeps me in the conversation. Plan mode lets me inspect the approach before code changes begin. Autopilot continues without waiting when the task is clear and reliable checks are available. In the App, these options are part of the session controls. In the CLI, Shift+Tab cycles between them.
The final setup choice is where the work runs. In the App, I can use the current repository, a new worktree, or a GitHub-hosted cloud sandbox. I usually choose a worktree because it gives the task a separate folder and branch without disturbing my main checkout.
The CLI starts locally in the directory and Git branch that are already open. It does not create a separate worktree when a session starts. I create a feature branch before the first task, and I use copilot --cloud when I want the work to run in a hosted environment instead.
The isolation terms are related, but they do different jobs. A session keeps the conversation and task context. A branch separates the task's commits from main. A worktree gives that branch its own folder, which is useful when I want to keep my main checkout open or run tasks in parallel. A sandbox protects a different boundary by limiting where commands can reach or by moving execution into an isolated cloud environment.
None of these layers replaces review. Before I accept the result, I inspect the diff, the commands Copilot ran, and their output. In the App, Changes shows the diff, while Plan and Artifacts explain how the session got there. In the CLI, /diff brings the changes together. I confirm that the expected checks passed before opening a pull request.
Agents, subagents, and skills in practice
The main Copilot agent handles a request when no custom agent is selected. The CLI also includes built-in specialists for exploration, command execution, code review, research, and rubber-duck analysis.
A custom agent is a reusable role with its own instructions and tools, normally stored in .github/agents/. I use one when the responsibility changes. An architecture agent can compare options and prepare an architecture decision record. After I approve that direction, an implementation agent can change the code and run the checks.
A subagent is different. It is a temporary worker with its own context, created to handle part of a larger task. For example, I can ask the main agent to use a test-writer agent for the unit tests while it keeps responsibility for the complete change. The Fleet command extends that idea by running several independent subagents in parallel.
A skill captures a reusable method rather than a new role. Repository skills stay with the code, so everyone on the project can use the same guidance. I keep personal skills for workflows I reuse across projects. When I need one, I simply ask Copilot to use it: "Use the API compatibility skill to review this endpoint."
This distinction keeps the setup small. I do not need separate Python, TypeScript, and Terraform agents when one implementation agent can load the appropriate skill and follow the instructions for the files it changes.
Tools are capabilities
Copilot has built-in tools for searching files, reading and editing code, and running commands such as builds or tests. I describe the outcome rather than prescribing every step. If I ask, "Where is API token validation implemented?", Copilot can search for token references, inspect the matching middleware and configuration, and answer with the relevant paths.
Tools that edit files or run commands need permission. In the CLI, Copilot asks for approval unless I have already allowed the action. I grant only the access required by the task. GitHub describes the available choices in the Copilot CLI permission model.
Model Context Protocol, usually called MCP, extends those capabilities to systems outside the repository. An MCP server can expose tools for GitHub, Azure DevOps, browser automation, databases, cloud resources, or observability platforms. I treat it as optional and add it only when a task genuinely needs external data or actions.
In the App, I manage these connections from Settings > MCP servers. I can install a server from the catalog, add a custom server, and disable anything I am not using.
MCP servers in the Copilot App.
From the CLI, I add a server with /mcp add and inspect configured servers with /mcp show. Once a server is connected, Copilot can choose a relevant tool when the task requires it. I can also be explicit: "Use the Azure DevOps MCP server to list the active work items assigned to me."
I keep MCP access narrow. Servers that I am not using stay disabled, exposed tools are limited to what the workflow needs, and every login or token receives the smallest practical set of permissions.
How to start
Choose either the App or CLI. You do not need to configure both. Start with a small, reversible change in a repository that has a known validation command.
In the Copilot App, a project is the folder or repository connected to Copilot. A session is the workspace where the agent handles one task in that project. GitHub's App quickstart explains how to install the App, sign in, and connect the first repository.
To begin, I click the plus sign next to Sessions and choose the codebase. It can be a folder already on my machine, a local clone, or a repository that the App clones from GitHub or another Git host.
For my first task, I use Plan mode so I can review the approach before Copilot changes anything. I describe one outcome, define its boundary, and name the command that will prove it works. A useful first prompt is: "Add validation that rejects an empty task title. Do not change any other behavior. Run pytest, then show me the diff and the test result."
Issues and files can be attached directly from the composer when they provide useful context. The important part is not the syntax. It is giving Copilot a clear outcome, a boundary, and a way to verify the result.
For isolated local work, the App can create a Git worktree with its own branch and checkout. This option is available for Git repositories and lets the agent edit files without changing my main working folder. Quick chat serves a different purpose. I use it for questions and brainstorming because it creates no branch or worktree.
If I prefer the terminal, I follow GitHub's CLI installation guide, open a terminal inside the repository, and create a feature branch before starting Copilot:
git status
git switch -c copilot/input-validation
copilot
On the first launch, I authenticate when prompted and approve the directory. Starting Copilot inside the repository gives it the correct project as its working context.
A local CLI session uses the directory and branch that are already open. If I want to keep my main checkout untouched or run multiple CLI sessions in parallel, I create or open a worktree first and start Copilot from that folder.
One command is worth learning on day one: copilot init. I run it at the repository root, review the generated instructions, and replace the placeholders with the repository purpose, important directories, trusted validation commands, constraints, and evidence required before a task is complete. I then commit the reviewed file so future sessions and teammates receive the same context.
Put the engineering knowledge in the right place
At this point, Copilot can read and change the code. It still does not know how the team works. Without repository guidance, it has to infer the architecture, trusted commands, important constraints, and what "done" means.
I store that knowledge with the code so every session can begin with it. For an existing repository, I start with the instructions generated by copilot init and improve them as I discover what the agent needs. For a new project, my agentic-engineering template provides a fuller starting point that I adapt to the stack and team.
The template uses this structure:
.
|-- AGENTS.md
|-- .github/
| |-- copilot-instructions.md
| |-- instructions/
| |-- agents/
| `-- skills/
`-- .gitignore
AGENTS.md follows a convention used by several coding tools, not only GitHub Copilot. A repository can have one at its root and more inside subdirectories. When several apply, the nearest file provides the local guidance. I use the root file for the general engineering workflow: how an agent should investigate, change code, validate the result, and report evidence.
.github/copilot-instructions.md is the Copilot-specific file for repository-wide guidance. It is supported across more Copilot surfaces than AGENTS.md, so it is the best place for context and rules that every Copilot interaction should receive.
I include both only when the project needs both. The Copilot file provides broad product coverage, while AGENTS.md adds cross-tool portability and local directory scope. If a team uses only Copilot, the Copilot file is the simpler starting point. GitHub's custom instructions support matrix shows which surfaces read each format.
The .github/instructions/ directory holds rules that apply only to matching files. Each file ends with .instructions.md and declares its scope in YAML frontmatter. A Python instruction file might begin like this:
---
applyTo: "**/*.py,**/*.pyi"
---
Those instructions load when Copilot works on matching Python files, but not when it edits CSS. Repository-wide guidance still applies. This is where I keep language, framework, and directory-specific rules that would otherwise clutter every task.
The .github/agents/ directory contains reusable specialist roles. Each agent file explains when the role is useful, gives it focused instructions, and lists the tools it needs. That tool list matters. An implementation agent needs editing and command execution, while a read-only reviewer does not. If I omit the list, Copilot may make every available tool accessible to the agent.
The .github/skills/ directory contains reusable procedures and knowledge packages. Each skill has its own folder with a required SKILL.md file. It can also include references, scripts, and assets:
.github/skills/engineering-principles/
|-- SKILL.md
`-- references/
|-- architecture-core.md
`-- testing-fitness-functions.md
The skill description explains what the procedure does and when it should be used. Its SKILL.md can then point Copilot to longer references only when they are relevant. An API-change skill, for example, can identify consumers, classify compatibility, require a migration plan for breaking changes, update contract tests, and report adoption risk. Those instructions do not belong in the global file because most tasks do not change an API.
Before adding an agent or skill, I check whether the repository already has one with the same responsibility. I merge or replace overlapping components instead of stacking them, then review the instructions, tools, and license.
These files must be committed. I do not add .github/, AGENTS.md, or their supporting documentation to .gitignore, because the value comes from sharing the same context with every contributor and session.
Shared agent configuration deserves the same review discipline as production code. A careless edit can weaken validation, expose unnecessary tools, or teach every session the wrong command. On a team repository, I send these changes through pull requests. Teams can also use code owners and repository rulesets to require approval for sensitive configuration.
Personal preferences belong outside the repository. Copilot CLI reads ~/.copilot/copilot-instructions.md, the App provides personal settings, and GitHub.com supports personal instructions in Copilot Chat. These preferences follow me without imposing them on the team.
Use issues to start and pull requests to finish
An issue is useful for tracked work, but it is not required for a first session. When one exists, I use it to record the desired outcome, acceptance criteria, and constraints. The normal path is issue, session, feature branch, pull request, continuous integration, review, and merge.
The path from issue to merge.
In the App, I open My work, select an issue, and start a new session. The issue becomes part of the session context. If I stop and return later, I reopen that session from the sidebar rather than starting over.
The CLI also lets me browse issues and add one to the conversation. Closing the terminal stops the current operation but preserves the conversation history. I use copilot --continue for the latest session or copilot --resume to choose an earlier one. The conversation returns, although an interrupted operation does not restart.
When the implementation is ready, I ask Copilot to create a pull request for continuous integration and team review. A local session does not create one automatically. In the CLI, /pr create can push the current branch and open or update its pull request.
Cloud delegation follows a different path. The CLI command /delegate <task> hands work to the Copilot cloud agent, which runs in the background and opens a draft pull request. The local conversation remains local.
Follow-up work uses the pull request as its context. I can ask Copilot to address review comments or investigate failing continuous integration. The CLI pull request workflow also includes focused commands for both jobs.
On GitHub.com, assigning an issue to the Copilot cloud agent starts the work and creates a pull request. Follow-up instructions should be posted on that pull request because the agent does not read new comments added to the original issue.
The pull request is where the work returns to the team. Copilot prepares the change. A human decides whether it reaches main.
Use Spec Kit when the work deserves a specification
GitHub Spec Kit is an open-source workflow for specification-driven development. It helps coding agents turn an idea into project principles, expected behavior, a technical plan, and an ordered work list.
I use it when requirements are unclear, decisions need review, or several components must change together. For a small and obvious edit, the lighter workflow from the previous sections is usually enough.
To install Spec Kit for GitHub Copilot, I first install its CLI and confirm that specify --help works. The following command uses --force in the current directory, so I commit or stash existing work before running it:
specify init --here --force --integration copilot `
--integration-options="--skills" --script ps
This version installs PowerShell scripts for Windows. On Linux or in a cloud environment, I replace --script ps with --script sh.
The skills option installs each Spec Kit step under .github/skills/. I commit those folders together with .specify/ so the workflow stays with the repository.
One naming detail can be confusing. General Spec Kit documentation uses commands such as /speckit.constitution, while the skills installation creates /speckit-constitution. The examples below use the generated skill names.
The core Spec Kit workflow.
Optional checks for coverage and convergence.
Run the commands below one at a time in the Copilot CLI prompt, not in PowerShell or Bash. Review each artifact before moving to the next step.
-
/speckit-constitutiondefines the project-wide standards, such as favoring simple code, requiring automated tests, and keeping the command-line interface consistent. -
/speckit-specifydescribes the behavior users need without choosing the implementation technology. -
/speckit-clarifyresolves important gaps, such as whether a completed task can be reopened. -
/speckit-planturns the expected behavior into a technical design, including the stack and architectural boundaries. -
/speckit-tasksconverts the plan into executable work, while/speckit-analyzecan check a larger change for missing coverage. -
/speckit-implementwrites the code from the approved artifacts. -
/speckit-convergechecks the result against the specification and identifies anything still missing.
The constitution remains with the project. For every substantial feature, I repeat the same sequence: describe the behavior, choose the technical approach, break the work into tasks, and implement it. I review and commit the generated specs/ content so the reasoning travels with the code.
Seven habits worth stealing
These habits made the biggest difference in my work. They combine GitHub's best practices for using Copilot with lessons from real projects.
- Keep changes small enough to review and validate in one pull request. Extract validation now; move storage in a separate task.
- Correct mistakes as soon as Copilot follows a wrong assumption. If the project already has a
UserService, say so before the agent builds another abstraction. - Write rules that Copilot can verify. "Run
npm testand fix every failure before finishing" is more useful than "make sure it works." - Keep one outcome per session. Planning, implementation, tests, and review can stay together, but unrelated work should move to another session.
- Review how you use Copilot. The CLI command
/chronicle tipscan identify patterns in recent sessions and suggest improvements. - Turn repeated corrections into repository guidance.
/chronicle improvecan suggest updates to.github/copilot-instructions.md, but I review every proposal before applying it. - Use the defaults for routine work. I increase model strength or reasoning for a risky migration, not for renaming a test fixture.
What to do next
Start with the smallest setup that can improve a real task. In an existing repository, run copilot init and adapt the generated instructions. For a new project, start from my agentic-engineering template and replace its example rules with the commands and constraints from your own stack.
Then open one session for a small change and take it through implementation, automated checks, and review. Add a custom agent, skill, MCP server, or Spec Kit only when the current workflow gives you a reason.
That is the practical shift from vibe coding to agentic engineering. The improvement does not come from a longer prompt or more autonomy. It comes from better context, smaller tasks, executable checks, and human judgment at the points that matter.
Disclosure: I used GitHub Copilot as an editorial assistant while developing this article. I reviewed and verified the final content.
References
These are the main sources behind the product behavior and workflows described in this article.





Top comments (0)