← Back to Index
↳ Project /36AWS · AI · Platform

Golden-Path FinOps Copilot (AWS + Bedrock)

A self-service provisioning copilot where a plain-language request becomes a right-sized, budget-checked, policy-gated pull request, and idle spend becomes a reviewed cleanup PR. The language model translates intent onto vetted modules; every consequential decision stays in code, and the output is a diff a human reviews, never a direct apply.

Role
Platform Eng / FinOps
Cloud
AWS
Model
Claude on Bedrock
Gate
OPA / Rego
Developer
plain-language request
Claude on Bedrock
drives tool loop · IAM/SigV4
right_size
cheapest that fits
estimate_cost
region-aware · Infracost
check_budget
team envelope
OPA / Rego
deny tags · GPU · budget · host posture
Pull Request
tfvars · cost · rationale
Human merge
then Terraform applies
Plain-language request to a reviewed pull request: the model only proposes, deterministic tools and an OPA gate decide, and nothing reaches Terraform until a human merges

/01Problem

Self-service infrastructure has two failure modes. A Backstage-style form makes the developer already know which module and which instance family they need before they can fill it out. An LLM that freeform-generates and applies Terraform is a gimmick no platform team would ship, because the moment a model invents HCL and runs it, nothing is reviewable and nothing is bounded.

The goal was the version that is actually defensible: let a model turn fuzzy human intent into a selection against vetted modules, keep every real decision deterministic and in code, and make the output a pull request a human reviews rather than a live change.

/02Approach

  • The model is a translation and advisory layer only. Claude on Bedrock calls a fixed set of deterministic tools (list_golden_paths, right_size, estimate_cost, check_budget, submit_for_review); it never authors Terraform or invents an instance type or a price.
  • A right-sizing engine picks the cheapest option that still fits the stated workload: Graviton over x86, burstable for bursty non-latency-critical workloads, Fargate Spot for non-prod stateless services, nightly auto-stop for non-prod, gp3 and KMS encryption always.
  • A fourth golden path provisions a hardened EC2 host: a CIS-hardened AMI baked by an in-repo EC2 Image Builder pipeline, IMDSv2 required, no public IP, SSM Session Manager access instead of SSH, an encrypted gp3 root, and all egress routed through the shared Palo Alto VM-Series firewall for inspection. The firewall is referenced, not provisioned, so the host stays in budget.
  • A cost tool prices the plan from Infracost when the binary is present and a static price table otherwise, so an estimate is produced with no network call and no credentials. Pricing is region-aware through a per-region multiplier, so the same host reads about 10% higher in eu-central-1 than in us-east-1. A budget gate checks that estimate against the team's monthly envelope and returns ok, warn, or over.
  • An OPA/Rego policy denies missing tags, unencrypted storage, un-approved GPUs, over-budget requests, un-hardened production databases, and any compute host that would launch with a public IP, without IMDSv2, without firewall-inspected egress, or from a non-hardened AMI. Over-budget and GPU requests are flagged, not silently approved, and clear only with an explicit approval label.
  • The output is a pull request carrying the rendered tfvars, the cost delta, the right-sizing rationale, and the policy result. It is never a direct apply; a human merges, then Terraform runs.

/03Why it holds up

The obvious challenge is why an LLM instead of a form. The answer is that the form is still there underneath, as the module catalog and the tool schemas; the model just removes the requirement that the developer already knows the answer. The determinism lives in the modules and the policy, and the model's output is always reviewable as a diff before anything is created. That is the line between a demo toy and something you would run in production.

The policy is written to avoid the usual trap where a Rego suite passes because no rule ever fires. Every deny rule has a fixture that breaks exactly one thing, plus a base-passes case that proves the rules do not fire spuriously, so the gate is verified to actually gate.

/04Bedrock, without a key

The model call goes through the Messages-API Bedrock client and authenticates with IAM and SigV4, so there is no Anthropic API key to store, rotate, or leak. For a tool whose entire thesis is FinOps and guardrails, the integration uses a role, not a secret, which is the same posture it enforces on everything it provisions.

Model access was enabled entirely from the CLI through the Bedrock model-agreement API (use-case form and EULA acceptance), not the console, so the whole enablement path is scriptable and auditable.

/05Testing

