Tools
The server registers 31 tools, 7 of which write. This page is generated from mcp-manifest.json, the surface the running server advertises, so the names, parameters, enums and defaults below are the ones it registers. The text under each heading is what a model reads verbatim when it picks between them.
Conventions
Of the 31, 24 are annotated readOnlyHint true, destructiveHint false, idempotentHint true, openWorldHint false: they read, and the same arguments return the same answer. The other 7 write, marked below, and carry readOnlyHint false so your client asks you before calling one. None of them touches a cloud resource itself: they record a decision, settle how a change is delivered, or put it in the rollout queue, and LevelFour's own executor applies it afterwards.
No tool takes a tenant, an organization or an account argument. The organization comes from the credential, because it is a separate Postgres database rather than a filter on a shared one. See Connecting a client.
provider is a plain string, not an enum. Which providers exist is a fact about your organization, so the server validates the value at call time and names the valid ones in the error. Read levelfour://providers or call get-identity first.
A default of none means the parameter is optional and omitted, and the description says what the server does without it. Dates are YYYY-MM-DD. Every page_size and limit caps at 50, and a list tool returns has_next_page and next_page already computed.
Results come back as text rather than a structured content block. Reading a result has the shapes, the pagination envelope every list shares, and what truncation and errors look like.
| Tool | Mode | Purpose |
|---|---|---|
connect-version-control | write | Start connecting the organization's GitHub, which the IaC format needs. |
create-savings-grant | write | Mint the scoped AWS access grant that Automated Savings runs through. |
decide-recommendation | write | Record the user's decision to accept or reject one savings recommendation. |
get-commitment-overview | read | Reserved Instance and Savings Plan position, in aggregate. |
get-cost-breakdown | read | Break spend down into its largest components over a period. |
get-cost-forecast | read | Projected spend for the end of the current month. |
get-cost-growth | read | Which services grew the most, and by how much. |
get-cost-series | read | Daily spend over a date range, as a time series. |
get-cost-summary | read | Current cloud spend and where it is heading, or one month's total. |
get-costs-by-tag | read | Spend grouped by the value of a cost-allocation tag, for showback and chargeback. |
get-execution-logs | read | What one step of a rollout ran, and what it printed. |
get-identity | read | Identify the connected LevelFour organization and what it has access to. |
get-implementation-status | read | Where one savings has got to: decided, waiting on an approver, or rolling out. |
get-manual-instructions | read | The step-by-step guide for applying one savings by hand. |
get-potential-savings | read | Total unbooked opportunity across all recommendations, with per-status counts. |
get-realized-savings | read | Savings already realized and booked, with who approved them. |
get-recommendation | read | The full case for one savings recommendation. |
get-savings-grant | read | The state of the Automated Savings access grant on one recommendation. |
get-savings-overview | read | How the savings backlog splits across its statuses, in count and in money. |
get-savings-readiness | read | What still has to happen before a savings can be delivered each way. |
get-usage-costs | read | Billable quantity and cost per unit, grouped by usage type, and what a usage type is. |
list-accounts | read | The cloud accounts connected to this organization. |
list-anomalies | read | Detected cost anomalies, meaning unexpected spikes. |
list-approval-requests | read | Rollouts waiting on an admin to release them, oldest first. |
list-commitments | read | The individual Reserved Instances and Savings Plans, with their end dates. |
list-recommendations | read | Savings opportunities LevelFour has found, largest first. |
list-repositories | read | The organizations and repositories a savings can open its pull request against. |
release-rollout | write | Release a rollout a colleague asked for, as the admin answering them. |
set-implementation-method | write | Record how an accepted savings should be delivered, and for a pull request, where it lands. |
start-rollout | write | Put an accepted savings into the rollout queue. |
update-anomaly-status | write | Record what the user decided about one detected cost anomaly. |
connect-version-control
read-write key, and your client asks before calling it.Purpose: Start connecting the organization's GitHub, which the IaC format needs.
Returns: the GitHub App install link. An organization owner opens it, chooses which repositories LevelFour may see, and GitHub then returns them to a LevelFour page that finishes the connection. Both halves are theirs to do: LevelFour cannot approve an app on their behalf.
When to use: When get-savings-readiness reports no version control connection.
NOT for: Choosing a repository for one savings, which is set-implementation-method once this is done. Not for GitLab either: a GitLab connection cannot carry the IaC format, because binding a repository to a recommendation keys on a GitHub installation.
Parameters
Takes no arguments.
create-savings-grant
read-write key, and your client asks before calling it.Purpose: Mint the scoped AWS access grant that Automated Savings runs through.
Returns: the new grant and the page where the customer authorizes it. Creating it changes nothing in their account: it writes a scoped policy and waits. The access exists only once they launch the CloudFormation stack themselves, which is how AWS delegates a role and is not something LevelFour can do on their behalf.
When to use: When the user wants an Automated savings to be able to run and no grant exists yet. This mints it and returns where they authorize it.
NOT for: Checking on one, use get-savings-grant. Asking what a savings still needs, use get-savings-readiness. Making the change, which runs after the grant connects. Not for minting a second grant either: a live one already covers the recommendation, and two launched stacks add permissions to the role rather than replacing them, so that is refused here.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
recommendation_id | string | required | Recommendation id from list-recommendations, for example REC-1234. |
decide-recommendation
read-write key, and your client asks before calling it.Purpose: Record the user's decision to accept or reject one savings recommendation.
Returns: the recommendation's new status and the decision as it was recorded.
When to use: When the user has named a recommendation and said to accept or reject it. This books that decision, so it is the tool for "accept REC-1234" or "reject REC-5678".
NOT for: Making the change. Accepting books a decision and stamps the approver; it does not resize, delete or modify anything. To settle how it gets delivered use set-implementation-method, and to put it in the rollout queue start-rollout. Not for reversing a decision, which only the dashboard can do. Not for a recommendation waiting on approval for a rollout a teammate requested either: answering them is release-rollout, and accepting here is refused. If the user has not seen the figures they are deciding on, get-recommendation puts the monthly saving and the operational impact in front of them first.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
decision | accepted, rejected | required | 'accepted' books the recommendation as a decision to make the change. 'rejected' closes it. Neither touches a cloud resource. |
explanation | string | none | Free text backing the rejection reason, used when reason is 'other'. |
reason | operational, strategy, not_applicable, other | none | Why it was rejected. Only meaningful with decision='rejected', and optional even then: the user can add it later in the dashboard. Use 'other' with explanation when none of the fixed reasons fit. |
recommendation_id | string | required | Recommendation id from list-recommendations, for example REC-1234. |
get-commitment-overview
Purpose: Reserved Instance and Savings Plan position, in aggregate.
Returns: coverage, utilization and the per-service split, plus how many commitments expire soon.
When to use: "How well are we covered." For the individual commitments and their expiry dates, follow with list-commitments.
NOT for: On-demand spend, use get-cost-breakdown.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
provider | string | none | Cloud provider id, for example aws, gcp, azure or k8s. This tool reports on one provider at a time: omit it and the organization's first connected provider is used, which is not the whole bill for a multi-cloud organization. Call get-identity to see which are available. |
get-cost-breakdown
Purpose: Break spend down into its largest components over a period.
Returns: a paginated, sorted list of cost lines with amounts and shares. With group_by, returns totals per value of that dimension instead of the list, with no pages to walk.
When to use: After get-cost-summary, to answer "what is driving it". Ask one broad question first rather than one call per service. The window is one calendar month unless start_date and end_date are both given. For "what does each region cost", "compare our accounts" or any per-region, per-account or per-service total, pass group_by rather than paging the lines and adding them up: a line is one service in one region in one account, so a month is thousands of them and a tally over pages is both slow and wrong.
Examples: top services this month: no arguments. Largest accounts in July: period="2026-07", sort_by="account_id". What each region costs: group_by="region". Compare accounts: group_by="account_id".
NOT for: Explaining a change over time, use get-cost-growth. Dating when a jump started, use get-cost-series. Savings opportunities, use list-recommendations.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
end_date | string, YYYY-MM-DD | none | End of the range, YYYY-MM-DD. Takes effect only together with start_date: on its own it is ignored and the month in period is reported instead. |
group_by | service, region, account_id | none | Total the spend by this dimension instead of listing cost lines. Returns one row per value with its cost, largest first, and no pages to walk. Each row also carries share_of_total, the same cost over the window before, and the change between them, all as the tool measured them, so a comparison needs no arithmetic of your own. previous_cost is null for a group that carried no spend in the window before, and change_vs_previous is null when there is nothing comparable to measure against: no prior spend for that group, or a window still being billed. Grouping by account_id adds account_name, which is null when no name is on file, leaving the id as the only label that account has. The rows may be trimmed when there are many groups; total, when it is present, still covers every group rather than only the rows shown. A row flagged unassigned holds the spend that carries no value for that dimension, which on region is a global service, a Reserved Instance fee or a Savings Plan line. page, page_size, sort_by and sort_order are ignored when this is set. |
page | integer, min 1 | 1 | 1-indexed page number. |
page_size | integer, 1 to 50 | 10 | Rows per page. |
period | string | none | Month to report on, YYYY-MM. Omit for the current month, or pass start_date and end_date together to report on an arbitrary window instead. |
provider | string | none | Cloud provider id, for example aws or gcp. Omit and the breakdown covers AWS only, which is not the whole bill for a multi-cloud organization. Call get-identity to see which are available. |
sort_by | cost, service, region, account_id, change_percentage | "cost" | Field to sort by. |
sort_order | asc, desc | "desc" | Sort direction. |
start_date | string, YYYY-MM-DD | none | Start of the range, YYYY-MM-DD. Takes effect only together with end_date: on its own it is ignored and the month in period is reported instead. |
get-cost-forecast
Purpose: Projected spend for the end of the current month.
Returns: the forecast figure, its confidence range, and the basis it was derived from: how much is already booked, the daily run rate, how many days are left to project, the day the actuals stop (actuals_through), how many of the trailing 30 days the run rate was drawn from (daily_rate_sample_days) and how many of those days carried almost nothing (daily_rate_thin_days).
When to use: "Where will we land this month." Read the basis before quoting the figure. A run rate drawn from a handful of days, actuals that stopped several days ago, or thin days in the window all mean the projection rests on less than it looks, and that belongs in the answer. Thin days usually mean an account stopped delivering billing data rather than that spend fell, so list-accounts is the next call rather than a conclusion.
NOT for: Historical spend, use get-cost-summary. A horizon beyond this month, which LevelFour does not forecast. LevelFour has no budget object either, so if the user asks whether they will exceed a budget you must ask them for the number.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
provider | string | none | Cloud provider id, for example aws, gcp, azure or k8s. This tool reports on one provider at a time: omit it and the organization's first connected provider is used, which is not the whole bill for a multi-cloud organization. Call get-identity to see which are available. |
get-cost-growth
Purpose: Which services grew the most, and by how much.
Returns: services ranked by how many dollars they added, with the percentage beside each, plus the two windows compared and how many days each covers, so a partial month is visible rather than silent.
When to use: "Why did the bill go up." Keep the default compare_to unless the user asked specifically about calendar months.
NOT for: Absolute spend ranking, use get-cost-breakdown. Unexpected spikes specifically, use list-anomalies.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
compare_to | previous_period, previous_month | "previous_period" | Baseline window. 'previous_period' compares the last 30 days against the 30 before them and is the reliable default. 'previous_month' compares this month so far against the whole of last month, so early in a month it understates growth. |
limit | integer, 1 to 50 | 10 | Maximum rows to return. |
provider | string | none | Cloud provider id, for example aws, gcp, azure or k8s. This tool reports on one provider at a time: omit it and the organization's first connected provider is used, which is not the whole bill for a multi-cloud organization. Call get-identity to see which are available. |
get-cost-series
Purpose: Daily spend over a date range, as a time series.
Returns: one point per day with the total for that day, and providers_covered naming the clouds those totals span. This is the only cost tool that covers every connected cloud at once, so a figure from here is not comparable with one from a single-provider tool unless providers_covered says it is.
When to use: To date a step change. When the bill jumped and you need to know which day it started, this is the only tool that can tell you. Pair it with get-cost-breakdown over the same window to attribute the jump. A day missing from the series had no rows at all, which is different from a day that cost nothing.
NOT for: Month totals, use get-cost-summary. Splitting a day by service, use get-cost-breakdown for that window.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
end | string, YYYY-MM-DD | none | End of the range, YYYY-MM-DD. Omit for today. |
start | string, YYYY-MM-DD | none | Start of the range, YYYY-MM-DD. Omit for the first of the current month. |
get-cost-summary
Purpose: Current cloud spend and where it is heading, or one month's total.
Returns: with a period, that month's spend and its change on the previous month, and nothing else. Without one: total spend, per-provider totals, month-over-month change and the monthly series.
When to use: The opening question, "what are we spending". For "what did we spend in July", pass period="2026-07" rather than reading it out of the series.
NOT for: Spend split by service, account or tag, use get-cost-breakdown. A day-level series, use get-cost-series.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
period | string | none | Month to report, YYYY-MM. Pass it when the question names one month, and the answer is that month's total and its change on the month before. Omit it for the current position, which also carries the forecast, potential savings and the monthly series. |
get-costs-by-tag
Purpose: Spend grouped by the value of a cost-allocation tag, for showback and chargeback.
Returns: spend per tag value, plus allocation coverage showing how much spend carries the tag. Called with no tag_key, returns the tag keys available so you can pick one.
When to use: "What does team X cost", or any per-team, per-environment or per-owner question. Read the coverage figure before reporting a total: untagged spend is not zero spend.
Examples: discover keys: no arguments. Then: tag_key="team".
NOT for: Per-service or per-account splits, use get-cost-breakdown. Waste per team, which no tool can answer directly because recommendations do not carry tags.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
end | string, YYYY-MM-DD | none | End of the range, YYYY-MM-DD. Omit for today. |
provider | string | none | Cloud provider id, for example aws, gcp, azure or k8s. This tool reports on one provider at a time: omit it and the organization's first connected provider is used, which is not the whole bill for a multi-cloud organization. Call get-identity to see which are available. |
start | string, YYYY-MM-DD | none | Start of the range, YYYY-MM-DD. Omit for the first of the current month. |
tag_key | string | none | Cost allocation tag key to group by. Call with no tag_key to list the keys available. |
get-execution-logs
Purpose: What one step of a rollout ran, and what it printed.
Returns: the commands and output recorded for a single step. These are LevelFour's own execution records, written by whatever applied the change; report them as such rather than as something you ran.
When to use: When the user asks what a rollout step actually ran or printed.
NOT for: The shape of the rollout, use get-implementation-status, which lists the steps and their states far more cheaply. Reading every step at once: output here is unbounded operator text, so this serves one step and names the others.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
recommendation_id | string | required | Recommendation id from list-recommendations, for example REC-1234. |
step_id | string | none | Step to read, from execution_steps on get-implementation-status. Omit for the step that failed, or the last step to run when none failed. |
get-identity
Purpose: Identify the connected LevelFour organization and what it has access to.
Returns: organization plan, the cloud providers that have data, and remaining evaluation runs.
When to use: To check the connection works, or when a provider argument was rejected and you need the valid values. You do not need to call this before every analysis.
NOT for: Cloud account ids or names, use list-accounts. Spend figures, use get-cost-summary.
Parameters
Takes no arguments.
get-implementation-status
Purpose: Where one savings has got to: decided, waiting on an approver, or rolling out.
Returns: the decision, the chosen delivery format, whether that format can actually run and what is blocking it if not, who asked for a rollout still waiting on approval, and the steps of a rollout under way with the state of each.
When to use: "Did that go through", "what is it waiting on", "why has nothing happened". Also before start-rollout, because it names the blocker in the same words that tool refuses with.
NOT for: What a savings needs before it can start, use get-savings-readiness. The commands a step ran, use get-execution-logs. The case for the savings, use get-recommendation. Watching in a loop: a rollout can take 12 to 72 hours to begin, so an empty pipeline means it has not started, not that it is stuck, and the answer to "is it done yet" is another call later rather than another call now.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
recommendation_id | string | required | Recommendation id from list-recommendations, for example REC-1234. |
get-manual-instructions
Purpose: The step-by-step guide for applying one savings by hand.
Returns: the customer-facing instructions as markdown, written for the person doing the work in their own cloud console, plus the resources the change touches.
When to use: When the delivery format is manual and the user is ready to make the change, or is deciding whether they can. This is the whole of the manual path: nothing is queued and no rollout runs, because the customer applies it themselves.
NOT for: The other formats. Automated Savings and IaC are applied by LevelFour and have their own prerequisites, which get-savings-readiness names. Not for whether the work is done either: that is settled separately and get-implementation-status reports it.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
recommendation_id | string | required | Recommendation id from list-recommendations, for example REC-1234. |
get-potential-savings
Purpose: Total unbooked opportunity across all recommendations, with per-status counts.
Returns: open potential savings split by provider, and a per-status breakdown of the whole catalog. The per-status figures are separate quantities and must not be summed: optimized is work already applied, unavailable is locked by the plan.
When to use: "How much could we save in total", or to size the backlog before listing it.
NOT for: Savings already achieved, use get-realized-savings. Individual opportunities, use list-recommendations.
Parameters
Takes no arguments.
get-realized-savings
Purpose: Savings already realized and booked, with who approved them.
Returns: realized totals, ROI and payback, plus a line-item history.
When to use: "How much have we actually saved", or any question about past results. Each ledger row carries a full monthly rate, so a sum across rows is a run rate, not a period total.
NOT for: Opportunities not yet applied, use get-potential-savings. Realized and potential savings must never be added together.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
account_id | array of string | none | Restrict to these values. Omit for all. |
end | string, YYYY-MM-DD | none | End of the range, YYYY-MM-DD. Omit to search up to the most recent record. |
environment | array of string | none | Restrict to these values. Omit for all. |
page | integer, min 1 | 1 | 1-indexed page number. |
page_size | integer, 1 to 50 | 10 | Rows per page. |
provider | string | none | Cloud provider id, for example aws, gcp, azure or k8s. Omit for every provider this organization has. Call get-identity if you are unsure which are available. |
service | array of string | none | Restrict to these values. Omit for all. |
start | string, YYYY-MM-DD | none | Start of the range, YYYY-MM-DD. Omit to search from the earliest record. |
get-recommendation
Purpose: The full case for one savings recommendation.
Returns: financials, the resources in scope, what will change, risk assessment, metrics, the delivery formats this savings backs in available_methods and the one chosen in implementation_method, and where the decision stands. display_status is the word every LevelFour surface prints; status here is the stored column and can read differently.
When to use: After list-recommendations, when the user asks about a specific id, and before recording any decision on it.
NOT for: Making the change. To record the user's accept or reject, use decide-recommendation; to settle the delivery format, set-implementation-method; to start the rollout, start-rollout. Not for a rollout already under way either, use get-implementation-status. Not for the hands-on guide: manual_instructions is withheld here and get-manual-instructions serves it. Not for scanning the backlog, use the list tool.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
recommendation_id | string | required | Recommendation id from list-recommendations, for example REC-1234. |
get-savings-grant
Purpose: The state of the Automated Savings access grant on one recommendation.
Returns: the grant's status, when it expires, what it is scoped to, and where the customer authorizes it. A grant reaches 'connected' only when they launch it in their own AWS console, which LevelFour cannot do for them and cannot hurry.
When to use: After create-savings-grant, to see whether the customer has authorized it yet, or when get-savings-readiness reports a grant blocker and you want the detail.
NOT for: Creating one, use create-savings-grant. Whether the savings itself can run, use get-savings-readiness, which weighs this alongside everything else. Do not poll this in a tight loop: authorizing is a person opening a console, so ask again later rather than again now.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
grant_id | string | none | Grant id from get-savings-grant or create-savings-grant. Omit for the latest. |
recommendation_id | string | required | Recommendation id from list-recommendations, for example REC-1234. |
get-savings-overview
Purpose: How the savings backlog splits across its statuses, in count and in money.
Returns: a count and a monthly savings figure per status (available, pending, awaiting_approval, processing, optimized, rejected, unavailable) plus the total number of recommendations, for one provider.
When to use: "How many savings are waiting on us", "how much is still open", or to size a status before listing it. Cheaper than paging list-recommendations to count rows.
NOT for: The individual opportunities, use list-recommendations. The organization-wide unbooked total, use get-potential-savings. Savings already booked, use get-realized-savings. These are separate quantities and summing across them is wrong: the optimized bucket is work already applied and the unavailable bucket is locked by the plan.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
provider | string | none | Cloud provider id, for example aws, gcp, azure or k8s. This tool reports on one provider at a time: omit it and the organization's first connected provider is used, which is not the whole bill for a multi-cloud organization. Call get-identity to see which are available. |
get-savings-readiness
Purpose: What still has to happen before a savings can be delivered each way.
Returns: one entry per format this savings backs, each saying whether it can run now and, when it cannot, the single thing that would clear it and the tool that does so. A ready IaC format also names the repositories its pull request would open against, which is usually a binding made long before this conversation. Pass a method to ask about one.
When to use: Before start-rollout, or whenever the user asks why a savings has not moved. It answers "what do I need" in one call rather than a refusal at a time.
NOT for: Where a rollout that already started has got to, use get-implementation-status. The case for the savings, use get-recommendation. Polling this while a customer authorizes a grant is fine, but a grant can take a while to connect, so leave time between calls.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
method | one-click, iac, one-click-plus-iac, manual | none | Ask about one delivery format. Omit for every format this savings backs. |
recommendation_id | string | required | Recommendation id from list-recommendations, for example REC-1234. |
get-usage-costs
Purpose: Billable quantity and cost per unit, grouped by usage type, and what a usage type is.
Returns: a paginated list of spend, quantity, unit and derived unit cost per usage type, largest first. A row whose quantity is not a countable unit carries no derived rate. Name a usage_type and each row also carries the services charging it, the regions and accounts it appears in and the days it was billed on.
When to use: To ground a savings claim in measured consumption, to tell a price change apart from a volume change, or to say what a code on the bill means. USE1-CachedData:Redis is answered by reading it here, because the row names the service and the region.
NOT for: Spend totals, use get-cost-breakdown. Note that usage quantity, not cost, is the reliable idleness signal here, because the cost columns round to cents.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
end | string, YYYY-MM-DD | none | End of the range, YYYY-MM-DD. Omit for today. |
page | integer, min 1 | 1 | 1-indexed page number. |
page_size | integer, 1 to 50 | 10 | Rows per page. |
provider | string | none | Cloud provider id, for example aws or gcp, or 'all'. Both 'all' and omitting it read the AWS usage tables, so name gcp explicitly to see GCP usage. Call get-identity to see which are available. |
start | string, YYYY-MM-DD | none | Start of the range, YYYY-MM-DD. Omit for the first of the current month. |
usage_type | string | none | Narrow to the usage types whose code contains this text, case-insensitively, for example USE1-CachedData:Redis or NatGateway. Naming one also reports which services charge it, which regions and accounts it appears in and how many days it was billed on, which is what says in plain words what the code is. Omit to rank every usage type by spend. |
list-accounts
Purpose: The cloud accounts connected to this organization.
Returns: account id, name, provider, region, connection status, and whether detailed billing data is flowing for each.
When to use: To turn an account id seen in a cost or recommendation row into a name, to answer "which accounts are connected", or to check why an account has no data.
NOT for: Spend per account, use get-cost-breakdown with sort_by="account_id".
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer, min 1 | 1 | 1-indexed page number. |
page_size | integer, 1 to 50 | 10 | Rows per page. |
list-anomalies
Purpose: Detected cost anomalies, meaning unexpected spikes.
Returns: anomalies with service, magnitude, detection time and status, plus counts by severity.
When to use: "Did anything spike", or investigating an unexpected increase in a past month. With no start and end this spans every anomaly ever detected, so pass both to ask about one month. The window is matched against the day a spike began, not the day it was detected.
NOT for: Expected or gradual growth, use get-cost-growth.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
end | string, YYYY-MM-DD | none | End of the range, YYYY-MM-DD. Omit to search up to the most recent record. |
page | integer, min 1 | 1 | 1-indexed page number. |
page_size | integer, 1 to 50 | 10 | Rows per page. |
provider | string | none | Cloud provider id, for example aws, gcp, azure or k8s. Omit for every provider this organization has. Call get-identity if you are unsure which are available. |
severity | critical, warning | none | Restrict to one severity. Omit for all. |
start | string, YYYY-MM-DD | none | Start of the range, YYYY-MM-DD. Omit to search from the earliest record. |
status | active, resolved, dismissed | none | Restrict to one anomaly status. Omitting it returns active and resolved only, so ask for 'dismissed' explicitly to see the ones marked not real. |
list-approval-requests
Purpose: Rollouts waiting on an admin to release them, oldest first.
Returns: the recommendation, its monthly saving, who asked, when they asked, and the delivery format they proposed, which can be absent.
When to use: "What is waiting on me", "what needs approving". Then release-rollout to release one.
NOT for: The savings backlog, use list-recommendations. Deciding whether a savings is worth doing, open it with get-recommendation first: this answers who is waiting, not whether to say yes.
Parameters
Takes no arguments.
list-commitments
Purpose: The individual Reserved Instances and Savings Plans, with their end dates.
Returns: each commitment with kind, service, start and end date, and status. Status is read from the end date, so a commitment whose term has passed reports as expired. The monthly commitment amount is present only where it is populated.
When to use: "What expires before the end of the quarter", or to size the cliff when a commitment lapses and its usage reverts to on-demand rates.
NOT for: Coverage and utilization percentages, use get-commitment-overview.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
kind | string | none | Restrict to one commitment kind, for example reserved_instance or savings_plan. |
page | integer, min 1 | 1 | 1-indexed page number. |
page_size | integer, 1 to 50 | 10 | Rows per page. |
provider | string | none | Cloud provider id, for example aws, gcp, azure or k8s. Omit for every provider this organization has. Call get-identity if you are unsure which are available. |
status | string | none | Restrict to one status, for example active or expired. |
list-recommendations
Purpose: Savings opportunities LevelFour has found, largest first.
Returns: a paginated list with id, service, environment, account, monthly savings, the share of current spend that saves, display_status, risk level and a short description. Only open opportunities unless display_status says otherwise, and the filter applied is echoed back as filtered_to. Read display_status: it is the word every LevelFour surface prints for a recommendation. status carries the same value here and is kept only for clients written before display_status existed. Full detail, annual figures included, is deliberately omitted: open one with get-recommendation. With group_by, returns totals per value of that dimension instead of the list, with no pages to walk.
When to use: "What can we save." Filter server-side rather than paging and discarding: to answer "what can we save on RDS in staging", pass service and environment. service here is spelled the short way, ElastiCache or RDS, not the billing name the cost tools return, so a service copied out of get-cost-breakdown ("Amazon ElastiCache", "Amazon Relational Database Service") matches nothing and comes back as an empty page that reads like an empty backlog. When a spelling is in doubt, drop the filter and read service off the rows. For "which service holds the most" or any per-team or per-account split, pass group_by rather than paging the backlog and adding it up.
Examples: biggest open wins: no arguments. Where the savings are concentrated: group_by="service". Everything actionable without a human: available_formats=["automated"]. What has already been applied: display_status=["optimized"]. What failed to apply: display_status=["failed"].
NOT for: Savings already realized, use get-realized-savings. These are potential and unbooked, and the two must never be added together.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
account | array of string | none | Restrict to these values. Omit for all. |
available_formats | array of string | none | Restrict to opportunities applicable this way: automated, iac, or manual. |
display_status | array of string | none | Restrict to these statuses. Omitted, only open opportunities are returned. The accepted values are 'available' (open, nobody has taken it), 'pending' (accepted and waiting to be applied), 'awaiting_approval', 'processing', 'in_progress' (a rollout under way), 'optimized' (applied, and 'saved' is accepted for the same thing), 'failed' (an apply that did not complete), 'rejected' and 'unavailable' (locked by the plan). 'in_progress' and 'failed' have no tab on the savings page, so this is the only way to find a rollout that is running or one that broke. Any other value returns zero rows rather than an error, so an empty page can mean a typo here rather than an empty backlog. |
environment | array of string | none | Restrict to these values. Omit for all. |
group_by | service, environment, account, tag | none | Total the savings by this dimension instead of listing them. Returns one row per value with its savings and how many opportunities it holds, largest first. The filters still apply, so the totals cover exactly the rows the same call would have listed. A row flagged unassigned holds the opportunities where that dimension is not set, and its value cannot be passed back as a filter. page, page_size and sort_by are ignored when this is set. |
page | integer, min 1 | 1 | 1-indexed page number. |
page_size | integer, 1 to 50 | 10 | Rows per page. |
provider | string | none | Cloud provider id, for example aws, gcp, azure or k8s. This tool reports on one provider at a time: omit it and the organization's first connected provider is used, which is not the whole bill for a multi-cloud organization. Call get-identity to see which are available. |
service | array of string | none | Restrict to these values. Omit for all. |
sort_by | monthly_savings, savings_percentage, recommendation_id, service, status, created_at | "monthly_savings" | Field to sort by. |
tag | array of string | none | Restrict to these values. Omit for all. |
list-repositories
Purpose: The organizations and repositories a savings can open its pull request against.
Returns: called bare, the version control installations this organization has. Called with one, the repositories that installation can reach, narrowed by query when given.
When to use: Before set-implementation-method on a format that opens a pull request, to put the orgs and then the repositories in front of the user so they can choose. An organization can have thousands of repositories, so search rather than page: query matches any part of the name, and "postgres" or the resource in the recommendation is usually enough.
NOT for: Connecting an organization that has none, which is connect-version-control. Whether a savings already has a repository, which get-savings-readiness answers as a yes or no without naming it.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
installation_id | integer | none | Version control installation from list-repositories. Omit to list the installations. |
page | integer, min 1 | 1 | 1-indexed page number. |
page_size | integer, 1 to 50 | 10 | Rows per page. |
query | string | none | Case-insensitive substring of the repository name, applied when an installation is named. Omit to list them all, which is only workable for a small organization. |
release-rollout
read-write key, and your client asks before calling it.Purpose: Release a rollout a colleague asked for, as the admin answering them.
Returns: the decision as recorded, and the delivery format it was released with.
When to use: When the user names a rollout a colleague asked for and says to let it through. This is the release itself, so reach for it once they have said yes rather than to show them what is pending.
NOT for: Seeing what is waiting, which is list-approval-requests. Refusing one, which is decide-recommendation with decision='rejected'. Nor accepting a savings nobody has asked to roll out, which is decide-recommendation as well. Releasing needs a credential an organization admin authorized; a plain API key is refused.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
implementation_method | one-click, iac, one-click-plus-iac, manual | none | Delivery format to settle before releasing, for a request whose author named none. Omit when they did. Must be one of available_methods on get-recommendation. |
recommendation_id | string | required | Recommendation id from list-recommendations, for example REC-1234. |
set-implementation-method
read-write key, and your client asks before calling it.Purpose: Record how an accepted savings should be delivered, and for a pull request, where it lands.
Returns: the recommendation with the format now settled on it, the repositories it will open against, and whether that format can run yet.
When to use: When the user has told you which format they want. Only the formats in available_methods are accepted, so read those from get-recommendation if you do not already have them. 'iac' and 'one-click-plus-iac' open a pull request, so they also need the organization and the repositories the user chose, from list-repositories. Ask them; a repository is somebody's infrastructure and the customer is the only one who knows which holds this resource.
NOT for: Starting the rollout, which is start-rollout. Changing the format once a rollout has begun, which is refused here: the steps already recorded belong to the old format. Choosing 'manual' says the customer will apply the change themselves, and get-manual-instructions is what they follow next.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
installation_id | integer | none | Organization whose repositories the pull request may open against, as an installation id from list-repositories. Required for a format that opens one, alongside repositories. Name the one the user chose: it is never inferred, because an organization can have several and only the customer knows which holds this resource. |
method | one-click, iac, one-click-plus-iac, manual | required | How the change gets delivered. 'one-click' is Automated Savings, which applies it in the customer's cloud through a scoped grant they authorize. 'iac' opens a pull request against a bound repository. 'one-click-plus-iac' does both, applying first so the committed infrastructure does not drift. 'manual' means the customer applies it themselves. Only the formats in available_methods on get-recommendation are accepted; a savings does not back all four. |
recommendation_id | string | required | Recommendation id from list-recommendations, for example REC-1234. |
repositories | array of string | none | Repositories the pull request opens against, as owner/name, from list-repositories under the same installation. Required for a format that opens one, and one or many is fine. This is the whole selection and it replaces any earlier one, so pass every repository that should receive a pull request. Search for it with the query argument on list-repositories rather than paging: an organization can have thousands. |
start-rollout
read-write key, and your client asks before calling it.Purpose: Put an accepted savings into the rollout queue.
Returns: either that the rollout started, or that an approval request was filed for an admin to release, in outcome. Which of the two happens depends on the credential: one an admin authorized starts it, any other files the request the way a team member's click does.
When to use: When the user says to go ahead on a savings that is already accepted and already has its delivery format settled, its destination included.
NOT for: Accepting it, which is decide-recommendation and has to happen first. Not for the manual format either: nothing is queued for a change the customer applies themselves, and get-manual-instructions is what they need instead. Nor for a format that cannot run yet: Automated Savings needs a scoped grant the customer launches in their AWS console, and IaC needs a bound repository. Both are refused here and both are finished in the LevelFour dashboard, so pass the refusal on rather than trying another way. A credential an administrator authorized may start a savings it also accepted, which is one click of Approve Savings; any other credential files an approval request for somebody else to answer, and that refusal is not something to work around.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
method | one-click, iac, one-click-plus-iac | none | Delivery format to settle before starting, when the row does not already carry one. Omit when it does. Must be one of available_methods on get-recommendation. 'manual' is absent on purpose: a change the customer applies themselves is queued nowhere, so set-implementation-method is the whole of it. |
recommendation_id | string | required | Recommendation id from list-recommendations, for example REC-1234. |
update-anomaly-status
read-write key, and your client asks before calling it.Purpose: Record what the user decided about one detected cost anomaly.
Returns: the anomaly id and the status now recorded against it.
When to use: Only when the user has told you, in this conversation, what to do with a specific anomaly. "That spike was our migration" is planned. "That was not real" is dismissed. "We fixed it" is resolved.
NOT for: Changing any cloud spend. This writes a status on a LevelFour row and nothing else. Dismissing also trains the detector, so do not use it to tidy a list. To read anomalies rather than judge them, use list-anomalies. Read status in the result rather than assuming your argument was stored verbatim. 'acknowledged', 'planned' and 'resolved' all store resolved and differ in the feedback recorded, so the row will not read back as 'acknowledged'.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
anomaly_id | string | required | Anomaly id from list-anomalies. |
note | string | none | Short note recorded with the change. Only stored for status='resolved'. |
status | acknowledged, dismissed, resolved, planned | required | What to record. 'dismissed' says the spike was not a real anomaly and is negative feedback to the detector. The other three all close the anomaly and differ only in the feedback stored against it: 'acknowledged' confirms it was real, 'planned' says the spend was expected such as a migration or a load test, and 'resolved' closes it with no verdict and takes an optional note. Closing is one-shot, so a second call against an already closed anomaly is refused rather than applied. |