Spec First, GitOps Second: The Platform Engineer's Guide to BMAD¶
Here's a pattern I see constantly with platform teams that have started leaning on AI: they skip straight to building. The security team needs vulnerability data in Prometheus so they can alert on critical CVEs in Grafana. Someone spins up a chat window and asks Claude to "write the ArgoCD Application for the tenable-exporter." No PRD. No architecture decision about secret management. No agreement on scrape interval or which clusters it deploys to. Just vibes and YAML.
And it works, kind of, for a while. Until the tenth iteration when the agent has lost context, the generated code contradicts a decision made in session two, and nobody can remember why they chose that particular pattern.
BMAD is the antidote. It's what happens when you take agile project discipline — upstream thinking before downstream building — and wire it into your AI workflow. And if you're already doing GitOps, the mental model maps perfectly: you don't kubectl apply before you know what you're applying. You shouldn't prompt an AI agent before you know what you're building.
49K reasons people are paying attention
BMAD-METHOD hit ~49,000 GitHub stars in June 2026 with v6.8.0 shipping in late May. It's the most-starred open-source spec-driven AI development framework right now — and it has a dedicated Platform Engineer agent (Sam) built specifically for Kubernetes, GitOps, and IaC workflows.

What BMAD actually is (and what it isn't)¶
BMAD stands for Breakthrough Method for Agile AI-Driven Development. It's open source, MIT licensed, and lives at bmad-code-org/BMAD-METHOD on GitHub.
It's not a coding tool. It's not an IDE plugin. It doesn't write code for you and it's not a collection of clever prompts. It's a workflow framework — a structured way to engage AI agents across the full lifecycle of a project, from the first rough idea through to production-ready code.
The core insight is the two-phase split:
- Upstream (thinking): You work with AI agents to produce PRDs, architecture decisions, and user stories before a single line of code is written. Think of it as your sprint 0, but AI-assisted.
- Downstream (building): The implementation agents consume the upstream artefacts as context. They know what to build and why — because it's written down.
The agents have names and personas: Mary (Business Analyst), Preston (Product Manager), Winston (Architect), Sally (Product Owner), Devon (Developer), Quinn (QA), and — importantly for us — Sam, the Platform Engineer, who specialises in Kubernetes, CI/CD pipelines, GitOps, and observability.
What makes it different from just "prompting carefully" is the file-based context chain. Each upstream document becomes a first-class input for the next agent. The PRD constrains the architect. The architecture constrains the developer. Nothing is re-derived from memory because everything is written to files — and you commit them to Git.
BMAD isn't magic prompts — it's structured context
The framework's power isn't clever system prompts. It's the file-based context chain: each upstream document becomes a first-class input for the next agent. The PRD constrains the architect. The architecture constrains the developer. Nothing is re-derived from memory because everything is written to files — which means you can commit them to Git.
BMAD vs GitHub's spec-kit: same idea, different problem¶
If you've come across GitHub's spec-kit, you might be wondering what the difference is. Both are spec-driven development tools. Both say "write the spec before you write the code." So why would you reach for BMAD?
The key distinction is who writes the spec, and how.
spec-kit is a spec format tool. It gives you a structured SPEC.md template and a set of Copilot prompt helpers to guide AI implementation from that spec. It's well-designed and genuinely useful — but the implicit assumption is that you already know what to specify. You fill in the template, then feed it to Copilot to implement. The spec is something you produce, and the AI consumes it.
BMAD flips this. The spec is something you co-produce with AI agents through structured dialogue. Preston doesn't accept your first rough idea — it challenges your assumptions, narrows your scope, and forces you to answer questions you didn't think to ask. Winston doesn't just implement from a brief — it evaluates your problem and makes explicit technology choices with documented rationale. By the time you have a BMAD architecture document, you've had the kind of conversation with an AI that you'd normally have in a good design review with a senior engineer.
For a simple CRUD service or a well-understood feature, spec-kit's approach is fine — you probably know what you're building. But for platform engineering work, where the spec itself is often the hard part, BMAD's upstream dialogue is what you need. You're not just translating a known requirement into a structured format. You're figuring out what the requirement actually is.
There are two other practical differences:
Platform-aware agents. spec-kit is language and domain agnostic. BMAD has Sam — a Platform Engineer agent who understands Kubernetes, GitOps, ArgoCD, Crossplane, and IaC patterns. When you hand Sam an architecture document that says "use Crossplane Compositions," you get correct Crossplane YAML back, not generic infrastructure pseudocode.
Spec compliance checking. spec-kit doesn't have a built-in review step. BMAD has Quinn, who reads the generated code against the spec and flags deviations before merge. That closes the loop between what you decided and what got built.
spec-kit is a great starting point if your team is just getting into spec-driven development and wants to establish the habit. BMAD is what you reach for when the spec is genuinely hard to write — which, for platform teams building shared infrastructure, is most of the time.
Why platform engineering teams need the upstream phase more than anyone¶
Platform engineers are building for other engineers. That changes the stakes considerably.
When you build a namespace provisioner, you're not just building one thing — you're building the pattern that every team in the organisation will follow when they need namespaces. When you pick Crossplane over Helm for self-service infra, that decision gets copied into six other platform features over the next year. When your RBAC model has a gap, it's a gap in every workload that follows the same template.
The blast radius of a bad architecture decision on a platform team is enormous. It's not one service, it's the standard. That's what makes the upstream thinking phase disproportionately valuable for IDP work, in a way it just isn't for a greenfield microservice where iterating fast is fine.
Most platform work I see goes wrong in one of two ways:
- Too much yak shaving in the details — three days into building the self-service namespace provisioner, the team is debating admission controller vs. Crossplane Composition, having never written down what the user of this provisioner actually needs.
- Too much ambiguity about "done" — the feature ships, users complain it's missing something obvious, and nobody has a written definition to refer back to.
BMAD's upstream phase forces you to answer these before touching code. You sit with Preston (PM agent) and Mary (BA) to define the problem, then hand Winston (Architect) a PRD and get back an architecture document that makes explicit calls: "We'll use Crossplane Compositions, not Helm. Here's why." That decision lives in a file. Devon (Developer) reads it. There's no ambiguity.
The temptation to skip straight to Sam
Sam (the Platform Engineer agent) is the one who generates your Kubernetes manifests, Terraform modules, and ArgoCD Application definitions. It's tempting to start there. Don't. Sam's output quality is directly proportional to the quality of the architecture document he's been given. Feed Sam a vague spec, get mediocre YAML. Feed him Winston's architecture document, get production-grade infrastructure code.
How to set up BMAD for a platform project¶
BMAD v6.8.0 installs in a single command:
This drops a .bmad/ directory into your project root with the agent persona files, templates for PRDs/architecture docs/user stories, and a project context file that every agent loads on startup.
For a platform engineering project, choose your IDE integration (Claude Code, Cursor, Copilot, or Gemini CLI), then select the agents you actually need. For most IDP work, you want at minimum: Preston, Winston, Sam, and Quinn. Sally is useful when you're building user-facing developer portal features. Mary and the others are optional unless you need formal business analysis.
Here's the directory structure you'll end up with:
your-platform-repo/
├── .bmad/
│ ├── agents/ # Agent persona files (Preston, Winston, Sam, Quinn)
│ ├── templates/ # PRD, architecture doc, user story templates
│ └── context/ # Project-level context BMAD agents always load
├── docs/
│ ├── prd.md # Product requirements — output of Preston session
│ ├── architecture.md # Architecture decisions — output of Winston session
│ └── stories/ # User stories — output of Sally session
├── gitops/
│ ├── apps/ # ArgoCD Applications
│ └── clusters/ # Cluster-level config
└── gitops/
├── apps/ # ArgoCD Applications / ApplicationSets
└── secrets/ # ExternalSecret manifests
The key thing: docs/prd.md and docs/architecture.md are committed to your repo. They're not throwaway scratchpad content. They're the source of truth that every downstream agent (and every human engineer) reads before making decisions.
This is just GitOps for your specs
If you squint, BMAD's approach to upstream documents is the same principle as GitOps: make the desired state explicit and version-controlled before reconciling it into reality. The only difference is the "reality" being reconciled is your codebase, not your cluster. The workflow is the same: think → write → commit → build.
Running the upstream phase: from idea to architecture in one session¶
Let's use a real example. tenable-exporter is a Prometheus exporter for Tenable.io — it pulls vulnerability, asset, and compliance metrics and surfaces them in Grafana so you can alert on critical CVEs without logging into the Tenable UI. It already exists, it's published to PyPI and GHCR, and it has a Helm chart. The question the platform team needs to answer isn't "how do we build this" — it's "how do we deploy this across our clusters properly."
And "properly" turns out to have a lot of hidden surface area. Credentials in the Helm values or in a Kubernetes Secret? Which clusters? Same scrape interval everywhere or differentiated by environment? Do we own the chart or consume the upstream OCI chart? What happens when Tenable's API rate limits us in prod?
These are exactly the questions you want answered before anyone writes a single YAML file. You kick off with Preston:
@Preston We need to deploy the tenable-exporter to our Kubernetes clusters via GitOps.
It's a Prometheus exporter for Tenable.io vulnerability data — published at
ghcr.io/polarpoint-io/tenable-exporter with an OCI Helm chart.
The security team needs vuln metrics in Grafana so they can alert on critical CVEs.
Please help me write a PRD for the deployment.
Preston doesn't just start writing. It asks: Which clusters does this need to run on, and are they all equivalent? Who owns the Tenable.io API credentials and how are they currently managed? What's the failure mode if the Tenable API is unavailable — should the exporter return stale data or no data? Are there compliance requirements about where credentials can be stored? What does "success" look like — a Grafana dashboard, a PagerDuty alert, something else?
These feel like obvious questions. Most teams skip them and discover the gaps during a 2am incident when the exporter can't find its credentials after a cluster rebuild.
The PRD that comes out of the session:
# Tenable Exporter Deployment — PRD v1.0
## Problem
The security team has Tenable.io providing continuous vulnerability scanning across
our AWS and Azure estate, but there's no way to alert on critical CVEs or track
remediation velocity in our existing Grafana/Prometheus stack.
Platform engineers are fielding ad-hoc requests to query Tenable directly, adding
noise to their on-call rotation.
## Users
Primary: Security platform team (Grafana dashboards, alerting)
Secondary: SRE teams (per-subscription vuln counts in their service dashboards)
## Success metrics
- Tenable metrics available in Prometheus within 10 minutes of exporter deploy
- Critical vuln alerts firing within one scrape interval of a new finding
- Zero Tenable credentials stored in Git or Helm values
## Out of scope (v1)
- Per-developer vulnerability views (security team owns the data model)
- Tenable.sc (on-prem) — Tenable.io only for now
- Automatic remediation triggering
## Constraints
- GitOps-native: all changes via PR, no kubectl apply by hand
- Tenable API keys must be sourced from Vault, not stored in the cluster
- Must deploy to: prod-aws-eu-west-1, prod-azure-uksouth, dev-aws-eu-west-1
- Tenable API has rate limits — scrape interval must not cause 429s in prod
That document goes into docs/prd.md and gets committed. Then Winston:
@Winston Here is the PRD for the tenable-exporter deployment: [reference docs/prd.md]
Please produce an architecture document covering:
- How we consume the upstream OCI Helm chart vs forking/vendoring it
- Secret management approach for Tenable API credentials (Vault → ExternalSecrets vs Sealed Secrets vs manual)
- Scrape interval strategy for prod vs dev (Tenable API rate limit context)
- Multi-cluster deployment pattern (single Application vs ApplicationSet)
- How the exporter lands in the monitoring namespace alongside existing stack
Winston makes the choices explicit. "We'll use the upstream OCI chart unmodified and reference it by version tag — forking creates a maintenance burden we don't want. Credentials will flow Vault → ExternalSecrets Operator → Kubernetes Secret, because we already run ESO and this keeps the secret lifecycle outside of ArgoCD. Scrape interval: 300s in prod (Tenable's API is rate-limited; 60s would cause 429s with our asset count), 60s in dev for faster feedback. ArgoCD ApplicationSet with a list generator — one entry per cluster — so adding a new cluster is a one-line PR."
Every one of those calls is now in a file. Not in someone's head. Not in a chat window that closed last Tuesday.
The PM agent will push back on scope — let it
Preston's job is to narrow, not expand. If you bring ten ideas, it'll ask you to pick three. That's the discipline. The upstream phase is slower than typing YAML — and that's the point. Slow down now, go faster later.
Handing off to Sam: GitOps-native implementation¶
Once you have PRD + architecture doc, Sam comes in:
@Sam Here is the architecture document for the tenable-exporter deployment:
[reference docs/architecture.md]
Please generate:
1. An ArgoCD ApplicationSet deploying tenable-exporter to all three clusters
2. An ExternalSecret manifest that pulls Tenable credentials from Vault
3. A monitoring namespace manifest with the correct labels
Use the OCI chart at ghcr.io/polarpoint-io/charts/tenable-exporter.
Follow docs/architecture.md for scrape intervals and secret references.
Here's what Sam generates for the ApplicationSet — and notice how every value traces back to a decision in the architecture doc or a constraint in the PRD:
# gitops/apps/tenable-exporter-appset.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: tenable-exporter
namespace: argocd
spec:
generators:
- list:
elements:
# Maps to PRD: "Must deploy to: prod-aws-eu-west-1, prod-azure-uksouth, dev-aws-eu-west-1"
- cluster: prod-aws-eu-west-1
env: prod
scrapeInterval: "300" # arch doc: 300s prod — Tenable API rate limit
filterProviders: "aws,azure"
- cluster: prod-azure-uksouth
env: prod
scrapeInterval: "300"
filterProviders: "azure"
- cluster: dev-aws-eu-west-1
env: dev
scrapeInterval: "60" # arch doc: 60s dev — faster feedback, no rate limit risk
filterProviders: "aws"
template:
metadata:
name: 'tenable-exporter-{{cluster}}'
spec:
project: platform
source:
repoURL: ghcr.io/polarpoint-io/charts
targetRevision: 1.1.3 # arch doc: pin to version, do not use latest
chart: tenable-exporter
helm:
values: |
tenable:
existingSecret: tenable-credentials # arch doc: credentials via ESO, not inline
scrapeInterval: {{scrapeInterval}}
filterProviders: {{filterProviders}}
resources:
requests:
memory: 64Mi
cpu: 50m
limits:
memory: 128Mi
destination:
server: 'https://{{cluster}}.k8s.internal:6443'
namespace: monitoring
syncPolicy:
automated:
prune: true
selfHeal: true
And the ExternalSecret that feeds credentials into that existingSecret:
# gitops/secrets/tenable-externalsecret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: tenable-credentials
namespace: monitoring
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: ClusterSecretStore
target:
name: tenable-credentials # matches tenable.existingSecret in the ApplicationSet
creationPolicy: Owner
data:
- secretKey: access-key
remoteRef:
key: platform/tenable
property: access_key
- secretKey: secret-key
remoteRef:
key: platform/tenable
property: secret_key
Every value in that ApplicationSet traces back to a written decision. The scrapeInterval: 300 in prod comes from Winston's architecture doc note about Tenable API rate limits. The existingSecret pattern exists because the PRD constraint said "zero Tenable credentials stored in Git." The targetRevision: 1.1.3 pin comes from the architecture call to use the upstream chart without forking. You're not reviewing YAML and inventing questions. You're checking generated code against a written spec.
Connecting BMAD output to your GitOps pipeline¶
Sam's output goes straight into gitops/apps/ and gitops/secrets/ — the same directories ArgoCD is already watching. Your pipeline doesn't change at all. ArgoCD doesn't know or care that the ApplicationSet was generated by Sam. It sees YAML in a Git directory, reconciles it to the clusters, and the tenable-exporter lands in the monitoring namespace on all three clusters.
What's different is the audit trail. Six months from now, a new engineer looks at the ApplicationSet and wonders: why 300s scrape interval in prod? Why ExternalSecrets and not Sealed Secrets? Why pin to 1.1.3 instead of latest? Every one of those questions has an answer in docs/architecture.md. The context doesn't live in someone's head or in a Slack thread from last February.
Before the manifests merge, Quinn reviews them against the spec:
@Quinn Please review the manifests in gitops/ against docs/architecture.md and docs/prd.md.
Check specifically:
- scrapeInterval values match the prod/dev split defined in architecture.md section 3
- existingSecret reference matches the ExternalSecret target name exactly
- No Tenable credentials appear inline in any manifest (PRD constraint: zero creds in Git)
- OCI chart targetRevision matches the pinned version in architecture.md section 2
Flag any deviations as issues. Do not suggest changes not covered by the spec.
That last instruction matters. Quinn's job is to check against the spec, not to freelance improvements. If Quinn finds something that should change, you update the PRD or architecture doc first — then regenerate. The spec is the source of truth, not the generated code.
Cross-link to your agents.md or CLAUDE.md
If you're using Claude Code for the downstream implementation, connect your BMAD architecture document to your AGENTS.md or CLAUDE.md pattern. The architecture doc is exactly the kind of persistent context that belongs in CLAUDE.md — so Devon and any human engineer working in the repo share the same mental model.
What you get¶
- A written PRD and architecture document before any YAML is generated — reviewable, diffable, committable to Git
- Sam's GitOps-native output (ArgoCD ApplicationSet, ExternalSecret, namespace manifest) where every value traces back to an explicit architecture decision
- Zero credentials in Git — the PRD constraint propagates through the architecture doc into Sam's ExternalSecret pattern automatically
- Quinn reviewing manifests against the spec before merge — scrape interval, secret references, chart version all checked
- A workflow that scales: new team members read
docs/to understand why the deployment looks the way it does, not just what it does - 90% less token waste in implementation sessions (v6 benchmark) because agents always have the right context loaded
Do I need to use all the BMAD agents?
No. For a focused platform project you can start with just three: Preston (PM) for the PRD, Winston (Architect) for the architecture doc, and Sam (Platform Engineer) for implementation. Add Quinn (QA) when you want spec-compliance reviews on generated code. Sally (PO) and Mary (BA) are more useful when you're building end-user-facing features than internal platform tooling.
Can I use BMAD with Claude Code specifically?
Yes — and it works well. BMAD's file-based context approach maps directly to CLAUDE.md. You put your architecture document reference in CLAUDE.md, and every Claude Code session starts with that context loaded. See the AGENTS.md pattern for Kubernetes repos for a template you can adapt.
Is the BMAD agent output production-ready or a starting point?
Starting point, always. Sam generates correct-structure manifests grounded in your architecture decisions, but you'll still review and adjust. The value isn't that Sam writes perfect YAML — it's that Sam writes consistent YAML that's traceable to a decision. Review time drops sharply because you're checking against a spec, not inventing one during review.
How does BMAD handle changes mid-project?
This is where the upstream investment pays off most. When requirements change, you update the PRD with Preston, run the changed sections past Winston for architecture impact, then prompt Sam with the diff. You're not re-deriving decisions from conversation history — you're updating a document and propagating the change. Same workflow as updating a GitOps config and letting ArgoCD reconcile.
What about teams that have existing GitOps repos — do I bolt BMAD on?
Yes. The docs/ directory with PRD and architecture docs can be added to any existing repo. You don't need to restructure anything. Start by having Winston document the current architecture of your platform — that document alone is useful context for every future implementation session, BMAD or otherwise.
For the AGENTS.md / CLAUDE.md pattern that connects BMAD's architecture docs to your Kubernetes repos, see agents.md for platform repos. For GitOps-native policy enforcement that pairs well with self-service provisioners, see Kubernetes policy enforcement.