Cloud Cost Optimization
wshobson/agents
Cuts cloud spend across AWS, Azure, GCP and OCI with cost tagging, rightsizing, commitment and spot pricing models, and architecture changes.
Report what the AWS DevOps Agent itself costs to run, and where that cost comes from, per Agent Space and per role on demand in chat or on a schedule through a custom agent.
$ npx skills add aws/tools-for-devops-agent --skill devops-agent-cost-insights -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install aws/tools-for-devops-agent devops-agent-cost-insights --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/aws/tools-for-devops-agent.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/devops-agent-cost-insights .claude/skills/devops-agent-cost-insights && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "devops-agent-cost-insights" agent skill from https://github.com/aws/tools-for-devops-agent/tree/main/skills/devops-agent-cost-insights into .claude/skills/devops-agent-cost-insights/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "devops-agent-cost-insights", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/aws/tools-for-devops-agent/tree/main/skills/devops-agent-cost-insightsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add aws/tools-for-devops-agent --skill devops-agent-cost-insights -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install aws/tools-for-devops-agent devops-agent-cost-insights --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/aws/tools-for-devops-agent.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/devops-agent-cost-insights .agents/skills/devops-agent-cost-insights && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "devops-agent-cost-insights" agent skill from https://github.com/aws/tools-for-devops-agent/tree/main/skills/devops-agent-cost-insights into .agents/skills/devops-agent-cost-insights/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "devops-agent-cost-insights", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add aws/tools-for-devops-agent --skill devops-agent-cost-insights -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install aws/tools-for-devops-agent devops-agent-cost-insights --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/aws/tools-for-devops-agent.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/devops-agent-cost-insights .cursor/skills/devops-agent-cost-insights && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "devops-agent-cost-insights" agent skill from https://github.com/aws/tools-for-devops-agent/tree/main/skills/devops-agent-cost-insights into .cursor/skills/devops-agent-cost-insights/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "devops-agent-cost-insights", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/aws/tools-for-devops-agent.git --path skills/devops-agent-cost-insights--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add aws/tools-for-devops-agent --skill devops-agent-cost-insights -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install aws/tools-for-devops-agent devops-agent-cost-insights --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/aws/tools-for-devops-agent.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/devops-agent-cost-insights .gemini/skills/devops-agent-cost-insights && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "devops-agent-cost-insights" agent skill from https://github.com/aws/tools-for-devops-agent/tree/main/skills/devops-agent-cost-insights into .gemini/skills/devops-agent-cost-insights/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "devops-agent-cost-insights", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install aws/tools-for-devops-agent devops-agent-cost-insightsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add aws/tools-for-devops-agent --skill devops-agent-cost-insights -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/aws/tools-for-devops-agent.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/devops-agent-cost-insights .github/skills/devops-agent-cost-insights && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "devops-agent-cost-insights" agent skill from https://github.com/aws/tools-for-devops-agent/tree/main/skills/devops-agent-cost-insights into .github/skills/devops-agent-cost-insights/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "devops-agent-cost-insights", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add aws/tools-for-devops-agent --skill devops-agent-cost-insights -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install aws/tools-for-devops-agent devops-agent-cost-insights --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/aws/tools-for-devops-agent.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/devops-agent-cost-insights .opencode/skills/devops-agent-cost-insights && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "devops-agent-cost-insights" agent skill from https://github.com/aws/tools-for-devops-agent/tree/main/skills/devops-agent-cost-insights into .opencode/skills/devops-agent-cost-insights/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "devops-agent-cost-insights", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
devops-agent-cost-insightsReport what the AWS DevOps Agent itself costs to run, and where that cost comes from, per Agent Space and per role on demand in chat or on a schedule through a custom agent.
Devops Agent Cost Insights is an agent skill from aws/tools-for-devops-agent, published by the product's own GitHub organization. Report what the AWS DevOps Agent itself costs to run, and where that cost comes from, per Agent Space and per role on demand in chat or on a schedule through a custom agent. Use this skill when a user asks to measure, break down, attribute, explain, or forecast DevOps Agent spend, or the cost of the downstream AWS API calls. Covers direct agent time by activity, Support plan credit offset, downstream API cost, and tool usage.
Its SKILL.md is about 12k tokens, which your agent loads only when the skill is triggered. The skill folder holds 295 other files (for example `CHANGELOG.md`, `README.md` and `evals/best-practices/v1/benchmark.json`).
It sits in DevOps & Cloud. It works with Amazon Web Services. The repository describes itself as: Open-source tools for AWS DevOps Agent - extend DevOps Agent with ready-to-use skills, custom agents, and other tools, for incident response, root cause analysis, and operational…. The licence is Apache-2.0.
8 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit ddda70b. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
awsFrom the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
aws.amazon.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Devops Agent Cost Insights loads about 12k tokens when it runs. Until then it costs about 114 tokens; SKILL.md has 6,880 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from aws/tools-for-devops-agent at commit ddda70b, republished under its Apache-2.0 licence (© aws). 6,880 words, ~12,284 tokens.
.claude/skills/devops-agent-cost-insights/SKILL.md (or your agent's skills folder). This skill also uses 286 other files; get the full folder from GitHub.This skill provides the methodology for gathering and calculating AWS DevOps Agent cost data. It intentionally does NOT prescribe a fixed output format. The consuming agent (chat, custom agent, etc.) decides its own presentation (plain text, multi-space tables, single-space visual dashboard with charts, etc.) based on its own prompt/output spec. Follow the steps below to gather and compute correct numbers; format them however the calling context requires.
The consuming agent's output contract controls visibility. When it requires silent, final-only execution:
This skill must add exactly $0.00 to the bill. Never
StartQuery,StartQueryExecution, orGetMetricData— and never any other operation the zero-cost rule names below. Each is a paid API, so issuing one bills the account this report is about. If a figure is only reachable through a paid call, it is unavailable; say so. This is the zero-cost rule, restated at Step 1 and attested in Step 7."Read-only" is not the safety test.
GetMetricDatareads only your own metrics and is billed per metric anyway. Before using any call not already named in the steps below, classify it per Operation classification in Step 3; an operation you cannot confirm as free is unclassified, not free.
Four things to cover every time:
Work through this checklist in order and do not skip a step. The steps are dependent, not independent: Step 1 fixes the <START>/<END> window that Steps 3 and 7 must reuse, and Step 7 validates the figures produced by Steps 1 through 6. Track checklist completion internally. Do not print step-by-step progress or skipped-step narration; surface only trust-impacting omissions in the consuming agent's single final response.
GetMetricStatisticsThe consuming agent defines the scope. When it supplies an explicit ROLE_ARN and declares exact-role scope, that scope overrides this skill's multi-role discovery and role-coverage guidance:
ROLE_ARN as the complete allowlist of one role. Skip role discovery and never add historical, rotated, inferred, or similarly named roles.userIdentity.sessionContext.sessionIssuer.arn must equal ROLE_ARN. For an STS assumed-role identity, normalize only an ARN with the same account and exact configured role name to ROLE_ARN.AgentSpaceUUID metric cannot isolate one role. Label downstream and tool usage as exact-role-scoped. Do not present the combined result as the complete Agent Space total.The multi-role discovery guidance below applies only when the consuming agent requests Agent Space-wide or account-wide scope.
These named rules are defined once here and referenced by name throughout. "Per the quantity source rule", "passes the attribution test", "per the Logs source rule", and "match the active role scope" mean exactly what is written below; the step does not restate them.
ROLE_ARN in exact-role mode, or one of the Step 0 discovered role ARNs in multi-role mode.describe_queries is the sole source of query count, role attribution, scan bytes, and cost. Never substitute a CloudTrail StartQuery lookup; journal data is a cross-check only. If describe_queries is unavailable, report Logs Insights unavailable rather than substituting another source.userIdentity / sessionIssuer.arn, never on a CloudTrail Username filter. DevOps Agent roles in one account share a single CloudTrail session name, so a Username count aggregates across roles and overstates the target. See Cross-check: CloudTrail for the mechanics.Requests, Metrics, traces) prices from the attributed call count, which Step 3 produces for every operation, so any per-call price dimension can be priced, including one from a service named nowhere in this skill; where a service tiers its requests, name the tier or do not price. A data-class unit (GB, TB) needs a byte figure, so it prices only from the sources Step 3 names, never from a call count. When the quantity is missing, report the call count with no dollars: these are all paid operations, so a row without dollars is a measurement gap, never a free call, and makes the Priced Downstream Total a lower bound. A confirmed 0 calls is exactly $0.00, not a gap. Each is countable when the audited agent issued it, forbidden when this run would (see Zero-cost rule).StartQuery, no StartQueryExecution, no GetMetricData, no log scanning. Use only the confirmed-free calls named in these steps. If a step appears to need a billable call, it finishes without that figure and reports the gap. Defined in the Overview, restated at the point of temptation in Step 1, and attested in Step 7. The rule binds by effect, not by name, across three evasion paths:StartQuery, StartQueryExecution, GetMetricData, BatchGetTraces) or any wrapper or tool form of them, including start_query, query_cloudwatch_logs, get_metric_data. Do not call GetQueryResults either: it is free, but it is the second half of a StartQuery pair and describe_queries already returns bytesScanned. An operation not named here is classified per Operation classification in Step 3 before it is called, and is unclassified rather than free if it cannot be confirmed free.shell is not an escape hatch. A paid operation invoked through shell (for example aws logs start-query, aws cloudwatch get-metric-data, or an equivalent CLI or script) bills the account exactly as the tool form would. Do not use shell, use_aws, or any command runner to issue a scan or paid read this rule forbids by name.get_investigation_journal_records and get_other_agentspace_journal_records are called directly. When those tools are blocked this run, the Context Gatherer subagent is the fallback (see Step 3), and this rule travels with the delegated request.What this step resolves depends on the scope the consuming agent asked for (see Scope precedence above): the single space this run is scoped to, or every space in the account. Nothing in it is inferred.
Always — resolve the space this run is running in, and its role. This is the whole purpose of the step when the consuming agent supplied no identifiers.
get_agent_space for the current space returns its name and agentSpaceId.list_associations for that space returns its AWS configuration. Take the role from configuration.aws.assumableRoleArn, with accountId and accountType alongside it. Pair on this field and nothing else.For a single-space request that is the whole step. Everything below applies only when the consuming agent requested Agent Space-wide or account-wide scope.
Account-wide or Agent Space-wide scope — enumerate the remaining spaces.
list_agent_spaces returns every Agent Space in the account, each with name, agentSpaceId, and createdAt. This is the authoritative inventory of live spaces.list_associations for each one and read configuration.aws.assumableRoleArn the same way.Never pair a role to a space by creation timestamp. Role and space creation times are not correlated: a space's role may be created long after the space, while an unrelated role is created moments before it. Nearest-timestamp pairing therefore produces confident but wrong pairings, attributing one space's downstream cost to another space's role.
configuration.aws.assumableRoleArnis the only pairing source.
list_agent_spaces returns spaces that exist now. CloudWatch retains AgentSpaceUUID dimension values for spaces that have since been deleted, so the metric namespace routinely carries many more space IDs than the account has spaces. Collect the AgentSpaceUUID values Step 1 will read and split them:
list_agent_spaces. Name and role are both known.Report retired spaces as one retired spaces line with their count. Never fold them into a named space, and never drop them. An account-wide total that omits them is a lower bound; one that includes them is complete for direct usage only, because their downstream activity has no resolvable role. State which of the two you produced — Step 2's credit gate depends on it.
aws:SourceAccount. When that value is not the audited account, the role serves another account's space: exclude it from totals and report it as a cross-account anomaly. Read aws:SourceAccount for this and nothing else — see the warning below before reading aws:SourceArn.assumableRoleArn points at is residue from a deleted space. List these separately, and never pair one to a live space to make the counts reconcile. Apply this only to the agent role type below; the web app role is never an assumableRoleArn, so testing it this way reports every one of them as an orphan.A trust policy does not pair a role to a space. On the agent role,
aws:SourceArnis normally the wildcardagentspace/*(no space ID); where a specificagentspace/<id>appears it is usually a web app role, which must never be paired.aws:SourceArntherefore fails on the role that matters and succeeds on the wrong one.
Role types are not interchangeable, and names are not a discovery mechanism. One space commonly has several roles with unrelated suffixes:
DevOpsAgentRole-AgentSpace-<suffix> — assumed by the agent to reach your resources. Cost attribution uses this one only, and only when configuration.aws.assumableRoleArn names it.DevOpsAgentRole-WebappAdmin-<suffix> — enables the off-console web app. Never a cost-attribution role.Paths vary (role/... and role/service-role/...), other patterns exist, and the suffixes of one space's roles do not match each other. Use names only to find orphans.
The reporting window is an input, not a fixed period. Take <START>/<END> from the request — an explicit range, a named period ("last 7 days", "August"), or the consuming agent's configured default. This skill prescribes no window of its own; a custom agent that wants a standing trailing window pins it in its own configuration and passes it in. Resolve it to absolute UTC timestamps once, here, then reuse those exact values everywhere downstream: Steps 3 and 7 depend on one window for the whole report, and a report that mixes windows describes no real period. Where scope affects credit eligibility (Step 2) or exactness labels (Step 7), those rules read the window resolved here.
Read metrics with GetMetricStatistics, never GetMetricData (zero-cost rule).
Enumerate the namespace first; never work from a fixed list of activity types. Billable activities are whatever AWS/AIDevOps currently publishes; a hardcoded list silently drops any activity added later and understates the total with no error.
use_aws(
service_name="cloudwatch", operation_name="list_metrics",
aws_account_id="<ACCOUNT_ID>", aws_region="<REGION>",
parameters={"Namespace": "AWS/AIDevOps",
"Dimensions": [{"Name": "AgentSpaceUUID", "Value": "<AGENT_SPACE_ID>"}]}
)Paginate until no NextToken remains. From the result, take every metric whose name matches Consumed*Time as a billable agent-time metric, and give each one a term in the sum below. Treat consumed-time metrics as billable seconds; a Consumed*Requests or *Count metric is a volume measure, not agent-seconds, so never multiply it by the agent-second rate — report it separately if useful.
Report the metric names you found. If enumeration returns a name this skill has not seen before, include it, price it at the agent-second rate, and say that it was discovered rather than expected. If list_metrics is denied, fall back to reading the names known at authoring time — ConsumedInvestigationTime, ConsumedEvaluationTime, ConsumedOnDemandTime — and label direct cost a lower bound, because an unenumerated namespace cannot be shown to be complete.
The AWS/AIDevOps namespace metrics are NOT OTel-enriched, so PromQL/Prometheus queries return empty for these. Read them with get_metric_statistics, one call per discovered metric per Agent Space in scope:
use_aws(
service_name="cloudwatch",
operation_name="get_metric_statistics",
aws_account_id="<ACCOUNT_ID>",
aws_region="<REGION>",
parameters={
"Namespace": "AWS/AIDevOps",
"MetricName": "<each Consumed*Time metric returned by list_metrics>",
"Dimensions": [{"Name": "AgentSpaceUUID", "Value": "<AGENT_SPACE_ID>"}],
"StartTime": "<START>",
"EndTime": "<END>",
"Period": 86400,
"Statistics": ["Sum"]
}
)AgentSpaceUUID dimension is required. Without it, you receive account-level aggregates that can't distinguish between spaces.
Use Period: 86400 (daily) so Datapoints can be broken out per day if the consuming agent needs a time-series/trend view, not just a single aggregate.
Resolve the agent-second rate on this run; never carry one in from memory. Try these in order and stop at the first that yields a rate, then report which one did:
If neither yields a rate, report direct cost as unavailable, naming the reason. Do not substitute a remembered figure. Direct cost is the largest number in this report, so a stale rate misstates the entire report rather than one line. Report the agent-seconds from Step 1 either way — those are measured, exact, and independent of any rate.
State the resolved rate and its source wherever direct cost appears. Then sum over every metric discovered above, so no activity is silently dropped:
billable_seconds = Σ( Sum(m) for each Consumed*Time metric m discovered )
direct_cost = billable_seconds × agent_second_rateThe sum is over the discovered set, not a fixed list of activities: one term per metric list_metrics returned, whatever they turn out to be. A metric the deployment does not emit contributes 0. Report the metrics that made up the sum, and name any that this skill did not anticipate.
If a discovered activity bills on its own charge rather than the agent-second rate, price that metric's seconds separately by resolving its rate per Resolving rates, and keep it as its own line rather than folding it into billable_seconds. Release-readiness review is the case to check for: a separate DevOps Agent charge has never been confirmed to exist in the price list.
If a separate-charge lookup fails, report that activity's hours with cost
unavailable— not$0.00, and not at the agent-second rate. An empty or denied lookup for a DevOps Agent charge is the expected outcome rather than a fault, since none has been confirmed to exist. Guessing either way misstates the total. A separately-charged activity left unpriced makes direct cost a lower bound, so label it.
DevOps Agent usage is offset by credits equal to a percentage of the account's monthly AWS Support charge, applied toward usage at the agent-second rate. Credits are issued by the 10th of each month, apply to that month's charges, and expire at month-end without rolling over. These percentages are published on the DevOps Agent pricing page, so the table below reflects public pricing, not an operator assumption. They have no Pricing API entry, so never try to resolve them from the price list; and because that page is script-rendered, a live fetch is unreliable, so the values are stated here directly. Only the account's own tier applies:
| Support plan | Credit | CREDIT_RATE_DECIMAL |
|---|---|---|
| Unified Operations | 100% | 1.00 |
| Enterprise Support | 75% | 0.75 |
| Business Support+ | 30% | 0.30 |
| Business, Developer, Basic | none | — |
The plan and charge are deployment values, not skill values. This skill ships none of them, and nothing in it infers them from bill line items or credit size. Read them from the operator's configuration if supplied — SUPPORT_PLAN and PRIOR_MONTH_SUPPORT_CHARGE — and treat either that is absent as unknown. An unknown plan yields no credit, which is safer than a wrong one. The credit rate is not a separate input: derive it from SUPPORT_PLAN using the tier table above. Both supplied values come from the Billing console: Support plans, and the AWS Support line on the previous month's bill, which must be the month immediately before the reported month.
Then apply the scope gate before subtracting anything.
Credit subtraction is gated by scope. Produce a subtracted Net Direct Cost only in a full-calendar-month, account-wide report in which the Step 0 reconciliation found no retired spaces inside the window. A retired space's usage is billed but cannot be attributed to a named space or role, so a window containing one has an incomplete inventory by definition and this branch does not apply. Account-wide scope cannot be established without Step 0: when Step 0 was skipped because scope was already fixed to one space or role, this branch does not apply and there is nothing to evaluate — report Net Direct Cost as unavailable at this scope. Otherwise:
monthly_credits = support_charge × credit_rate
net_direct_cost = max(0, direct_cost − monthly_credits)The base is the Support charge of the calendar month immediately preceding the report month (that is the most recent complete charge when credits are issued on the 10th). Use credit_rate as the decimal from the tier table (e.g. 0.75 for Enterprise Support), not the percentage; multiplying by 75 overstates the credit hundredfold.
At a narrower scope, do not subtract. For exact-role, single-space, partial-month, rolling, weekly, or per-investigation reports, show the plan, rate, and monthly credit as account-level reference only, and report Net Direct Cost as unavailable at this scope. Scope precedence treats exact-role single-space as the common path, so this branch is the default rather than the exception.
Guardrails:
monthly_credits only when SUPPORT_PLAN is a crediting tier and PRIOR_MONTH_SUPPORT_CHARGE is set. The charge is taken to be that of the calendar month immediately before the reported month; supply the current month's figure, since a stale charge carried over from an earlier run computes a wrong credit.unknown and the rate is unavailable. Show direct cost and prompt: "Provide your monthly AWS Support charge to calculate your credit offset."net_direct_cost at zero, and never print $0.00 for an unknown credit. The entitlement computed here is not the applied amount — confirm it against the credit on the bill before relying on a net figure.Source authority depends on the category. Work down this order, and stop at the first source that owns the figure:
describe_queries is exclusive for Logs count, role, bytes, and cost (the Logs source rule); Athena history supplies exact bytes.describe_queries Logs totals.StartQueryExecution, a management event CloudTrail records by default — no data events needed. Separately, GetMetricData and the X-Ray operations appear only as data events, which are off by default; that is where their quantity comes from, since they have no service history API of their own. When the data event is present, read the exact billable quantity from its requestParameters: MetricDataQueries for GetMetricData (the per-metric count that GMD-Metrics bills, not the call count) and TraceIds for BatchGetTraces. When it is absent, the journal supplies only the call count and the cost is unavailable, since the per-item quantity is not in the journal.Never start with CloudTrail (CloudTrail-lower-bound rule).
Read journal records across the window with get_investigation_journal_records and get_other_agentspace_journal_records, plus get_tool_calls for tool-level detail. From each utilization / tool-call record extract the operation issued, the IAM role or session context that issued it, and the timestamp.
Build the per-role, per-operation call counts from this data first. For Logs Insights StartQuery, keep the journal count only as a cross-check per the Logs source rule — the reported Logs query count, attribution, bytes, and cost come from describe_queries.
GetMetricData is countable when the audited agent issued it; this run still may not issue it (zero-cost rule).If journal access is unavailable this run, say so explicitly. For Logs Insights the Logs source rule still holds — journal absence does not authorize a CloudTrail
StartQuerylookup. For Athena and the data-event rows, fall back to the documented service history and CloudTrail paths. Never report zero as though the journal confirmed it. "No journal access" and "no calls made" are different findings.If the direct journal tools are blocked this run, the Context Gatherer subagent is the fallback for reading journal/utilization records during an investigation. Carry the zero-cost rule into the delegated request, and never delegate an action you could not issue directly. If neither the direct tools nor delegation return records, report journal access unavailable, not zero.
Use the native lookup_cloudtrail_events tool for operations with no service history API of their own, such as X-Ray, and to sanity-check journal counts elsewhere. The tool applies jmespath_filter to a root array of event summaries. Identity fields are not top-level JMESPath fields; the detailed event is serialized JSON in CloudTrailEvent.
For exact-role scope, use one event name per call and filter the serialized event by the complete ARN before it reaches the report:
lookup_cloudtrail_events(
attribute_key="EventName",
attribute_value="<EVENT_NAME>",
aws_account_id="<ACCOUNT_ID>",
aws_region="<REGION>",
start_time="<START>",
end_time="<END>",
exclude_event_names=[],
jmespath_filter="[?contains(CloudTrailEvent, '<ROLE_ARN>')].{Time: EventTime, Event: CloudTrailEvent}"
)For multi-role scope only, use [].{Time: EventTime, Event: CloudTrailEvent} and post-filter parsed events against the discovered role ARN set. Never use events[?userIdentity...]: events is not the JMESPath root and userIdentity exists only inside the serialized CloudTrailEvent value.
Parse every returned Event JSON string before using it. Then verify the parsed userIdentity.sessionContext.sessionIssuer.arn against the active role scope; the contains filter is an early reduction, not the final identity check. A valid no-match result is events: []. The result events: null means the JMESPath shape or tool response failed, not zero activity. Retry once with the exact filter shape above; if it remains null, mark CloudTrail unavailable and do not report a zero.
Use CloudTrail selectively. Not for Logs Insights StartQuery (Logs source rule), and never as the Athena scan-size source (Athena history stays authoritative for bytes). Athena history does not expose the initiating principal, so StartQueryExecution CloudTrail events are required to map the active role scope to responseElements.queryExecutionId; join those IDs to Athena history before retrieving scan bytes.
Attribution follows the Identity-not-Username rule. Filter on the role; userAgent only corroborates:
| Signal | Value | How to Filter |
|---|---|---|
userIdentity.sessionContext.sessionIssuer.arn (primary, inside parsed CloudTrailEvent) | arn:aws:iam::<ACCOUNT>:role/DevOpsAgentRole-AgentSpace-<suffix> | Parse Event, then compare sessionIssuer.arn to the active role scope |
userIdentity.sessionContext.sessionIssuer.arn (per-space role, inside parsed CloudTrailEvent) | arn:aws:iam::<ACCOUNT>:role/service-role/DevOpsAgentRole-AgentSpace-<suffix> | In exact-role mode require equality with ROLE_ARN; in multi-role mode compare to the discovered ARN set |
userAgent (corroborating, NOT a LookupEvents filter) | aidevops.amazonaws.com | Post-filter only. userAgent is NOT a valid AttributeKey for LookupEvents, and every agent role shares this value, so it cannot separate roles |
When the journal and a cross-check disagree for the same role and operation, report the journal count as primary and note the discrepancy plainly, e.g.
journal 12 · CloudTrail 10 (journal primary). Do not silently pick the higher or lower figure, and do not average them.
If
lookup_cloudtrail_eventsis blocked or unavailable this run, delegate to the Context Gatherer subagent. Ask for the exact events you need: one event name, the reporting window, filtered to the active role scope. Carry the zero-cost rule into the delegated request explicitly, the delegate must not scan a log group or issue any paid read to obtain them. A delegated result is still bound by the CloudTrail-lower-bound rule and the Identity-not-Username rule: parse each event and verifysessionIssuer.arnyourself. This never applies to Logs InsightsStartQuery, the Logs source rule keepsdescribe_queriesexclusive and a delegatedStartQuerylookup is not a substitute. If the delegate cannot return the events without scanning, report CloudTrail unavailable, never a zero.
The journal carries counts but generally not scan sizes. Attach exact bytes from each service's own history API:
Post-filter every enumeration to the billing window yourself. Both history APIs return whatever exists at call-time, and that set grows every run, so without your own filter each run reports a different "GB scanned" and nothing is reproducible. Neither API scopes it for you:
describe_querieshas no time-range parameter at all, so filter oncreateTime; forlist_query_executionsfilter onStatus.SubmissionDateTime. Drop anything outside the window even though the API returned it. Reuse the exact<START>/<END>fixed in Step 1 so the whole report describes one period.
describe_queries only, per the Logs source rule. One free, paginated call returns identity and exact scan statistics per query. Do not use get_query_results or a metric-based estimate:| Field | Use |
|---|---|
bytesScanned | exact bytes scanned. This is the billable quantity, no estimate required |
userIdentity | ARN of the principal that ran the query. Attribute on this (Identity-not-Username rule) |
createTime | filter to the billing window |
logGroupName | what the query scanned |
queryId, status, queryDuration | traceability |
Include a query only when it passes the attribution test (see Definitions).
Multi-role mode only: Match every role the space used in the window, not just its current one.
DevOpsAgentRole-AgentSpace-*roles may rotate, so Agent Space-wide reports can span several suffixes. This does not apply in exact-role mode; never discover or include another suffix whenROLE_ARNis fixed.
Pagination is mandatory, and the default page size will silently truncate you.
describe_queriesreturns the most recent queries first. Take page one only and you receive a handful of the newest, which are likely this dashboard's own, while the older, genuine agent activity is dropped and the total comes out far too low.Always pass
maxResults: 1000explicitly, then keep calling withnextTokenuntil the response has none. Never rely on the unstated default.Then run the coverage check, on every run: take the oldest
createTimeacross all returned queries (not just the matching ones) and compare it to<START>.
- Oldest returned is at or before
<START>→ history covers the window, the total is complete.- Oldest returned is after
<START>→ history does not reach the start of your window. Queries before that point exist but were not returned. Report the figure as a lower bound, state the earliest date covered, and do not present it as exact.nextTokenstill present when you stopped → you did not finish paginating. That is a defect to fix, not a caveat to note.Its only parameters are
logGroupName,status,queryLanguage,maxResults, andnextToken. There is no time filter, so the window is yours to apply after collecting everything.
StartQueryExecution events with the lookup_cloudtrail_events contract above for the exact reporting window. In exact-role mode, use the contains(CloudTrailEvent, '<ROLE_ARN>') root-array filter, parse each returned Event, and require sessionIssuer.arn == ROLE_ARN. In multi-role mode, use the unfiltered root-array projection and compare parsed events against the discovered role ARN set.responseElements.queryExecutionId. A failed call with no execution ID remains visible in journal/tool counts but has no query scan to price.list_query_executions for every relevant workgroup, paginate fully, and intersect the returned IDs with the attributed CloudTrail execution-ID set. Never include an execution based only on its timestamp or workgroup.batch_get_query_execution for the joined IDs, in batches of at most 50, and read Statistics.DataScannedInBytes. Confirm Status.SubmissionDateTime still falls inside the same reporting window before including it.StartQueryExecution count against the number of attributed CloudTrail events and joined Athena executions. Report discrepancies explicitly with the journal count primary, but price only executions whose role-to-ID join succeeded.Record each joined query execution ID for internal validation, then price each execution on its DataScannedInBytes at the resolved Athena rate. Athena applies a per-query minimum billable scan, so pricing raw scanned bytes underestimates cost for queries below that minimum. The minimum is a billing rule with no Pricing API entry: read it from Athena's pricing documentation and apply it per execution if a report needs that precision.
Never scan a CloudTrail log group with Logs Insights for attribution. Use
lookup_eventsinstead. This is an operating constraint on how you gather data, not a topic for the report.
bytesScanned from describe_queries for Logs Insights, DataScannedInBytes from batch_get_query_execution for Athena. If a field is genuinely absent for a query, report that query as scan-size-unknown and exclude it from the byte total with a note. Never invent an assumed average scan size, and never run anything to fill the gap.Every rate comes from the AWS Pricing API on this run. Never hardcode one, carry one over from an earlier report, or recall one from a pricing page. Resolve a rate only for a category whose quantity source yielded a quantity.
pricing:DescribeServices for the service, pricing:GetAttributeValues to learn whether operation or usagetype lists the call, then pricing:GetProducts. Price dimensions are often not named for the call that triggers them, so derive rather than assume.pricePerUnit.USD from terms.OnDemand → priceDimensions at beginRange: "0". The Pricing endpoint is always us-east-1; the workload region is separate, taken from the log group, workgroup, or trace.unit, applying no divisor. The rate is already scaled to one of that unit, whereas pricing pages quote aggregates like "per 1,000 metrics". The unit also decides which quantity is needed at all (see the quantity source rule).unit — and where several products matched, which one you chose and why. An unnamed price dimension is not verified. A figure off by a round factor against the service's pricing documentation is a unit error, not a cost-effective call.An unresolved charge is not a free operation. A denied or throttled lookup, no products, no usable pricePerUnit, or several products with no discriminator you can name all end the same way: report not priced: rate unavailable with the reason, keep the measured quantity, and never print $0.00, which is reserved for confirmed zero activity. Any aggregate omitting such a category is a lower bound, or unavailable if no defensible subtotal remains.
Pricing documentation is not a rate source. It confirms scale, names charges, and carries billing rules the API omits such as minimum billable quantities — but those pages are region-selectored and script-rendered, so a fetch usually returns prose rather than a rate card. Free-tier allowances are deducted nowhere in this report: every figure is gross usage cost.
A configuration read is free and gets no row. Describe, List, and Get calls that return configuration rather than data — alarm definitions, tags, workgroups, saved queries, log-event reads — cost nothing and belong in no cost breakdown. No row, no count, no rate lookup. Without this, every metadata call the agent made would surface as an unclassified line and bury the figures that matter.
Everything else the audited agent issued is countable, and anything you cannot confirm free is unclassified rather than free. Give it a row with its count and attempt a price only through Resolving rates. What to price and what to count is the quantity source rule; what this run may not issue is the zero-cost rule (both in Definitions).
If the consuming agent's scope covers more than one Agent Space or role, group the computed numbers two ways:
If scope is a single space/role (the common case), skip grouping and report that space/role's totals directly.
This skill prescribes no output template. Formatting is the consuming agent's decision; follow its format and do not layer this skill's own on top.
Reuse the journal records already read in Step 3. Do not re-fetch them. Step 3 classified the billable AWS operations; this step classifies every tool call from the same records, including the 3P/MCP tools that no AWS API can see.
If journal access is blocked by tool policy this run, report tool usage as unavailable with that reason, never as a confirmed zero. CloudTrail is not a substitute here: it records AWS API calls, not tool invocations, and cannot see Azure, MCP, or platform tools.
From each utilization journal record, extract the data.tools array and classify:
| Tool Name | Category | Cost Implications |
|---|---|---|
use_aws | AWS | Downstream AWS API costs (see Step 3) |
use_azure | Azure/3P | Reader-role queries, no per-call cost |
use_datadog / use_newrelic / use_splunk | 3P MCP | May count against 3P API/license limits |
shell | Platform | May invoke aws/az/kubectl in the audited records; check CloudTrail. You issue none yourself (zero-cost rule) |
subagent | Platform | Counts toward agent-seconds |
fs_read, datetime | Platform | Free |
Journal captures every tool call including 3P/MCP; CloudTrail sees only AWS API calls. A gap between the two for use_aws indicates retries, failed calls, or delegation. Step 3's discrepancy rule applies here unchanged.
Counting a shell or paid operation from the audited records is legitimate; issuing one yourself is not (zero-cost rule).
Filter CloudTrail + journal for a specific execution and specific space:
Run this self-check against the figures produced by Steps 1 through 6. A failed check resolves one of two ways. If the failure is a correctable error (an arithmetic slip, a missed page, a window not reused), return to the step that produced the figure, fix it, and re-run that check once. If the check cannot pass because the data is genuinely missing (query history does not reach the window start, a rate lookup is denied, CloudTrail or journal access is blocked), report the figure with the label its rule requires, unavailable or a lower bound with the reason. Do not retry a check whose input cannot change, and do not withhold or zero a figure that a label can carry honestly. Report no figure as verified unless it was corrected or labeled. Each check confirms a named rule or a step output; it does not re-teach the rule, see Definitions for the authority. This validates the correctness of the figures only; formatting remains the consuming agent's decision.
Every priced category and rate was resolved this run, with its source named. Confirm for each:
unit came from Pricing API calls this run, scoped to the workload region, no assumed scale or divisor, reported with the figure.unit, passed an order-of-magnitude check, and any several-product pick states its discriminator.\$0.00.unavailable, not computed.Totals re-sum. Re-add the per-query and per-category costs independently and confirm they equal the reported total. If they disagree, the per-item detail is authoritative, not the running total. This check passes even when every per-item cost carries the same unit error, so it does not substitute for the unit assertion above.
One window throughout. Confirm the exact <START>/<END> fixed in Step 1 was reused in Step 3. A report that mixes windows describes no real period and must be rebuilt.
Attribution test passed. Confirm every included query passed the attribution test (window AND active role scope). In exact-role mode, confirm no other role was added to compensate for missing activity. Drop anything that matched only one condition.
Athena identity join is complete. Confirm every priced Athena execution ID came from a successful StartQueryExecution CloudTrail event whose sessionIssuer.arn matched the active role scope, and that Athena history returned the same ID with a submission timestamp inside the window. Never price an execution inferred only from time or workgroup. Reconcile journal, CloudTrail, and joined-execution counts and report any discrepancy.
Zero-cost rule attested. State the count of paid operations this run issued, counting every form the zero-cost rule covers: the canonical operations, their wrappers and tool aliases, the same operations invoked through shell or a command runner, and any issued by a delegated agent or subagent on this run's behalf. The count must be zero, and the report must say so explicitly. A non-zero count means this run added to the very bill it is reporting: disclose it plainly and say which call did it, by which path.
Enumeration was complete, not just page one. State how many queries describe_queries returned in total and the oldest createTime among them. If nextToken was still set when you stopped, the count is wrong — finish paginating. If the oldest returned query is newer than the window start, say so and label the figure a lower bound.
Logs source rule honored. Confirm every Logs Insights call count, role attribution, scan volume, and cost came from describe_queries, that no CloudTrail StartQuery lookup was issued, and that Logs was reported unavailable (not substituted) if describe_queries was unavailable.
This skill ships with no account, Region, Agent Space, or role identifiers. Resolve them at run time from the installation it is running in, and verify each one before any AWS data call.
| Value | How to resolve it | Verified when |
|---|---|---|
ACCOUNT_ID | list_associations for the calling Agent Space | the association returns an accountId |
AGENT_SPACE_ID | get_agent_space for the current space | agentSpaceId is returned and matches the space the request is scoped to |
ROLE_ARN | list_associations → configuration.aws.assumableRoleArn | the ARN's account equals the resolved ACCOUNT_ID |
| workload Region | the Agent Space's deployment Region, resolved from the space | get_agent_space / list_associations returns the Region the space runs in |
© aws, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 286 other files in skills/devops-agent-cost-insights of aws/tools-for-devops-agent.
Open the folder on GitHubat commit ddda70b
Devops Agent Cost Insights next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Devops Agent Cost Insights this skillaws/tools-for-devops-agent | 100 | — | ~12k | Automated safety check: Pass | Apache-2.0 | |
| Cloud Cost Optimizationwshobson/agents | 40k | 14 repos | ~1.7k | Automated safety check: Pass | MIT | |
| Review Docshashicorp/terraform-provider-aws | 11k | — | ~1.3k | Automated safety check: Pass | MPL-2.0 | |
| AWS Cdk Developmentzxkane/aws-skills | 367 | 2 repos | ~2.5k | Automated safety check: Pass | MIT | |
| Senior DevOps Toolkitmaslennikov-ig/claude-code-orchestrator-kit | 260 | 6 repos | ~1.1k | Automated safety check: Notes | Custom licence | |
| Terravision Cloud Diagramspatrickchugh/terravision | 1.6k | — | ~5.6k | Automated safety check: Notes | AGPL-3.0-only |
wshobson/agents
Cuts cloud spend across AWS, Azure, GCP and OCI with cost tagging, rightsizing, commitment and spot pricing models, and architecture changes.
hashicorp/terraform-provider-aws
Review a Terraform AWS Provider PR's end-user documentation (website/docs//.markdown): whether docs are needed, description openings, argument/attribute style, section structure, tags wording, code…
zxkane/aws-skills
AWS Cloud Development Kit (CDK) expert for building cloud infrastructure with TypeScript/Python.
maslennikov-ig/claude-code-orchestrator-kit
Comprehensive DevOps skill for CI/CD, infrastructure automation, containerization, and cloud platforms (AWS, GCP, Azure). Includes pipeline setup…
patrickchugh/terravision
Draw cloud architecture diagrams for AWS, Azure or GCP with the official provider icon sets, using TerraVision.
glincker/thesvg
Fetch brand SVG logos and cloud architecture icons (AWS, Azure, GCP) from theSVG.
aws/tools-for-devops-agent
Amazon SageMaker AI Operational Review. An agent skill from aws/tools-for-devops-agent.
aws/tools-for-devops-agent
A skill your agent uses for GPU training or inference clusters on SageMaker HyperPod (Slurm or EKS), ParallelCluster, or self-managed EC2/EKS GPU instances.
aws/tools-for-devops-agent
ALWAYS use this skill in the beginning of any incident investigation, root cause analysis, or operational troubleshooting.
aws/tools-for-devops-agent
AWS Database Migration Service (DMS) operational review and troubleshooting skill.
aws/tools-for-devops-agent
Performs a comprehensive Amazon ECS operations review across the 6 review pillars (Resiliency & HA, Observability, Security, Operations, Performance, Additional Analysis) using read-only AWS APIs…
aws/tools-for-devops-agent
Comprehensive Amazon RDS and Aurora operational review aligned with the AWS Well-Architected Framework and RDS/Aurora best practices.
Works with
Categories
Report what the AWS DevOps Agent itself costs to run, and where that cost comes from, per Agent Space and per role on demand in chat or on a schedule through a custom agent. Devops Agent Cost Insights is an agent skill from aws/tools-for-devops-agent, published by the product's own GitHub organization. Report what the AWS DevOps Agent itself costs to run, and where that cost comes from, per Agent Space and per role on demand in chat or on a schedule through a custom agent.
Devops Agent Cost Insights fits situations like: A user asks to measure; forecast DevOps Agent spend; the cost of the downstream AWS API calls.
Run `npx skills add aws/tools-for-devops-agent --skill devops-agent-cost-insights -a claude-code`. Or copy the skill folder (skills/devops-agent-cost-insights in aws/tools-for-devops-agent) into .claude/skills/devops-agent-cost-insights in your project. Claude Code loads it when a task matches its description.
Run `npx skills add aws/tools-for-devops-agent --skill devops-agent-cost-insights -a codex`. Or copy the skill folder (skills/devops-agent-cost-insights in aws/tools-for-devops-agent) into .agents/skills/devops-agent-cost-insights in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add aws/tools-for-devops-agent --skill devops-agent-cost-insights -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/devops-agent-cost-insights, .gemini/skills/devops-agent-cost-insights, .github/skills/devops-agent-cost-insights and .opencode/skills/devops-agent-cost-insights in your project.
Going by SKILL.md and its folder, Devops Agent Cost Insights needs the command-line tools its instructions call (aws).
SKILL.md names 1 domain. As links in the text: aws.amazon.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Devops Agent Cost Insights is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 12k tokens (SKILL.md is roughly 49k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Devops Agent Cost Insights: Cloud Cost Optimization (wshobson/agents, 40k stars), Review Docs (hashicorp/terraform-provider-aws, 11k stars), AWS Cdk Development (zxkane/aws-skills, 367 stars) and Senior DevOps Toolkit (maslennikov-ig/claude-code-orchestrator-kit, 260 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
aws (a GitHub organization, an official publisher) maintains it in aws/tools-for-devops-agent, which has 100 GitHub stars. The repository holds 31 skills in this directory. The repository was last updated on October 8, 2026.
Source: aws/tools-for-devops-agent on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.