Building Better Azure Terraform Modules with GitHub Copilot Agents and Skills


If you’ve ever tried to put together a “simple” Terraform module for Azure, you’ll know it rarely stays simple.

You start with a couple of resources. Then someone asks for tags. Naming has to follow Azure CAF. Security defaults need tweaking. Monitoring gets bolted on late. By the time you open a pull request, the Well‑Architected Framework review points out gaps, and you’re back rewriting half the plan.

I’ve been using GitHub Copilot custom agents and skills to cut down on that churn – faster starts, consistent structure, and less copy‑paste drudgery – without losing flexibility when it matters. I set up a shared repo so you can use the same patterns. Here’s the gist.

Repo: github-copilot-skills-terraform

Agent vs Skills

A small intro for now, i’ve another blog post incoming to discuss my thoughts further but, here’s briefly how I think about it:

  • Skills are reusable knowledge packets

Put them in .github/skills/

Example: azure-verified-modules skill with Microsoft‑recommended TLS settings, endpoint rules, and variable validation patterns.

  • Agents are personas with workflows and tool access.

Store them in .github/agents/

Example: terraform-module-expert agent that calls the azureterraformbestpractices MCP tool first, then loads the AVM skill before writing code.

Skills load automatically when relevant. Agents you call explicitly with @agent-name in Copilot Chat.

Why This Matters for Terraform

When you’re managing infrastructure as code, you deal with:

  • Security best practices that must be consistently applied
  • Complex module patterns that follow organisational standards
  • CI/CD workflows that require specific configurations

Without skills, you’d need to explain these requirements in every chat session. With skills, this knowledge becomes part of the agent’s capabilities.

How they work together

Here’s where the magic happens – agents can reference skills. Let me show you a real example from my repository:

The Terraform Module export agent (link to agent in repo)

