Treating Copilot coding agent like a new hire

GitHub Copilot's coding agent mode is designed to work like an AI peer programmer: assign it an issue and it creates a branch, opens a pull request, and iterates on a solution inside a GitHub Actions container. While that workflow is automated, the quality of the output depends heavily on how well you prepare the environment, documentation, and instructions—much like onboarding a human developer.

Understanding the sequence Copilot follows helps you know where your input matters. After it creates the branch and pull request (steps that need no configuration from you), Copilot moves into a contained Actions environment, reads the assigned issue, explores the repository, and works iteratively until it finalizes a proposed change and updates the PR for review.

Configuring the working environment with a custom Actions workflow

Copilot coding agent runs inside a container hosted by GitHub Actions. To give it the same tooling your team uses, you can define a custom workflow file at .github/workflows/copilot-setup-steps.yml with a job named copilot-setup-steps. Inside that job, list steps that install dependencies, set up services, and prepare the environment. For example, a Python application using SQLite could use a workflow file like this:

name: "Copilot Setup Steps"

# Automatically run the setup steps when they are changed
# Allows for streamlined validation,
# and allow manual testing through the repository's "Actions" tab

on:
  workflow_dispatch:
  push:
    paths:
      - .github/workflows/copilot-setup-steps.yml
  pull_request:
    paths:
      - .github/workflows/copilot-setup-steps.yml

jobs:
  # The job MUST be called `copilot-setup-steps`
  # otherwise it will not be picked up by Copilot.
  copilot-setup-steps:
    runs-on: ubuntu-latest

    # Permissions set just for the setup steps
    # Copilot has permissions to its branch
    
    permissions:
      # To allow us to clone the repo for setup
      contents: read

    # The setup steps - install Python and our dependencies
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: "3.13"
          cache: "pip"

      - name: Install Python dependencies
        run: pip install -r requirements.txt

      - name: Install SQLite
        run: sudo apt update && sudo apt install sqlite3

When an issue is assigned to Copilot, this workflow runs automatically to configure the container before Copilot begins its work.

💡 Pro tip: If you know something should be done a particular way, tell Copilot! In our above example, Copilot could install the requisite services on its own. However, doing so may lead to unexpected versions or other mistakes. As I always like to joke, don’t be passive aggressive with Copilot. 😀

Writing issues that set Copilot up for success

The issue or prompt is Copilot's entry point—the more precise it is, the better the resulting pull request. Think about what you'd want in your first assignment on a new project: a clearly defined problem statement or user story, full error messages or reproduction steps for bugs, prior attempts, and suggestions for how to approach the problem.

Consider migrating a test suite from unittest to pytest. Copilot can likely figure out the general approach, but a well-specified issue saves time and reduces the chance of a rejected PR. A good issue works for both human and AI developers:

Title: Migrate server tests from unittest to pytest

Body:

We are looking to migrate from unittest to pytest to take advantage of some pytest specific features.

Requirements:

- A new folder called `migrated_tests` will be created with the new pytest tests.
- All existing unittests are rewritten using pytest style in the `migrated_tests` folder, keeping the exact same functionality and code coverage.
- Documentation is updated, highlighting the migration and steps required to run the new tests.
- All new tests pass.

Existing resources:

- All existing tests exist in `server/tests`
- There is a script at `scripts/run-server-tests.sh` which is used to run tests and generate code coverage reports

Recommended approach:

- Explore existing tests to determine their functionality
- Read the coverage reports to determine existing code coverage
- Recreate the tests one by one, testing along the way, to ensure compatibility
- Run all tests at the end to ensure everything passes
- Generate a code coverage report to demonstrate code coverage has been maintained
- Generate documentation of the migration and how to run the new tests

Making your repository easy for Copilot to navigate

A developer starting on a new project needs to understand the structure, coding conventions, and project rules. Copilot coding agent needs the same signals. When assigned an issue, it explores the codebase, reads README files, and searches for relevant code patterns before it starts writing anything.

Standard documentation best practices pay off here. A robust, up-to-date README that describes the project and services, comments that explain what and how operations work, and consistent naming for classes, functions, and variables give Copilot a reliable map. A logical folder structure that follows accepted conventions also makes exploration more predictable.

💡Pro tip: Understanding how Copilot tackles problems can help you improve how you use it. Here’s how to do that: On the PR Copilot created you’ll see a View session button that shows you everything Copilot did (or is doing if the session is currently active). This is both a great way to validate Copilot’s work and see how it approaches tasks. You can then use this information to further refine your approach to assigning tasks and configuring Copilot’s environment.

Using custom instructions files to encode team knowledge

Custom instructions let you document the rules and institutional knowledge that developers pick up but rarely write down. Copilot coding agent recognizes two types of instruction files: copilot-instructions.md for repository-wide rules, applied to all requests, and <file-name>.instructions.md for guidance targeting specific file types or paths.

Repository-level instructions

