Prompt engineering & custom instructions
Good prompts are specific about the outcome, grounded in context, and explicit about constraints and verification. Anything you repeat belongs in custom instructions.
Anatomy of a strong prompt
Five parts. Not every prompt needs all five, but agent tasks almost always do.
Add rate limiting to the public REST API.
Routes live in #src/api/routes; we use Express 5 and Redis (#src/lib/redis.ts).
100 req/min per API key, 429 with Retry-After header, no new dependencies except rate-limiter-flexible.
e.g. 101st request in a minute → 429, Retry-After: 37.
Add integration tests and run `npm test -- api`. Summarise the changes.
01
State the outcome, not just the action
“Add pagination” is an action. “GET /orders returns 50 items per page with a `next` cursor; existing clients keep working” is an outcome Copilot can verify against.
02
Ground it in context
Attach the exact files, symbols, errors or issue URL. Use #codebase when you don't know where the code lives. Close unrelated tabs — open editors feed inline suggestions.
03
Set explicit constraints
Name the language version, libraries allowed or forbidden, performance limits, public API that must not change, and the style to follow.
04
Show, don't describe
An input/output example or a sample test pins down behaviour more precisely than paragraphs of prose.
05
Break big work into steps
Ask the Plan agent (or /plan) first, review it, then implement step by step. Smaller steps make diffs reviewable and failures cheap.
06
Ask it to verify
End with how to check the work: “run npm test -- billing and fix failures”. Agents can run commands, so tell them which.
07
Iterate and steer
Treat the first answer as a draft. Reply with what's wrong, steer mid-run, or restore a checkpoint and re-prompt.
08
Encode repeat advice
If you type the same guidance twice, move it into custom instructions, a prompt file, or a skill.
Constraints that act like a system prompt
You can't edit Copilot's system prompt, but instructions files are injected alongside it on every chat and agent request. Write them as rules, not essays.
- Use imperative, testable rules: “Use Zod for validation”, not “we generally like validation”.
- State the stack and versions: framework, language level, package manager.
- List the exact commands to build, lint and test — agents will run them.
- Name forbidden things: libraries, patterns, files the agent must never edit.
- Keep it short. Long instruction files dilute attention and cost context.
- Put language- or folder-specific rules in scoped .instructions.md files.
How instructions layer
All applicable instructions are combined. When they conflict, the more specific source wins.
| Layer | Location | Applies to |
|---|---|---|
| Organization instructions | GitHub organization settings | Every member's supported Copilot sessions |
| Personal instructions | ~/.copilot/copilot-instructions.md · ~/.copilot/instructions/ | You, across all projects |
| Repository instructions | .github/copilot-instructions.md · AGENTS.md | Everyone working in the repo |
| Scoped instructions | .github/instructions/**/*.instructions.md | Files matching applyTo, or tasks matching description |
| Custom agent | .github/agents/*.agent.md | Requests while that agent is selected — wins on conflict |
Repository-wide: .github/copilot-instructions.md
Automatically included in every chat, agent and code-review request in the repo. Generate a first draft with /init in VS Code chat, then edit it.
# Project instructions
## Stack
- TypeScript (strict) on Node.js 20+. React 19 for UI, Vitest for tests.
- Prefer the standard library and existing utilities in `src/lib` before adding a dependency.
## Architecture
- HTTP handlers live in `src/api/routes`; data access lives in `src/repositories`.
- Keep functions small and pure where practical; isolate side effects at the edges.
## Conventions
- Use named exports. File names are kebab-case; React components are PascalCase.
- Never swallow errors: return a typed `Result` or throw a domain error with context.
- No secrets, tokens or credentials in code, tests or fixtures.
## Validation
- Run `npm run typecheck && npm test -- <changed-area>` after changing code.
- Add or update tests for every behaviour change.AGENTS.md works too
AGENTS.md at the repo root (or in subfolders for monorepos) is recognised by VS Code, Copilot CLI and Copilot coding agent, as well as other AI tools.Scoped: *.instructions.md with applyTo
Rules that only apply to matching files. The front matter controls when they load.
---
name: 'Unit tests'
description: 'Use when creating or updating unit tests.'
applyTo: '**/*.{test,spec}.{ts,tsx,js}'
---
# Unit test conventions
- Use Vitest (`describe` / `it` / `expect`). One behaviour per `it`.
- Name tests `<unit> <behaviour> when <condition>`.
- Arrange–Act–Assert, with a blank line between sections.
- Cover the happy path, boundaries, and at least one failure path.
- Do not mock what you own; mock network, clock and filesystem only.---
name: 'React components'
description: 'Use when creating or editing React components.'
applyTo: 'src/components/**/*.tsx'
---
# React component rules
- Function components only; props typed with a named `type Props`.
- Server Components by default; add `"use client"` only for state, effects or browser APIs.
- Style with Tailwind utilities using design tokens (`bg-bg`, `text-fg`, `text-accent`) — never raw hex.
- Every interactive element is keyboard-reachable and has an accessible name.# AGENTS.md
Shared instructions for every AI coding agent (Copilot, Codex, others).
## Setup
- Install: `npm ci`
- Dev server: `npm run dev`
- Checks: `npm run typecheck && npm run lint && npm test`
## Rules
- Make the smallest change that fully solves the task.
- Run the checks above before declaring work complete.
- Never commit secrets or edit generated files in `dist/`.Remember