---
name: Terraform Module Expert
description: An expert agent for discovering, evaluating, and implementing Azure Terraform modules. Helps create custom modules following Azure Verified Module patterns, reduce code duplication, and best practices.
tools:
  - vscode
  - execute
  - read
  - edit
  - search
  - web
  - azure-mcp/azureterraformbestpractices
  - azure-mcp/documentation
  - azure-mcp/get_azure_bestpractices
  - azure-mcp/search
  - terraform/*
  - agent
  - todo
---

Mandatory workflow

BEFORE generating any Terraform code:

1. Must Call azureterraformbestpractices get tool

2. Must Reference the azure-verified-modules skill to learn AVM patterns

3. Generate code with best practices applied

The workflow in action

Lets kick-off an example, with agent “Terraform Module Expert” with my simple prompt: Create me an azure virtual network module

Right away, look whats happening, heres the direct agent output:

The user is asking me to create an Azure virtual network module. Based on my instructions as a Terraform Module Expert, I need to follow the mandatory workflow:

Must Call azureterraformbestpractices get first
Optionally Call get_azure_bestpractices get --resource general --action code-generation for general Azure guidance
Must Reference the azure-verified-modules skill to learn AVM patterns
Must Use Terraform Registry tools to search for reference examples
Apply best practices and generate code
Since this is a template repository (not actual infrastructure), I'm creating a new module. This appears to be a greenfield situation. According to my instructions, I should:

Follow the recommended folder structure
Ask the user if they want to follow the recommended structure or have preferences
Explain why the structure is recommended
Let me start by calling the required tools in parallel where possible:

azureterraformbestpractices - Must call first
Get latest azurerm provider version
Search for virtual network provider details
Reference the azure-verified-modules skill
Then I'll create the module structure.
Screenshot of vscode github copilot showing the agent thinking

Not going to outline all of the above, but look what its doing:

  • Mandatory first step: Invoke azureterraformbestpractices to align with core Terraform + Azure standards
  • Optional guidance: Query get_azure_bestpractices (resource=general, action=code-generation) for cross-cutting Azure patterns
  • Design baseline: Reference Azure Verified Modules (AVM) patterns to ensure future compatibility and consistency
  • Research phase: Use Terraform Registry to review existing VNet modules and provider examples
  • Provider alignment: Confirm latest azurerm provider version and supported VNet features
  • Module creation: Greenfield module → apply recommended Terraform module folder structure
  • User decision point: Ask whether to adopt the recommended structure or customise
  • Rationale: Explain why the structure improves reusability, testing, documentation, and AVM alignment
  • Outcome: Generate a clean, best-practice VNet module template (no live infrastructure)

Awesome – right? Below its going off to do its learning

Showing GitHub copilot agent learning patterns from skills and referencing MCP server tools

Letting me know its a new module and the structure its going to use (provided from my agent skills):

infra/modules/virtual-network/
├── main.tf                     # Resource definitions
├── variables.tf                # Input variables with validation
├── outputs.tf                  # Module outputs
├── versions.tf                 # Provider requirements
├── README.md                   # Module documentation
└── examples/                   # Working examples (REQUIRED)
    └── basic/
        ├── main.tf
        ├── variables.tf
        ├── outputs.tf
        ├── terraform.tfvars.example
        ├── example.auto.tfvars
        └── README.md

Looking at the agent output, all is covered!

Screenshot of GitHub copilot agent output showing key features that the Terraform module will have

What features has been added to this module without me providng any detail?

  • Virtual Network with custom address spaces
  • Multiple subnets with flexible configuration
  • Service endpoints for PaaS integration
  • Subnet delegation for specialized services
  • NSG and Route Table associations
  • DDoS Protection Standard support (optional)
  • Custom DNS server configuration
  • Private endpoint network policies
  • Comprehensive input validation
  • Tagged resources for governance

All the above from a single line prompt – awesome!

That also matches Azure Well‑Architected Framework guidance without me having to list it all. Looking at some of the output from the module readme it provided:

### Naming Convention
Follow Azure naming conventions: `vnet-{workload}-{environment}-{region}-{instance}`

Example: `vnet-webapp-prod-eastus-001`

### Address Planning
- Use RFC 1918 private address spaces: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
- Reserve space for future growth
- Plan for peering with other VNets and on-premises networks
- Avoid overlapping address spaces

### Security
- Always associate NSGs with subnets containing resources
- Use service endpoints for PaaS services to keep traffic on Azure backbone
- Disable public network access where possible
- Use private endpoints for PaaS services in production

It also includes a basic example for you to get started with:

module "vnet" {
  source = "./modules/virtual-network"

  name                = "vnet-webapp-prod-eastus-001"
  location            = "eastus"
  resource_group_name = "rg-networking-prod-eastus-001"
  address_space       = ["10.0.0.0/16"]

  subnets = {
    web = {
      name             = "snet-web"
      address_prefixes = ["10.0.1.0/24"]
    }
    app = {
      name             = "snet-app"
      address_prefixes = ["10.0.2.0/24"]
    }
    data = {
      name             = "snet-data"
      address_prefixes = ["10.0.3.0/24"]
      service_endpoints = ["Microsoft.Sql", "Microsoft.Storage"]
    }
  }

  tags = {
    environment = "prod"
    project     = "webapp"
    owner       = "platform-team"
    cost-center = "engineering"
    managed-by  = "terraform"
  }
}

Getting Started

1. Clone the repo:

git clone https://github.com/thomast1906/github-copilot-skills-terraform.git

2. Copy .github/agents and .github/skills into your project.

3. Install MCP servers:

  • Terraform MCP via Docker
  • Azure MCP via VS Code extension

4. Add .github/copilot-instructions.md with your global rules.

5. Test an agent in Copilot Chat:

Create an Azure storage account module

Wrapping Up

Agents define what GitHub Copilot does.

Skills give it the knowledge to do it right.

Used together in a Terraform workflow, they cut repetition, catch problems earlier, and free you up for the decisions that actually need a human.

If you want to try it, grab the repo, set up one skill for your most common Terraform task, build an agent that uses it, and run it on a routine build.

You’ll see the difference in the very first review cycle.

The goal was simple: push the repetitive, standards‑driven work into an automated baseline so you can spend your time on actual design choices.

The repo will keep growing with new agents and skills. If you’ve got patterns that work in production, I’m happy to add them. (Feel free to PR them 🙂 )

1 thought on “Building Better Azure Terraform Modules with GitHub Copilot Agents and Skills”

Leave a Reply

Discover more from Thomas Thornton Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading

Discover more from Thomas Thornton Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading