Cloud / FinOps
A FinOps agent for AWS cost optimization
An agent that finds the savings hiding in an AWS account: six read-only tools, no arithmetic delegated to the model, no ability to mutate anything.
- Role
- Design and development — personal project, public code
- Period
- July — August 2026
- Tools, all read-only
- 6
- IAM actions required
- 4
- Cost arithmetic left to the LLM
- 0
- Python
- Strands Agents SDK
- Amazon Bedrock
- boto3
- AWS CDK
- pytest
Context
The costs of an AWS account drift naturally: instances sized generously at launch and never revisited, detached EBS volumes nobody remembers to delete, Elastic IPs allocated and never associated — billed all the same, since February 2024, at a flat rate per address. Detecting this waste is not hard, it is tedious: it means cross-referencing Compute Optimizer recommendations, the EC2 inventory, and the pricing API, then putting a figure on every case. Exactly the kind of work that slips from sprint to sprint.
That makes it good terrain for an LLM agent — crossing sources, reasoning, prioritizing, summarizing. It is also terrain where a badly designed agent is dangerous. This project, personal and with public code, serves both purposes: produce a cost diagnosis you can act on, and answer seriously the question of how you put an LLM agent in contact with infrastructure without inheriting its risks.
Constraint
The constraint is twofold, and each half shaped part of the design.
First, safety: a language model is sometimes wrong with great confidence. Giving write access on an AWS account to a non-deterministic system is not defensible. Safety could not rest on the quality of a prompt — it had to rest on what the agent is materially capable of doing.
Second, accuracy: a FinOps tool is only worth what its numbers are worth. An LLM produces plausible figures, not exact ones — and a saving announced wrongly costs more in credibility than it earns. The model therefore had to be prevented from ever computing anything.
Decisions
The first decision structures everything else: the agent is read-only by construction. Six tools are exposed to it — rightsizing recommendations via Compute Optimizer, detection of unattached EBS volumes and unassociated Elastic IPs, EC2 and EBS pricing via the Price List API, the cost of public IPv4 addresses, and a savings calculator — and none of them mutates anything. The IAM policy fits in four actions, all reads. The nuance matters: a denied permission can be bypassed by a configuration mistake; an absent capability cannot be invoked. The cost is accepted: the agent does not “fix” anything itself — remediation remains a human act, outside the system.
Second decision: no arithmetic is left to the model. The pricing tools return exact figures from the AWS API; a dedicated tool, in pure code, does the subtractions and the totals; the prompt explicitly forbids the model from calculating and requires it to label as “unpriced” anything it cannot put a figure on with the tools, rather than estimating from memory. The agent does not even trust Compute Optimizer’s precomputed savings: for every recommendation, it re-prices both the current instance type and the proposed one, and derives the exact difference from live pricing. Finally, the numbers in the report — savings table, chart, resource map — are re-derived in code, independently of the model’s prose. The model narrates; the code counts.
Third decision: the system can be developed without AWS and without an
LLM. A mock mode serves data in the exact shape of real AWS responses,
with mock/real parity enforced in the same place in every function. A
--tools-only mode runs the whole pipeline — collection, pricing, report —
without a single model call: that is what makes CI and demos possible. The
logic lives in ordinary Python functions and the tool decorators are
one-line wrappers, so the core of the system is tested like normal code,
without mocking an LLM. The price: mocks to maintain as the APIs evolve. It
is small next to the alternative — developing blind against real, billed
resources.
Last decision, the least obvious one: testing against real AWS requires creating real waste, and that cost had to be bounded. A disposable CDK stack provisions exactly the minimal scenery the tools know how to detect — an idle instance, a volume never attached, an IP never associated — with a budget alert and a one-command teardown. As for the foundation: Strands Agents on Amazon Bedrock by default, which keeps billing data inside the account’s AWS boundary; the model provider is an environment variable, not an architectural decision — the direct Anthropic API substitutes for Bedrock without touching the tools’ code.
Outcome
The agent runs in three modes — mock, tools-only, and full agent against a real account — and produces a Markdown report: a savings table per action, a chart, and a resource map colored by state. The report’s totals are reproducible to the cent without a model, which also makes them a check on the agent’s prose.
The code is public — the repository stands as proof for every claim on this page. What the project demonstrates: an LLM agent can produce a cost diagnosis worthy of trust, provided the architecture takes away from the model what it does badly — arithmetic, mutation — and leaves it what it does well — orchestrating tools, crossing data, and prioritized synthesis.