The deterministic pipeline runs and is verifiable with no AWS credentials at all. Unit tests cover the right-sizing engine and the budget gate, the Rego suite proves every deny rule fires, and an offline scenario sweep exercises the burstable, production-hardened, spot, storage, and over-budget paths end to end, each producing a rendered pull request.

The headline request, a Postgres for staging at about 50GB with bursty daytime traffic and no latency sensitivity, resolves to a t4g.micro burstable Graviton instance on gp3 with a nightly auto-stop schedule at about $7.53 a month, and an over-budget production request is blocked by the policy gate until an approval label is attached.

Run live against Bedrock, the same request is driven by the model itself: it calls list_golden_paths, right_size, estimate_cost, check_budget, and submit_for_review in that order, lands on the same t4g.micro plan, and opens the pull request. The tools stay deterministic, so the live path and the offline sweep produce the same artifact.

To close the loop, one rendered request was applied against real AWS through a throwaway harness that supplies only the networking the module needs. The db.t4g.micro Postgres reached available as the copilot specified it, encrypted, single-AZ, not publicly accessible, with its master password in Secrets Manager, and terraform destroy tore all six resources down clean. The vetted module was unchanged; the harness proves the rendered output is real infrastructure, not just a plausible diff.

The hardened-compute path was proven the same way. A rendered EC2 request was applied against real AWS, and the running host was verified through the EC2 API to match the posture the copilot promised: a t4g.micro Graviton instance with IMDSv2 required, no public IP, an encrypted gp3 root, every golden-path tag, and a private-subnet default route pointing at the shared firewall's interface. The Image Builder pipeline stood up for real alongside it, and terraform destroy removed all twenty-three resources clean, with a post-destroy sweep confirming nothing lingered.

/06Closing the loop: waste reclamation

Provisioning is the inform-and-prevent half. The other half is acting on spend that already exists. The Cost Intelligence dashboard detects idle spend (unattached EBS, gp2 volumes, stray Elastic IPs); this copilot acts on it through the same determinism boundary, via two new tools, list_waste_findings and remediate_waste, or a make reclaim run offline. Findings come from a local fixture or, pointed at the dashboard's /waste endpoint, straight from the live cloud.

The output is a cleanup pull request with a reviewable remediation script, never an apply, held behind two deterministic gates. Unattributed waste (no CostCenter tag) is listed but held, so a human decides, the same tagging discipline the guardrails enforce at provision time, applied at the point of action. Destructive actions (delete a volume, release an address) need an approval label; the safe, reversible action (gp2 to gp3) ships immediately.

Run live through Bedrock, the model surfaced what was reclaimable now versus held and why, opened the cleanup PR, and correctly refused to set the approval label itself. That connects two repos into one FinOps lifecycle: the dashboard says what is being wasted, and the copilot opens the reviewed PR that reclaims it.

↳ Run Receipt/36
Right-sizeBursty non-latency staging Postgres resolved to a t4g.micro burstable Graviton on gp3 with nightly auto-stop, ~$7.53/mo
Policy13 Rego tests: every deny rule fires against a fixture, a base-passes case rules out a vacuous gate
BudgetOver-budget production request BLOCKED; clears only with an explicit approval label
BedrockLive run on Claude Sonnet over Bedrock: the model drove the loop list_golden_paths → right_size → estimate_cost → check_budget → submit_for_review, authenticated over IAM/SigV4 with no API key
Deploy (RDS)One rendered request applied for real: db.t4g.micro Postgres 18.3, 50GB gp3, encrypted, private, Secrets Manager password; terraform destroy tore down all 6 resources clean
Deploy (compute)Hardened EC2 request applied for real: t4g.micro verified via the EC2 API with IMDSv2 required, no public IP, encrypted gp3 root, and a private-subnet egress route to the shared firewall; Image Builder pipeline live alongside; all 23 resources destroyed clean
ReclaimWaste findings turned into a cleanup PR: untagged waste and destructive deletes held for approval, safe gp2→gp3 ships; validated offline and driven live by the model over Bedrock
OutputA reviewed pull request, never a direct apply
Claude on BedrockOPA / RegoEC2 Image BuilderInfracostTerraformPythonFastAPIGitHub PRs
StatusCheckingDeployed2026-09-20 13:33 UTCVisitsOriginPrivate S3 + CloudFront OACPipelineGitHub Actions OIDCCounterAPI Gateway + Lambda + DynamoDB