Building Effective Agent Architectures with GitHub Copilot
Honest disclaimer: The thoughts here are mine — the prose, structure, and general readability are courtesy of AI. I handed it a brain-dump and it handed back something you'd actually want to read. Felt appropriate, given the topic.
GitHub Copilot's customization system separates into four distinct layers: custom agents, instructions, skills, and MCP servers. Each handles a different concern, and they compose together while remaining independently upgradeable.
The key insight: separating "who" (agent workflow), "rules" (project standards), and "how" (capabilities) means you can change one without touching the others. Update standards without rewriting agents. Upgrade skills without modifying instructions. Change agent behavior while keeping conventions intact.
Everything lives in git. Changes go through pull requests. You can review, approve, and roll back AI behavior like infrastructure.
Project Structure
A typical setup:
.github/
├─ agents/ # Custom workflow agents
├─ instructions/ # Context-specific standards
├─ skills/ # Reusable capabilities (SKILL.md files)
└─ copilot-instructions.md # Global standards
.vscode/
└─ mcp.json # MCP server configsAll version controlled in your repo. Skills are SKILL.md files that define specific operations agents can invoke.
All reviewable through PRs.
Quick example: Want all API errors to follow a consistent format?
# .github/instructions/api.instructions.md
---
applyTo: 'src/api/**'
---
Return errors as: { "error": { "code": "...", "message": "..." } }Copilot applies this automatically when working on API files. Standard enforced through the tool, not documentation.
The Four Layers
1. Custom Agents
Custom agents define workflow orchestration. They specify which tools are available, coordinate multi-step processes, and delegate to specialist agents.
# .github/agents/feature-builder.agent.md
---
name: Feature Builder
tools: ['agent']
agents: ['Researcher', 'Implementer']
---
Coordinate feature development by delegating research to Researcher (read-only) and implementation to Implementer (write-access).When custom agents work well:
- Multi-phase workflows with distinct tool needs
- Tool restrictions prevent accidents (researcher can't modify code)
- Specialized expertise per domain
Keep workflow logic here, not coding standards.
2. Instructions
Instructions define project standards that apply automatically based on file context.
# .github/instructions/api.instructions.md
---
applyTo: 'src/api/**'
---
- Validate input with Joi schemas
- Return errors as: { "error": { "code": "...", "message": "..." } }
- Include testsGlobal instructions (.github/copilot-instructions.md) apply everywhere. Targeted instructions use applyTo patterns for file-specific rules.
When instructions work well:
- Team-wide conventions that always apply
- File-specific standards (API patterns, component conventions)
- Replacing documentation with enforcement
Keep global instructions under 50 lines. Use targeted files for context-specific rules.
3. Skills
Skills extend what agents can do by providing specific, invokable capabilities. You define them as SKILL.md files in .github/skills/, and agents gain new operations they can perform.
# .github/skills/github-pr-analyzer.SKILL.md
---
name: GitHub PR Analyzer
---
Analyze pull requests for code quality issues, suggest improvements,
and summarize changes for review.Skills are executable capabilities. When an agent needs to analyze a PR, it invokes the skill. The skill handles the complex logic; the agent uses the result.
Skills load automatically when relevant. Any agent can invoke any skill in your .github/skills/ directory, making capabilities instantly reusable across workflows.
When skills make sense:
- Complex operations requiring specialized logic
- Reusable capabilities across multiple agents
- Domain-specific workflows you want to standardize
4. MCP Servers
MCP servers connect Copilot to external systems—databases, APIs, cloud services.
// .vscode/mcp.json
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": { "POSTGRES_CONNECTION": "${env:DATABASE_URL}" }
}
}
}When MCP works well:
- Agents need runtime data (database schemas, API state)
- External system information affects decisions
- Data lives outside your codebase
Use environment variables for credentials. Start with read-only operations.
Why Separation Matters
Independent layers mean independent updates. Four examples:
Adding Capabilities
Adding capabilities: Add a new skill file to .github/skills/, and all agents can immediately invoke it. For example, add a PR analyzer skill and all agents gain PR analysis capabilities.
Enforcing Standards
Enforcing standards: Add API validation requirement to instructions file. Copilot applies it automatically when working on APIs. No reminders needed.
Changing Workflows
Changing workflows: Update feature-builder agent to be more thorough during planning. Standards stay unchanged in separate instruction files.
Switching Data Sources
Switching data sources: Move from local Postgres to cloud database by updating MCP server config. Agents and instructions stay the same—only connection details change.
Shared standards across projects: Create a shared repository of instruction files. Reference them in multiple services via git submodules or sync scripts. Update once, all services benefit.
When to Use Each Layer
Static rule that always applies → Instructions
Multi-step workflow → Custom Agent
Reusable specialized operations → Skills
Runtime data access → MCP
Examples:
- "All API errors use format X" → Instructions
- "Check if users table has email column" → MCP
- "Use TypeScript strict mode" → Instructions
- "Coordinate research then implementation" → Custom Agent
- "Summarize this GitHub PR" → Skills
Version Control as Governance
These files live in git. Changes go through pull requests:
git checkout -b add-api-validation
# Edit .github/instructions/api.instructions.md
git commit -m "Add email validation requirement"
# Team reviews in PR, merges when approvedAll four layers live in your repository as version-controlled files.
For regulated teams:
- Compliance requirements live as code
- Git provides audit trail (who changed what, when)
- Review gates enforce governance through workflows
- Rollback works like any infrastructure change
You can require security team approval for compliance instruction changes, just like production deployments.
Start Simple
Begin with global instructions:
.github/copilot-instructions.md (20-30 lines covering core standards)Add skills when you need reusable capabilities:
.github/skills/
└─ github-pr-analyzer.SKILL.mdAdd agents when repetitive workflows appear:
.github/agents/
└─ feature-builder.agent.mdSplit instructions by context when global file grows:
.github/instructions/
├─ api.instructions.md
└─ components.instructions.mdAdd orchestration when multi-phase workflows become common:
.github/agents/
├─ feature-builder.agent.md (orchestrator)
├─ researcher.agent.md (specialist)
└─ implementer.agent.md (specialist)Integrate external systems when runtime data is needed:
.vscode/mcp.json (MCP servers)Each stage solves a real problem. Build complexity incrementally.
Common Pitfalls
Mixing standards into agents: Keep workflow in agents, standards in instructions. If it applies to all work in a directory, it's an instruction.
Monolithic instructions: Don't put everything in one 3000-line file. Split by context using applyTo patterns.
Over-engineering early: Don't create 25 hyper-specific agents before you know what you need. Start with instructions, add agents as workflows emerge.
Duplicating skills unnecessarily: Check existing skills before creating new ones. Don't create five variations of the same operation.
Hardcoding credentials in MCP configs: Use environment variables (${env:VAR_NAME}) for sensitive data. Never commit credentials to version control.
Wrapping Up
The layered approach gives you separation of concerns, independent upgrades, and version-controlled governance.
Agents define workflow. Instructions enforce standards. Skills provide reusable capabilities. MCP accesses external data.
When these work independently, you can upgrade skills without rewriting agents, update standards without touching workflows, and change agent behavior while keeping rules intact.
Version control makes this infrastructure. Changes go through PRs. Git provides audit trails. Everything is reviewable and rollback-able.
For regulated teams, compliance lives as code with traceable changes and enforced review gates.
Start with instructions. Add agents when workflows repeat. Add MCP when external data is needed. Build incrementally.
The value comes from composability, not complexity.
References
Official Documentation:
Comments
Post a Comment