Agent Skillspydantic/genai-prices › add-price-model

add-price-model

GitHub

用于在genai-prices仓库中添加或更新LLM模型定价数据。涵盖多供应商价格搜集、OpenRouter探测、YAML编辑及PR构建,确保价格历史完整与数据准确发布。

.claude/skills/add-price-model/SKILL.md pydantic/genai-prices

Trigger Scenarios

添加新LLM模型定价 更新现有模型价格 同步多提供商(如AWS, OpenRouter)的价格快照

Install

npx skills add pydantic/genai-prices --skill add-price-model -g -y
More Options

Non-standard path

npx skills add https://github.com/pydantic/genai-prices/tree/main/.claude/skills/add-price-model -g -y

Use without installing

npx skills use pydantic/genai-prices@add-price-model

指定 Agent (Claude Code)

npx skills add pydantic/genai-prices --skill add-price-model -a claude-code -g -y

安装 repo 全部 skill

npx skills add pydantic/genai-prices --all -g -y

预览 repo 内 skill

npx skills add pydantic/genai-prices --list

SKILL.md

Frontmatter
{
    "name": "add-price-model",
    "description": "Add a new LLM model (or provider) to genai-prices pricing data, or change the price of one that is already there. Use when asked to add\/update pricing for a model — e.g. \"add grok 4.5\", \"add the new Claude\", \"update openai o5 prices\", \"provider X cut its prices\". Covers sourcing prices, probing OpenRouter for undocumented dated snapshot IDs, editing the provider YAML, preserving price history across a rate change, building, verifying resolution, and opening the PR."
}

Add a model to genai-prices

Never hand-edit generated data. Edit the provider YAML in prices/providers/<provider>.yml, then make build. The live published payload is prices/new_data/v2/data.json; prices/data.json and prices/data_slim.json are frozen v1 snapshots that no build step writes any more — leave them alone.

0. Scope: every provider that hosts this model, not just the one you were named

