---
name: cloudcost
description: "Query multi-cloud billing costs (AWS, GCP, Alibaba) via FinOps Query Gateway. Use when user asks about cloud costs, spending, or account comparisons."
argument-hint: "[question or analysis command]"
---

# FinOps Query Gateway Skill

Query multi-cloud billing data (AWS, GCP, Alibaba Cloud) through the FinOps Query Gateway HTTP API. The Gateway handles SQL generation, access control, and cross-cloud merging automatically.

## Setup

### Gateway URL
The Gateway API is at `https://cloudcost-api.pingcap.net`.

### Token resolution order
1. `$FINOPS_GATEWAY_TOKEN` env var
2. `~/.config/finops/config.json` → `token` field

### Authentication
If no token is found or any API call returns 401, direct the user to:
https://cloudcost-api.pingcap.net/auth/login

## Core Rules

1. **NEVER query BigQuery directly** — all queries go through the Gateway API.
2. **NEVER generate raw SQL** — use `/v1/query/ask` or `/v1/query/analyses/:id` to get data.
3. **Prefer analysis templates** (`/v1/query/analyses/:id`) over free-form `/v1/query/ask` when a template matches the user's intent.
4. **Date floor: 2026-01-01** — billing data before this date is unavailable.
5. **All costs are in USD** — no currency conversion needed.
6. **`request_id` traceability** — every query response includes a `request_id`. Always include it in your answer so the user can reference it later.
7. **Use `preview` mode first** for expensive or exploratory queries to check SQL and estimated bytes before executing.

## Gateway API Endpoints

### `POST /v1/query/ask`

Natural-language question to cost data. The Gateway translates your question into SQL, executes it, and returns tabular results.

**Request body:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `question` | `string` | yes | Natural-language cost question (max 2000 chars) |
| `mode` | `'preview' \| 'execute'` | no | `preview` returns SQL + estimated bytes without running; `execute` (default) runs the query |
| `client_type` | `string` | no | Client identifier type (default: `'skill'`) |
| `client_name` | `string` | no | Client name (default: `'claude-code'`) |

**Example:**

```bash
curl -s -X POST "$FINOPS_GATEWAY_URL/v1/query/ask" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "AWS EC2 costs by region for February 2026",
    "mode": "execute",
    "client_type": "skill",
    "client_name": "claude-code"
  }'
```

**Response shape:**

```json
{
  "request_id": "qg_...",
  "semantic_query": { "source": "summary", "dimensions": [...], "metrics": [...], "filters": {...} },
  "shards": [{ "cloud": "aws", "location": "us-west2", "table": "...", "bytes_processed": "...", "row_count": 10 }],
  "answer_markdown": "...",
  "bytes_processed_total": "12345678",
  "row_count": 10,
  "rows": [...],
  "truncated": false,
  "applied_policy": { "date_floor": "2026-01-01", "authorized_account_count": 42 }
}
```

---

### `POST /v1/query/analyses/:analysisId`

Run a built-in analysis template. Templates are pre-validated queries with optional parameters — faster and more reliable than free-form questions.

**Request body:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `mode` | `'preview' \| 'execute'` | no | Same as `/v1/query/ask` |
| `params` | `Record<string,string>` | no | Template-specific parameters |
| `client_type` | `string` | no | Client identifier type (default: `'skill'`) |
| `client_name` | `string` | no | Client name (default: `'claude-code'`) |

**Example:**

```bash
curl -s -X POST "$FINOPS_GATEWAY_URL/v1/query/analyses/top_accounts_last_month" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "params": { "limit": "10" },
    "mode": "execute",
    "client_type": "skill",
    "client_name": "claude-code"
  }'
```

**Response shape:** Same as `/v1/query/ask`, plus `"analysis_id": "top_accounts_last_month"`.

---

### `GET /v1/catalog/semantic-schema`

Get the full schema catalog: available dimensions, metrics, sources, and analysis templates. No request body.

**Example:**

```bash
curl -s "$FINOPS_GATEWAY_URL/v1/catalog/semantic-schema" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN"
```

**Response includes:** `dimensions`, `metrics`, `sources`, `filters`, `analysis_templates`.

---

### `GET /v1/catalog/accounts`

List all cloud accounts the current user has access to. No request body.

**Example:**

```bash
curl -s "$FINOPS_GATEWAY_URL/v1/catalog/accounts" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN"
```

**Response shape:**

```json
{
  "accounts": [
    { "cloud_provider": "aws", "account_id": "123456789012", "account_display_name": "...", "account_purpose": "Development", "access_level": "public", "cost_center": "...", "account_owner": "..." }
  ],
  "total": 156
}
```

---

### `GET /v1/me/queries?limit=N&offset=N`

Retrieve the current user's recent query history.

**Query params:**

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `limit` | `number` | no | Number of queries to return (default 20, max 100) |
| `offset` | `number` | no | Pagination offset (default 0) |

**Example:**

```bash
curl -s "$FINOPS_GATEWAY_URL/v1/me/queries?limit=5" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN"
```

**Response shape:**

```json
{
  "queries": [
    { "id": "...", "request_id": "qg_...", "question": "...", "mode": "execute", "status": "completed", "bytes_processed_total": "12345", "row_count": 10, "started_at": "...", "finished_at": "...", "client_type": "skill", "client_name": "claude-code" }
  ],
  "total": 42,
  "limit": 5,
  "offset": 0
}
```

## Analysis Templates (Prefer These)

When the user's question matches a template, always use `/v1/query/analyses/:id` instead of `/v1/query/ask`. Templates are pre-validated, faster, and less error-prone.

