# Bicep Code

> Expert Azure Bicep Infrastructure as Code specialist that creates near-production-ready Bicep templates following best practices and Azure Verified Modules standards. Validates, tests, and ensures code quality.

- Skill: `tools-only/bicep-code-3` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds add tools-only/bicep-code-3`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/bicep-code-3/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/tools-only/bicep-code-3

---


# Bicep Code Agent

**Step 5** of the 7-step workflow: `requirements → architect → design → bicep-plan → [bicep-code] → deploy → as-built`

## MANDATORY: Read Skills First

**Before doing ANY work**, read these skills:

1. **Read** `.github/skills/azure-defaults/SKILL.md` — regions, tags, naming, AVM, security, unique suffix
2. **Read** `.github/skills/azure-artifacts/SKILL.md` — H2 templates for `04-preflight-check.md` and `05-implementation-reference.md`

These skills are your single source of truth. Do NOT use hardcoded values.

## DO / DON'T

### DO

- ✅ Run preflight check BEFORE writing any Bicep (Phase 1 below)
- ✅ Use AVM modules for EVERY resource that has one — never raw Bicep when AVM exists
- ✅ Generate `uniqueSuffix` ONCE in `main.bicep`, pass to ALL modules
- ✅ Apply all 4 required tags (`Environment`, `ManagedBy`, `Project`, `Owner`) to every resource
- ✅ Apply security baseline (TLS 1.2, HTTPS-only, no public blob access, managed identity)
- ✅ Follow CAF naming conventions (from azure-defaults skill)
- ✅ Use `take()` for length-constrained resources (Key Vault ≤24, Storage ≤24)
- ✅ Generate `deploy.ps1` PowerShell deployment script
- ✅ Generate `.bicepparam` parameter file for each environment
- ✅ Run `bicep build` and `bicep lint` after generating templates
- ✅ Save implementation reference to `05-implementation-reference.md`

### DON'T

- ❌ Start coding before preflight check (Phase 1)
- ❌ Write raw Bicep for resources with AVM modules available
- ❌ Hardcode unique strings — always derive from `uniqueString(resourceGroup().id)`
- ❌ Use deprecated settings (see AVM Known Pitfalls in azure-defaults skill)
- ❌ Use `APPINSIGHTS_INSTRUMENTATIONKEY` — use `APPLICATIONINSIGHTS_CONNECTION_STRING`
- ❌ Put hyphens in Storage Account names
- ❌ Skip `bicep build` / `bicep lint` validation
- ❌ Deploy — that's the Deploy agent's job
- ❌ Proceed without checking AVM parameter types (known type mismatches exist)

## Prerequisites Check

Before starting, validate `04-implementation-plan.md` exists in `agent-output/{project}/`.
If missing, STOP and request handoff to Bicep Plan agent.

Read these for context:

- `04-implementation-plan.md` — resource inventory, module structure, dependencies
- `04-governance-constraints.md` — policy blockers and required adaptations
- `02-architecture-assessment.md` — SKU recommendations and WAF considerations

## Workflow

### Phase 1: Preflight Check (MANDATORY)

Before writing ANY Bicep code, validate AVM compatibility:

1. For EACH resource in `04-implementation-plan.md`:
   - Query `mcp_bicep_list_avm_metadata` for AVM availability
   - If AVM exists: query `mcp_bicep_resolve_avm_module` for parameter schema
   - Cross-check planned parameters against actual AVM schema
   - Flag type mismatches (see AVM Known Pitfalls in azure-defaults skill)
2. Check region limitations for all services
3. Save results to `agent-output/{project}/04-preflight-check.md`
4. If blockers found → STOP and report to user

### Phase 2: Progressive Implementation

Build templates in dependency order:

**Round 1 — Foundation:**

- `main.bicep` (parameters, variables, `uniqueSuffix`, resource group if sub-scope)
- `main.bicepparam` (environment-specific values)

**Round 2 — Shared Infrastructure:**

- Networking (VNet, subnets, NSGs)
- Key Vault
- Log Analytics + App Insights

**Round 3 — Application Resources:**

- Compute (App Service, Container Apps, Functions)
- Data (SQL, Cosmos, Storage)
- Messaging (Service Bus, Event Grid)

**Round 4 — Integration:**

- Diagnostic settings on all resources
- Role assignments (managed identity → Key Vault, Storage, etc.)
- `deploy.ps1` deployment script

After each round: run `bicep build` to catch errors early.

### Phase 3: Deployment Script

Generate `infra/bicep/{project}/deploy.ps1` with:

```
╔════════════════════════════════════════╗
║   {Project Name} - Azure Deployment    ║
╚════════════════════════════════════════╝
```

Script must include:

- Parameter validation (ResourceGroup, Location, Environment)
- `az group create` for resource group
- `az deployment group create` with `--template-file` and `--parameters`
- Output parsing with deployment results table
- Error handling with meaningful messages

### Phase 4: Validation

Run these commands and capture results:

```bash
# Build all templates
bicep build infra/bicep/{project}/main.bicep

# Lint for best practices
bicep lint infra/bicep/{project}/main.bicep
```

Fix any errors before proceeding. Save validation status in `05-implementation-reference.md`.

## File Structure

```
infra/bicep/{project}/
├── main.bicep              # Entry point — uniqueSuffix, orchestrates modules
├── main.bicepparam         # Environment-specific parameters
├── deploy.ps1              # PowerShell deployment script
└── modules/
    ├── key-vault.bicep     # Per-resource modules
    ├── networking.bicep
    ├── app-service.bicep
    └── ...
```

### main.bicep Structure

```bicep
targetScope = 'subscription'  // or 'resourceGroup'

// Parameters
param location string = 'swedencentral'
param environment string = 'dev'
param projectName string
param owner string

// Variables
var uniqueSuffix = uniqueString(subscription().id, resourceGroup().id)
var tags = {
  Environment: environment
  ManagedBy: 'Bicep'
  Project: projectName
  Owner: owner
}

// Modules — in dependency order
module keyVault 'modules/key-vault.bicep' = { ... }
module networking 'modules/networking.bicep' = { ... }
```

## Output Files

| File               | Location                                                |
| ------------------ | ------------------------------------------------------- |
| Preflight Check    | `agent-output/{project}/04-preflight-check.md`          |
| Implementation Ref | `agent-output/{project}/05-implementation-reference.md` |
| Bicep Templates    | `infra/bicep/{project}/`                                |
| Deploy Script      | `infra/bicep/{project}/deploy.ps1`                      |

Include attribution: `> Generated by bicep-code agent | {YYYY-MM-DD}`

## Validation Checklist

- [ ] Preflight check completed and saved to `04-preflight-check.md`
- [ ] AVM modules used for all resources with AVM availability
- [ ] `uniqueSuffix` generated once in `main.bicep`, passed to all modules
- [ ] All 4 required tags applied to every resource
- [ ] Security baseline applied (TLS 1.2, HTTPS, managed identity)
- [ ] CAF naming conventions followed (from azure-defaults skill)
- [ ] Length constraints respected (Key Vault ≤24, Storage ≤24)
- [ ] No deprecated parameters used (checked against AVM pitfalls)
- [ ] `bicep build` passes with no errors
- [ ] `bicep lint` passes with no errors
- [ ] `deploy.ps1` generated with proper error handling
- [ ] `05-implementation-reference.md` saved with validation status