A model rarely lives on one provider. The big vendors' flagships are resold across clouds and aggregators, and each needs its own YAML entry — the same request "add the new Claude" means anthropic.yml and aws.yml (Bedrock) and google.yml (Vertex) and openrouter.yml. Adding only the direct-vendor entry is the most common miss (it's what happened for Opus 5 in #501, requiring the follow-up #502). Before editing, list every provider that hosts the model and cover them in one PR:

  • Direct vendoranthropic.yml, openai.yml, google.yml (Gemini), x_ai.yml, etc.
  • Aggregators/gatewaysopenrouter.yml (usually day-one; often exposes -fast/:beta variants).
  • Cloud resellersaws.yml (Bedrock: global.* + regional.* split, regional ~+10%), google.yml (Vertex Claude entries live here too, separate from Gemini), Azure (azure.yml is Azure OpenAI only — Claude on Foundry is out of scope there; note it, don't force it).

Confirm hosting from each provider's docs/model list; don't assume. If a reseller genuinely hasn't shipped it yet, that's the only reason to defer a provider — say which one and why in the PR, and follow up when it lands (see "Provider rollout timing" below). "I was only asked about provider X" is not a reason to skip the others.

1. Branch

Contribute via a branch on origin (this repo is pydantic/genai-prices, no fork). Always base off freshly-fetched upstream:

git fetch origin && git checkout -b <slug> origin/main

2. Source the prices (cite everything)

Get input / cached-input / output per-Mtok and context window from the provider's own docs first (authoritative). Vendor docs often omit the cache-read rate — cross-check OpenRouter's endpoint API, which exposes it:

https://openrouter.ai/api/v1/models/<provider>/<model>/endpoints

pricing.input_cache_read is per-token — ×1,000,000 for the per-Mtok value. Record every number's source; put them in the PR body.

3. Probe OpenRouter for the dated snapshot ID (do this every time)

Providers ship dated snapshot IDs (e.g. grok-4.5-20260708) that aren't in their docs. A real minimal request returns the resolved dated ID in the response model field — capture it so the YAML match covers future dated snapshots.

Key lives in ~/ai-coding-tools/.env as OPENROUTER_API_KEY. Don't reference secret env vars in an inline command (a hook blocks it and env-run rejects it) — put the request in a script that consumes the var internally, then run it with env-run:

# scratchpad/or_probe.sh consumes $OPENROUTER_API_KEY internally
~/.claude/scripts/env-run ~/ai-coding-tools/.env -- bash scratchpad/or_probe.sh
curl -sS https://openrouter.ai/api/v1/chat/completions \
  -H "Authorization: Bearer ${OPENROUTER_API_KEY}" -H "Content-Type: application/json" \
  -d '{"model":"<provider>/<model>","messages":[{"role":"user","content":"hi"}],"max_tokens":5}' \
  | jq '{id, model, provider}'

The model field (e.g. x-ai/grok-4.5-20260708) reveals the snapshot. A regex: '^<model>-\d{8}$' clause (plus a <provider>/-prefixed variant) makes it resolve without a separate entry.

4. Add the YAML entry

Match a sibling model's shape in prices/providers/<provider>.yml (ordering, match/or style, fields). Include:

  • match.or: bare id, regex: '^<id>-\d{8}$', <provider>/-prefixed bare + dated, -latest
  • context_window
  • prices_checked: today's date (check the currentDate system reminder)
  • prices: input_mtok, cache_read_mtok (omit if the provider has none), output_mtok

Add a price_comments field when a value needs explanation/reference.

Those three keys cover the common case. The full vocabulary is derived from prices/units.yml — check it when the model bills for anything else (reasoning or citation tokens, per-modality rates, 1h cache writes, web searches, requests). Not every key is per-Mtok: _kcount is per 1,000, _mchars per 1M characters, _hours per 3,600s, _gpixels per 1e9, _kpages per 1,000. A per-Mtok figure under a _kcount key is valid YAML and wrong by 1000×. Prices must also cover their ancestors — a model with cache_write_1h_mtok needs cache_write_mtok too; make build will tell you which key is missing.

Do not add a new unit to prices/units.yml to make a model fit. That widens the published v2 schema and is a v3 change — see AGENTS.md § "Adding a unit". Open an issue instead.

Migrate family-level -latest aliases when the new model is the current flagship. Two kinds of -latest alias coexist, and they behave differently:

  • version-specific (<id>-latest, e.g. grok-4.3-latest) — always stays on its own entry.
  • family-level / bare (<provider>-latest, e.g. grok-latest) — means "the current flagship" and should point at whichever model is newest/best right now.

When adding a new flagship, move the family-level alias off the previous flagship onto the new entry (add it here, delete it there). First verify which model the vendor's alias actually resolves to — check the provider docs and, if you can, hit the API and read the response model field — then match that. Don't assume; the aliasing scheme is provider-specific (some vendors have no bare-family alias at all).

4b. Changing the price of a model that already exists

A provider changing its rates is not an edit to the existing prices: block. Overwriting those values re-prices every request the library ever priced for that model, so a request from before the change gets billed at the new rate. That is what happened to GPT-5.6 Luna and Terra in #531, and #535 had to undo it.

Add a dated entry instead. Convert prices: from a mapping to a list of conditional entries:

prices:
  - prices: # the rates that were already there, unchanged and unconstrained
      input_mtok: 1
      output_mtok: 6
  - constraint:
      # https://developers.openai.com/api/docs/changelog
      start_date: 2026-07-30
    prices: # the new rates
      input_mtok: 0.2
      output_mtok: 1.2
  • Put the entry with no constraint first. Both engines scan the list backwards and take the first entry whose constraint is active, so an unconstrained entry placed last would always win.
  • Set start_date to the date the provider's new price took effect, not to today. Cite the changelog or announcement that states that date, in a YAML comment beside start_date.
  • Set prices_checked to today. It records when you verified the rates, which is a different fact from when the rates changed.
  • Append one entry to a model that already uses a list. Leave the existing entries alone.

Overwrite in place in exactly one case: the old value was wrong when it was written. A correction has no history worth preserving. State which of the two cases you are in, in the PR body.

Verify both sides of the boundary:

uv run python -c "
from datetime import datetime, timezone
from genai_prices import calc_price, Usage
u = Usage(input_tokens=1_000_000)
for day in [(2026, 7, 29), (2026, 7, 30)]:
    t = datetime(*day, tzinfo=timezone.utc)
    r = calc_price(u, '<id>', provider_id='<provider_id>', genai_request_timestamp=t)
    print(t.date(), '->', r.model_price.input_mtok, r.total_price)
"

Then pin both sides in tests/test_price_calc.py — one assertion the day before the change, one on the day of. A test that only covers the current rate passes just as well against an overwritten history, which is why #531 went green.

5. Build + verify resolution

Use make build, not just make build-prices. The installed genai_prices package (and the JS package) read their bundled data (packages/python/genai_prices/data.py, packages/js/src/data.ts). make build-prices writes only prices/new_data/v2/* and prices/providers/.schema.json — it does not touch the bundled data, so a calc_price check run after it verifies stale package data and can silently show the wrong result. make build runs build-prices + package-data + inject-providers.

make build    # build-prices + package-data + inject-providers

Confirm the base id, the dated snapshot, the provider-prefixed dated id, and any -latest alias you touched all resolve to the intended entry (include the previous flagship to prove its version-specific -latest didn't move):

uv run python -c "
from genai_prices import calc_price, Usage
u = Usage(input_tokens=1000, output_tokens=1000)
for m in ['<id>', '<id>-<YYYYMMDD>', '<provider>/<id>-<YYYYMMDD>', '<provider>-latest', '<prev-id>-latest']:
    r = calc_price(u, m, provider_id='<provider_id>')
    print(m, '->', r.model.id, r.model.prices.input_mtok, r.model.prices.output_mtok)
"

6. Commit, push, PR

The pre-commit build hook regenerates ten paths, so the first git commit will abort after it rewrites them; re-stage and commit again. Stage files explicitly — never git add -A (it leaks local/scratch files) — and never --no-verify, since that hook is what keeps the published data in sync with the YAML:

git add prices/providers/<provider>.yml \
        prices/providers/.schema.json \
        prices/new_data/v2/data.json prices/new_data/v2/data.schema.json \
        prices/new_data/v2/data_slim.json prices/new_data/v2/data_slim.schema.json \
        packages/python/genai_prices/data.py packages/python/genai_prices/data_units.py \
        packages/js/src/data.ts packages/js/src/dataUnits.ts \
        README.md
git commit -m "Add <Provider> <Model> pricing"   # re-run once if hooks rewrite files
git push -u origin <slug>
gh pr create --base main --title "Add <Provider> <Model> pricing" --body "..."

A plain price addition usually only dirties a subset of these — git status after the aborted commit tells you which. The schema and *_units files change only when prices/units.yml does, which a price addition should not do.

Never force-push. PR body: pricing table, sources (provider docs + OpenRouter for cache rate), and scope notes (e.g. single variant / no cache-write / any -latest alias you moved, each with its one-line reason).

After pushing, don't go idle — poll until CI is green and every reviewer comment (cubic included) is addressed or dismissed (see AGENTS.md). Unresolved review threads mean the PR isn't mergeable.

Provider rollout timing

This is the escape hatch for step 0, not a reason to default to a single-provider PR. Cover every provider that already hosts the model in the same PR. OpenRouter usually lists new models day-one. Only when a reseller (Bedrock / Vertex) genuinely hasn't shipped yet do you defer that provider — name it in the PR body and follow up in a later PR once it lands, rather than blocking the rest.

Version History

  • 1f01992 Current 2026-08-19 23:50

    新增要求覆盖所有托管该模型的供应商;明确v2数据构建流程,冻结v1快照文件;强调保留价格历史记录。

  • ffbbb14 2026-07-25 05:34

Same Skill Collection

.claude/skills/add-provider/SKILL.md

Metadata

Files
0
Version
5a49f30
Hash
3c3f309c
Indexed
2026-07-25 05:34

inicio - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-30 06:27
浙ICP备14020137号-1 $mapa de visitantes$