Place a repository-level file at .github/copilot-instructions.md. This helps Copilot understand the project context it can't always infer on its own. Include:

  • An overview of what you're building and how it fits together
  • Key user stories or product goals
  • Frameworks and libraries in use
  • Project structure notes highlighting important files and folders
  • Global coding guidelines and rules

In the example below, the file starts with an app overview, user flow, frameworks, rules, and available resources:

# Classic arcade

This project hosts a classic arcade, themed after the 1980s 8-bit games.

## Standard player flow

1. Player opens app and sees list of games.
2. Player selects game to play.
3. Player sees a splash screen with the message "Insert quarter".
4. Player presses space to start game and plays game
6. After game ends, the "Game over" message is displayed.
7. The player score is checked against high scores. If the score is in top 10, user is prompted for their initials (3 initials).
8. High scores are displayed, and an option to return to the main menu to start over again.

## Frameworks

- Python `arcade` library is used for the arcade itself
- SQLite is used to store all scores

## Coding guidelines

- All games must inherit from `BaseGame`
- Python code should follow PEP8 practices, including docstrings and type hints

## Project structure

- `data`: Stores data abstraction layer and SQLite database
- `games`: Stores collection of games and `BaseGame`
- `app`: Stores core app components including menuing system

These details might be discoverable through investigation, but writing them down helps Copilot avoid wrong assumptions—especially when code deviates from accepted best practices.

Targeted instructions for specific file types

Unit tests, data layers, and UI code each follow different conventions. For file-specific rules, use <file-name>.instructions.md files stored in the .github/instructions/ folder or its subfolders. Each file can contain an applyTo section that uses a glob pattern to target specific files. For instance, with Python game files in a games folder, you might use the pattern **/games/*.py. An example file named .github/instructions/game.instructions.py might look like this:

---
applyTo: **/games/*.py
---

## Resources and requirements

- All games inherit from `BaseGame`
- Unit tests are required for all games, focused on core functionality
- When adding a new game to the arcade ensure sample high scores are added to the database

## Arcade framework notes

- `rectangle` is always abbreviated as `rect` in the framework
- The `BaseGame` class contains numerous abstractions to streamline game creation

Note that this file lists requirements and resources, and it explicitly documents that rectangle should be abbreviated as rect—a common mistake Copilot might otherwise repeat. These targeted files help prevent recurring errors and keep file-specific conventions consistent.

💡Pro tip: Instructions files are a great way to guide Copilot in the right direction when you see it making particular types of mistakes.

Investing in solid instruction files pays off twice: it improves Copilot's output in the IDE and when you assign work to coding agent. Because these files become part of the repository, they remain useful artifacts that keep improving suggestion quality over time.

Giving Copilot more context with MCP servers

Every developer hits a point where they need to look something up — whether that's digging through repository history for context on an old feature, or checking syntax for a specific algorithm. AI agents handle these kinds of tasks through Model Context Protocol (MCP), an open standard from Anthropic designed to connect AI models to external services and data sources.

MCP isn't just about letting agents execute actions; it also expands the model's context by tapping into more data sources. GitHub Copilot coding agent supports MCP servers out of the box, with two enabled by default: the GitHub server for interacting with repositories and searching issues, and Playwright for generating end-to-end and acceptance tests using Copilot's built-in web browser.

Example: Azure MCP server for Bicep generation

Take Azure Bicep, a domain-specific language (DSL) for defining Azure resources. Copilot benefits from extra support when generating code for a DSL like Bicep, and the Azure MCP server provides just that.

If your team already uses MCP servers in VS Code, Copilot can pick those up automatically from the project's .vscode/mcp.json file. Otherwise, you can configure MCP servers specifically for the coding agent under the project's Settings tab, then Copilot and Coding agent, where a textbox accepts the JSON configuration.

To tailor the Azure MCP server for Bicep work only, the following configuration limits the server to Bicep schema support:

{
  "mcpServers": {
    "AzureBicep": {
      "type": "local",
      "command": "npx",
      "args": [
        "-y",
        "@azure/mcp@latest",
        "server",
        "start",
        "--namespace",
        "bicepschema",
        "--read-only"
      ]
    }
  }
}

Controlling internet access and data exfiltration risks

The type field in the MCP example above is set to local, meaning the server runs inside the container without Copilot contacting external services. But the possibility of a remote server raises an important question: is Copilot allowed to hit the internet, and if so, how is that governed?

Copilot coding agent ships with a default firewall that limits access to core services like package registries including npm and pip. This containment helps mitigate data exfiltration risks — for example, if malicious instructions were injected into GitHub Copilot, the firewall prevents code or sensitive information from leaking to remote hosts.

Adding a remote MCP server, or otherwise needing Copilot to reach internet resources, requires updating the firewall's allow list. That configuration lives in the same place as MCP server settings: under the repository's Settings, then Copilot and Coding agent.

Setting Copilot up for success

Like any teammate, GitHub Copilot coding agent performs best with proper preparation. Investing time upfront to shape its environment, draft clear issue descriptions, optimize the project layout, and wire up custom instructions and MCP servers all contribute to higher-quality pull requests and a smoother development workflow.