| Template ID | Name | Params | Use When |
|------------|------|--------|----------|
| `cost_by_cloud_monthly` | Monthly Cost by Cloud | `months?: number` (default 3) | "Compare costs across clouds", "Multi-cloud spend" |
| `top_accounts_last_month` | Top Accounts Last Month | `limit?: number` (default 20) | "Which accounts cost the most", "Top spenders" |
| `top_services_last_month` | Top Services Last Month | `limit?: number` (default 20) | "Most expensive services", "Service breakdown" |
| `account_mom_change` | Account Month-over-Month Change | (none) | "Cost change by account", "Month-over-month comparison" |
| `prod_vs_dev_split` | Production vs Development Split | (none) | "Prod vs dev costs", "Cost by environment" |

All template params are passed as strings in the `params` object, e.g. `{ "months": "6" }`.

## Valid Dimensions & Metrics

### Summary Dimensions (source: `summary`)

```
billing_period_month, cloud_provider, region, service, service_category,
account_id, account_display_name, account_purpose, cost_center, account_owner,
tag_project
```

### Detail Dimensions (source: `detail`)

All summary dimensions, plus:

```
access_level, payer_account_id,
tag_environment, tag_service_type, tag_usedby, tag_component, tag_tenant, tag_cluster
```

### Metrics

| Metric | Description |
|--------|-------------|
| `unblended_cost_usd` | Default cost metric (pre-discount) |
| `usage_cost_usd` | Usage-based cost |
| `effective_cost_usd` | Cost after savings plans / reserved instances |
| `sp_covered_usage_cost_usd` | Cost covered by savings plans (AWS only, 0 for GCP/Alibaba) |

### Filters

Available filter parameters for `/v1/query/ask`:

```
date_from, date_to, clouds, account_ids, account_purpose,
services, regions, tag_project
```

## Example Questions

**1. "Compare AWS, GCP, and Alibaba costs for the last 3 months"**

```bash
curl -s -X POST "$FINOPS_GATEWAY_URL/v1/query/analyses/cost_by_cloud_monthly" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"client_type":"skill","client_name":"claude-code"}'
```

**2. "Which accounts spent the most last month?"**

```bash
curl -s -X POST "$FINOPS_GATEWAY_URL/v1/query/analyses/top_accounts_last_month" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"client_type":"skill","client_name":"claude-code"}'
```

**3. "What are the top 10 most expensive services?"**

```bash
curl -s -X POST "$FINOPS_GATEWAY_URL/v1/query/analyses/top_services_last_month" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"params":{"limit":"10"},"client_type":"skill","client_name":"claude-code"}'
```

**4. "How did account costs change month-over-month?"**

```bash
curl -s -X POST "$FINOPS_GATEWAY_URL/v1/query/analyses/account_mom_change" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"client_type":"skill","client_name":"claude-code"}'
```

**5. "What's the production vs development cost split?"**

```bash
curl -s -X POST "$FINOPS_GATEWAY_URL/v1/query/analyses/prod_vs_dev_split" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"client_type":"skill","client_name":"claude-code"}'
```

**6. "Show me AWS EC2 costs by region for February 2026"**

No template matches this specific filter combination — use free-form:

```bash
curl -s -X POST "$FINOPS_GATEWAY_URL/v1/query/ask" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"question":"AWS EC2 costs by region for February 2026","mode":"execute","client_type":"skill","client_name":"claude-code"}'
```

**7. "What accounts do I have access to?"**

```bash
curl -s "$FINOPS_GATEWAY_URL/v1/catalog/accounts" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN"
```

**8. "上个月三朵云的总费用分别是多少？"**

Chinese question asking for last month's total cost per cloud:

```bash
curl -s -X POST "$FINOPS_GATEWAY_URL/v1/query/analyses/cost_by_cloud_monthly" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"params":{"months":"1"},"client_type":"skill","client_name":"claude-code"}'
```

**9. "哪些账户花费最高？"**

Chinese question asking which accounts cost the most:

```bash
curl -s -X POST "$FINOPS_GATEWAY_URL/v1/query/analyses/top_accounts_last_month" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"client_type":"skill","client_name":"claude-code"}'
```

**10. "2026年2月按服务分类查看GCP成本"**

Chinese question asking for GCP cost by service for Feb 2026. No template matches the cloud + date filter:

```bash
curl -s -X POST "$FINOPS_GATEWAY_URL/v1/query/ask" \
  -H "Authorization: Bearer $FINOPS_GATEWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"question":"GCP cost by service for February 2026","mode":"execute","client_type":"skill","client_name":"claude-code"}'
```

## Gotchas

- **`sp_covered_usage_cost_usd` is AWS-only.** It is always 0 for GCP and Alibaba. Do not use it for cross-cloud comparisons.
- **Cross-cloud merging is automatic.** No need to query each cloud separately — the Gateway unions the data.
- **Use `rewrite_hint` from error responses.** When a query fails with `422 unsupported_query_shape`, the response includes a `rewrite_hint` explaining how to fix the query.
- **`preview` mode is free.** It returns the generated SQL and estimated bytes scanned without executing. Use it before large queries.
- **Tag dimensions (`tag_*`) require `detail` source.** Only `tag_project` is in `summary`; all other tags need the detail source.
- **GCP data lives in BigQuery `US` region, AWS/Alibaba in `us-west2`.** The Gateway handles cross-region routing automatically.
- **Maximum 1000 rows per response.** Add filters or aggregation to stay within this limit.
- **Date format is `YYYY-MM-DD`.** When specifying `date_from` / `date_to`, always use this format.
- **Questions can be in any language.** The Gateway's LLM layer handles multilingual input (English, Chinese, etc.).
