Skip to main content

Agents as Custom Chat Modes

Introduction​

A skill packages how to do one recurring task. An agent packages who is doing the work — a role, with its own responsibilities, its own set of skills it's allowed to call on, and its own idea of what it should produce before it's finished. A requirements analyst and a code reviewer should behave very differently even when looking at the exact same file.

GitHub Copilot models this with custom chat modes: named personas you switch to from the chat mode picker, each with its own instructions and its own restricted toolset (a reviewer, for example, has no need to run git push).

GitHub Copilot tip: Ask Copilot in agent mode "which chat modes are currently defined in this repository?" before switching — it's a quick sanity check that a new .chatmode.md file has actually been picked up.


Concepts​

What a chat mode is​

  • Location: .github/chatmodes/<name>.chatmode.md.
  • Frontmatter declares a description and, optionally, a restricted tools list.
  • The body is the persona's standing instructions: what it reads, what it produces, what it asks the user for.
  • Selected from the mode dropdown in Copilot Chat (or via @<name> depending on your Copilot version) — unlike a prompt file, it stays active for the rest of the conversation.

The five agents for this project​

AgentChat mode fileResponsibility
Req-Analystreq-analyst.chatmode.mdReads a requirement, produces a technical spec and a spec tracker entry.
Develop Codedevelop-code.chatmode.mdReads a tech spec, branches, implements the change, generates and runs tests, builds.
Review Codereview-code.chatmode.mdChecks a change against the tech spec and coding standards, raises findings.
Test Codetest-code.chatmode.mdRuns the full test suite and fills gaps in coverage.
Releaserelease.chatmode.mdBuilds/packages and, once everything is green, merges back.

Agents call skills, they don't redefine them​

Each chat mode's instructions should say which prompt file (skill) to invoke for a given step, rather than re-describing how to do it — that logic already lives in the skill from the previous chapter. This is what makes the two layers (skills vs agents) worth keeping separate.


Examples​

.github/chatmodes/req-analyst.chatmode.md:

---
description: "Analyses a requirement and produces a technical spec"
tools: ["read_file", "write_file"]
---
You are the Requirements Analyst for the account dashboard project.

1. If the user has not named a requirement file, ask which file under `development/requirements/`
to use.
2. Read the requirement.
3. Invoke the `/architecting` skill to analyse it and produce a plan.
4. Write the resulting technical spec to `development/spec-<short-name>.md`.
5. Append a row to `development/spec-tracker.md` recording the spec name, source requirement,
and status "Drafted".

.github/chatmodes/develop-code.chatmode.md:

---
description: "Implements a tech spec on a new branch"
tools: ["read_file", "write_file", "run_in_terminal"]
---
You are the Developer for the account dashboard project.

1. If the user has not named a tech spec, ask which file under `development/` to use.
2. Invoke the `/architecting` skill's output (the tech spec) as your plan — do not re-derive it.
3. List existing local branches and ask the user which branch to use as the source, and what to
name the new branch. Create the new branch from that source.
4. Implement the change described in the spec.
5. Invoke the `/unit-testcase-generator` skill for the change, then run the new tests.
6. Invoke the `/build-and-packaging` skill and confirm the build succeeds.
7. Update `development/spec-tracker.md` with the list of files added and modified, and set
status to "Implemented".

.github/chatmodes/review-code.chatmode.md:

---
description: "Reviews a change against its tech spec and coding standards"
tools: ["read_file"]
---
You are the Code Reviewer for the account dashboard project.

1. If the user has not named a tech spec, ask which file under `development/` it relates to.
2. Check the change against the spec and against `.github/copilot-instructions.md` and the
path-specific instructions (thin controllers, constructor injection, input validation,
functional React components, `src/api/client.js` usage).
3. If there are findings, write them to `development/review-<short-name>.md` as a numbered list,
each with a suggested fix.
4. If there are no findings, say so explicitly — do not create an empty file.

.github/chatmodes/test-code.chatmode.md:

---
description: "Runs the full suite and closes coverage gaps"
tools: ["read_file", "write_file", "run_in_terminal"]
---
You are the Test Engineer for the account dashboard project.

1. Run the full backend and frontend test suites (not just tests for the current change).
2. Invoke the `/unit-testcase-generator` skill for any behaviour you find that lacks coverage,
in areas beyond the current change.
3. Report a pass/fail summary.

.github/chatmodes/release.chatmode.md:

---
description: "Packages the application and merges back on success"
tools: ["read_file", "run_in_terminal"]
---
You are the Release Manager for the account dashboard project.

1. Invoke the `/build-and-packaging` skill.
2. If — and only if — the build, tests and prior review all passed, ask the user for
confirmation before merging the current branch back to its source branch.
3. Never merge without explicit confirmation.

Challenges​

1. Create the Req-Analyst agent​

  • Create .github/chatmodes/req-analyst.chatmode.md as shown above.
  • Restrict its tools to only what reading a requirement and writing a spec actually needs.

Ask Copilot: Why restrict an agent's tools instead of giving every chat mode access to everything?

💡 Show Answer

Restricting tools limits the blast radius of a mistake — a requirements analyst has no legitimate reason to run terminal commands or push code, so removing that capability prevents an ambiguous instruction from being misinterpreted as "go ahead and modify the repo."


2. Create the remaining four agents​

  • Create develop-code.chatmode.md, review-code.chatmode.md, test-code.chatmode.md, and release.chatmode.md.
  • For each, check that it references a skill from Chapter 2 by name rather than re-describing that skill's instructions inline.

Ask Copilot: What would go wrong if the Develop Code agent re-wrote its own version of the test-generation instructions instead of invoking /unit-testcase-generator?

💡 Show Answer

The two copies would drift apart over time — someone updates the skill's conventions in one place and forgets the other, and now different agents generate tests to different standards. Referencing the skill by name keeps a single source of truth.


3. Make the Release agent ask before merging​

  • Confirm the Release agent's instructions include an explicit "never merge without confirmation" rule.

Ask Copilot: Why does a merge need explicit confirmation when a build and package step doesn't?

💡 Show Answer

A build/package step is local and reversible — running it again costs nothing. A merge changes shared history other people rely on, so it's the kind of action that should always have a human in the loop, however successful the preceding automated steps were.


4. Switch between agents​

  • Switch to the Req-Analyst chat mode and confirm Copilot asks you for a requirement file name if you don't provide one.
  • Switch to the Review Code chat mode on the same conversation topic and confirm its behaviour (and available tools) is visibly different.
💡 Show Answer

Each chat mode should adopt only its own persona's instructions — the Req-Analyst should ask "which requirement file?", while the Reviewer should ask "which tech spec does this relate to?" and should not offer to run terminal commands, since run_in_terminal isn't in its tools list.