Detect your own patterns
Run a check leancosts does not ship as a detector (your rule, your agent, your timing) and file what it finds as a change request that your team approves and the savings ledger measures.
Three tools do it, in one conversation with your MCP client:
| Step | Tool | What it does |
|---|---|---|
| 1 | search_resources | selects the estate (cloud, type, tag, cost band) |
| 2 | list_resource_metrics | reads the signal for up to 500 of them at once |
| 3 | create_change_request | files the finding, with the pattern attached |
Before you start
Section titled “Before you start”- An MCP client connected to leancosts: Connect Claude to leancosts.
- The
change_request.createcapability on the token or session you connect with. Without it, step 3 is refused before it validates anything. - At least one sync finished, so your bill and your metric windows exist.
1. Paste the prompt
Section titled “1. Paste the prompt”The Copilot page carries this prompt under Detect your own patterns, ready to copy. Edit the filter and the threshold to your own check:
Find Azure disks tagged env=prod that have been unattached for more than 30days. Use search_resources, then list_resource_metrics for the ones you select,then create_change_request with op delete for each and the detectionPatternfilled in. Do not estimate the saving yourself.The last line matters, and step 3 says why.
2. Let the agent select and measure
Section titled “2. Let the agent select and measure”search_resources takes the filter (providers, resourceTypes,
resourceGroups, accountIds, tagKey + tagValue, tagMissingKey,
minMonthlyCost / maxMonthlyCost) and returns each hit with the monthly cost
your bill attributed to it.
list_resource_metrics then reads the persisted utilization windows for up to
500 resources in one call, so checking one signal across an estate costs one
call rather than one per resource. Ids match case-insensitively.
freshestIngestedAt tells you how recent the newest row in the answer is. A
stale stamp is the reason to distrust everything above it.
3. File the finding
Section titled “3. File the finding”create_change_request takes the title, the why, the scope, the changes
(one row per resource, op = create · update · delete), optional links,
and submitImmediately. When the change acts on a finding leancosts already
holds, pass its id from list_opportunities as opportunityId: the saving is
then booked once, never beside your team’s own “applied” answer. Naming a
finding does not change its status in the register. The finding must be in
your organization and name a resource the change request covers.
Do not send an estimate. There is no field for one on a row, and the
top-level estimatedMonthlyImpactUsd exists only so that passing it is
refused rather than silently ignored. leancosts derives the number itself:
- Each
deleterow is priced from that resource’s last closed month on your bill (the same figuresearch_resourcesshowed your agent) and appends one auditable line towhy:Estimate: <resourceId>: -$<amount> last closed month, measured. - A resource your bill never attributed a cost to comes back under
unpricedand contributes nothing to the total. A missing bill line is not a measured zero. updateandcreaterows are never priced. A resize estimate would need a price-book target, and an invented one is a claim no bill can back.- When nothing could be priced, the estimate is empty, not
$0.
Attach the pattern
Section titled “Attach the pattern”detectionPattern records what you compared:
{ "filter": { "providers": ["azure"], "resourceTypes": ["microsoft.compute/virtualmachines"], "tagKey": "env", "tagValue": "prod" }, "signals": [ { "metric": "Percentage CPU", "aggregation": "p95", "windowDays": 30, "comparator": "below", "threshold": 3 } ], "action": "stop"}Use the metric names your own answer from step 2 carried; Percentage CPU is
the Azure VM one.
Every signals[].metric must be a name your organization’s ingestion actually
writes. Name one it does not and the call is refused, listing the metrics the
resources in this change request do carry, so run step 2 first. signals: []
is fine when you detected on inventory alone (an unattached disk older than 30
days has no metric to name).
Verify
Section titled “Verify”- The tool answers with the change request, its derived
estimatedMonthlyImpactUsdand theunpricedlist, plus: “Filed. The change request needs a human approval; leancosts does not apply it.” - Open Savings register → Change requests. The new row carries the pill Your agent.
- Open it: the rationale shows one
Estimate:line per priced resource, and the detection pattern block under the scope shows your filter as chips, one line per signal, and the action. - Approve and execute it the way you would any other change request: Act on a cost finding. Your team runs the change with its own credentials; leancosts never touches your cloud.
- After the next bill lands, the Impact tab of the same hub carries the measured delta, the only number that counts as saved.
What this is not
Section titled “What this is not”- Not a rules engine. leancosts stores no rule, schedules no check and runs no code of yours. Your agent runs when you run it.
- Not an approval bypass. An agent-filed change request needs the same human approval as any other, and the agent cannot approve its own.
- Not a write path. No tool on this endpoint changes anything in your cloud.
Every tool your client can call is listed in Use leancosts with an agent.