Python 88.3%
TypeScript 7.6%
Shell 4.1%
1#!/usr/bin/env python32"""Build the Anthropic models catalogue + pricing fragments and the models doc.34Inputs (offline): sources/anthropic/pages/** (facts transcribed below with their canonical URL),5 sources/anthropic/models-api-raw.json (GET /v1/models, sanitized),6 tmp-live/anthropic-models/summary.json (scripts/verify_anthropic_models.py output, optional).7Outputs: generated/fragments/models/anthropic-models.json8 generated/fragments/pricing/anthropic-pricing.json9 docs/models/anthropic-models.md10Re-run after refreshing the sources; the doc matrices are derived from the same records as the JSON.11"""12from __future__ import annotations1314import json15from pathlib import Path1617ROOT = Path(__file__).resolve().parents[1]18RAW = ROOT / "sources" / "anthropic" / "models-api-raw.json"19SUMMARY = ROOT / "tmp-live" / "anthropic-models" / "summary.json"20OUT_MODELS = ROOT / "generated" / "fragments" / "models" / "anthropic-models.json"21OUT_PRICING = ROOT / "generated" / "fragments" / "pricing" / "anthropic-pricing.json"22OUT_DOC = ROOT / "docs" / "models" / "anthropic-models.md"2324RETRIEVED = "2026-09-18"25LAST_VERIFIED = "2026-09-18"26D = "https://platform.claude.com/docs/en/"272829def src(*paths: str) -> list[dict]:30 return [{"url": D + p, "retrieved_at": RETRIEVED} for p in paths]313233# --------------------------------------------------------------------------------------------34# Static facts transcribed from the docs (models/<slug>/overview, pricing, deprecations, tool pages)35# --------------------------------------------------------------------------------------------36# generation buckets used by capability rules37GEN5 = {"claude-fable-5-1", "claude-mythos-5-1", "claude-fable-5", "claude-mythos-5", "claude-opus-5", "claude-sonnet-5"}38GEN47P = GEN5 | {"claude-opus-4-8", "claude-opus-4-7", "claude-mythos-preview"} # new tokenizer, sampling params rejected39GEN46P = GEN47P | {"claude-opus-4-6", "claude-sonnet-4-6"} # 1M default, inference_geo, compaction40GEN45 = {"claude-opus-4-5-20251101", "claude-sonnet-4-5-20250929", "claude-haiku-4-5-20251001"}41CURRENT = GEN46P | GEN4542TOOLSET_MODELS = {"claude-fable-5-1", "claude-mythos-5-1", "claude-fable-5", "claude-mythos-5", "claude-opus-5", "claude-sonnet-5", "claude-opus-4-8"}43COMPUTER_20251124 = TOOLSET_MODELS | {"claude-opus-4-7", "claude-opus-4-6", "claude-sonnet-4-6", "claude-opus-4-5-20251101"}44COMPUTER_20250124 = {"claude-sonnet-4-5-20250929", "claude-haiku-4-5-20251001", "claude-opus-4-1-20250805", "claude-sonnet-4-20250514", "claude-opus-4-20250514"}45TASK_BUDGET_MODELS = {"claude-fable-5-1", "claude-mythos-5-1", "claude-fable-5", "claude-mythos-5", "claude-opus-5", "claude-opus-4-8", "claude-opus-4-7"}46FAST_MODE_MODELS = {"claude-opus-5", "claude-opus-4-8"}47BATCH_300K = {"claude-opus-5", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-4-6", "claude-sonnet-5", "claude-sonnet-4-6"}48NO_PRIORITY_TIER = {"claude-fable-5-1", "claude-mythos-5-1", "claude-mythos-5", "claude-mythos-preview", "claude-opus-5", "claude-sonnet-5"}49MID_CONV_SYSTEM = {"claude-fable-5", "claude-mythos-5", "claude-opus-4-8", "claude-opus-5", "claude-fable-5-1", "claude-mythos-5-1"}50MID_CONV_TOOL_CHANGES = {"claude-fable-5", "claude-mythos-5", "claude-opus-4-8", "claude-opus-5"}51PER_MESSAGE_EFFORT = {"claude-fable-5-1", "claude-mythos-5-1", "claude-opus-5"}52ALWAYS_ON_THINKING = {"claude-fable-5-1", "claude-mythos-5-1", "claude-fable-5", "claude-mythos-5"}53PROGRESS_UPDATES = {"claude-fable-5-1", "claude-mythos-5-1", "claude-fable-5"}54RETENTION_30D = {"claude-fable-5-1", "claude-mythos-5-1", "claude-fable-5", "claude-mythos-5"}55CACHE_MIN = {"claude-fable-5-1": 512, "claude-mythos-5-1": 512, "claude-opus-5": 512, "claude-fable-5": 512, "claude-mythos-5": 512,56 "claude-mythos-preview": 2048, "claude-opus-4-7": 2048, "claude-opus-4-6": 4096, "claude-opus-4-5-20251101": 4096,57 "claude-opus-4-8": 1024, "claude-sonnet-5": 1024, "claude-sonnet-4-6": 1024, "claude-sonnet-4-5-20250929": 1024,58 "claude-opus-4-1-20250805": 1024, "claude-opus-4-20250514": 1024, "claude-sonnet-4-20250514": 1024,59 "claude-haiku-4-5-20251001": 4096, "claude-3-5-haiku-20241022": 2048}60TOOL_SYS_PROMPT_TOKENS = { # pricing page "Tool use system prompt token count": (auto/none, any/tool)61 "claude-opus-5": (286, 406), "claude-opus-4-8": (290, 410), "claude-opus-4-7": (675, 804), "claude-opus-4-6": (497, 589),62 "claude-opus-4-5-20251101": (496, 588), "claude-opus-4-1-20250805": (313, 315), "claude-opus-4-20250514": (313, 315),63 "claude-sonnet-5": (354, 474), "claude-sonnet-4-6": (497, 589), "claude-sonnet-4-5-20250929": (496, 588),64 "claude-sonnet-4-20250514": (313, 315), "claude-haiku-4-5-20251001": (496, 588), "claude-3-5-haiku-20241022": (264, 355)}65RATE_LIMIT_CLASS = {"claude-fable-5-1": "fable-5.x (shared Fable 5.1 + Fable 5)", "claude-fable-5": "fable-5.x (shared Fable 5.1 + Fable 5)",66 "claude-mythos-5-1": "mythos-5.x (shared Mythos 5.1 + Mythos 5; same terms as Fable)", "claude-mythos-5": "mythos-5.x (shared Mythos 5.1 + Mythos 5; same terms as Fable)",67 "claude-opus-5": "opus-5 (own bucket)", "claude-opus-4-8": "opus-4.x (shared 4.8/4.7/4.6/4.5)", "claude-opus-4-7": "opus-4.x (shared 4.8/4.7/4.6/4.5)",68 "claude-opus-4-6": "opus-4.x (shared 4.8/4.7/4.6/4.5)", "claude-opus-4-5-20251101": "opus-4.x (shared 4.8/4.7/4.6/4.5)",69 "claude-sonnet-5": "sonnet-5 (own bucket)", "claude-sonnet-4-6": "sonnet-4.x (shared 4.6/4.5)", "claude-sonnet-4-5-20250929": "sonnet-4.x (shared 4.6/4.5)",70 "claude-haiku-4-5-20251001": "haiku-4.5", "claude-3-5-haiku-20241022": "haiku-3.5 (retired on Claude API; counts cache reads toward ITPM)"}7172# id, display, family, generation, slug, released (docs), reliable cutoff, training cutoff, ctx, max_out, thinking, default effort,73# effort levels, retirement, bedrock ids, vertex, foundry, cp-aws, pricing (in,out,5m,1h,read), latency, lifecycle, alias74MODELS: list[dict] = [75 dict(id="claude-fable-5-1", display="Claude Fable 5.1", family="Fable", gen="5.1", slug="fable-5-1", released="2026-09-01",76 cutoff=("Jun 2026", "Jun 2026"), ctx=1_000_000, max_out=128_000, thinking="adaptive (always on)", effort_default="high",77 effort=["low", "medium", "high", "xhigh", "max"], retirement="not sooner than 2027-09-01",78 bedrock=["anthropic.claude-fable-5-1"], vertex="claude-fable-5-1", foundry="claude-fable-5-1", cpaws="claude-fable-5-1",79 price=(10, 50, 12.5, 20, 0.25), latency="Slower", lifecycle="Active (latest)", alias=None,80 desc="For demanding reasoning and long-horizon agentic work"),81 dict(id="claude-mythos-5-1", display="Claude Mythos 5.1", family="Mythos", gen="5.1", slug="mythos-5-1", released="2026-09-01",82 cutoff=("Jun 2026", "Jun 2026"), ctx=1_000_000, max_out=128_000, thinking="adaptive (always on)", effort_default="high",83 effort=["low", "medium", "high", "xhigh", "max"], retirement="not sooner than 2027-09-01",84 bedrock=["anthropic.claude-mythos-5-1"], vertex="claude-mythos-5-1", foundry="claude-mythos-5-1", cpaws=None,85 price=(10, 50, 12.5, 20, 0.25), latency="Slower", lifecycle="Active (invite only, Project Glasswing)", alias=None,86 desc="Invite-only frontier model (Project Glasswing)"),87 dict(id="claude-fable-5", display="Claude Fable 5", family="Fable", gen="5", slug="fable-5", released="2026-06-09",88 cutoff=("Jan 2026", "Jan 2026"), ctx=1_000_000, max_out=128_000, thinking="adaptive (always on)", effort_default="high",89 effort=["low", "medium", "high", "xhigh", "max"], retirement="not sooner than 2027-06-09",90 bedrock=["anthropic.claude-fable-5"], vertex="claude-fable-5", foundry="claude-fable-5", cpaws="claude-fable-5",91 price=(10, 50, 12.5, 20, 1.0), latency=None, lifecycle="Active (legacy)", alias=None,92 desc="Most capable widely released model at launch; access paused then restored 2026-07-01"),93 dict(id="claude-mythos-5", display="Claude Mythos 5", family="Mythos", gen="5", slug="mythos-5", released="2026-06-09",94 cutoff=("Jan 2026", "Jan 2026"), ctx=1_000_000, max_out=128_000, thinking="adaptive (always on)", effort_default="high",95 effort=["low", "medium", "high", "xhigh", "max"], retirement="not sooner than 2027-06-09",96 bedrock=["anthropic.claude-mythos-5"], vertex="claude-mythos-5", foundry="claude-mythos-5", cpaws=None,97 price=(10, 50, 12.5, 20, 1.0), latency=None, lifecycle="Active (invite only, Project Glasswing)", alias=None,98 desc="Invite-only frontier model (Project Glasswing)"),99 dict(id="claude-mythos-preview", display="Claude Mythos Preview", family="Mythos", gen="preview", slug=None, released="2026-04-07",100 cutoff=(None, None), ctx=1_000_000, max_out=128_000, thinking="adaptive", effort_default="high",101 effort=["low", "medium", "high", "max"], retirement="to be announced (deprecated 2026-06-09)",102 bedrock=["anthropic.claude-mythos-preview"], vertex=None, foundry=None, cpaws=None,103 price=None, latency=None, lifecycle="Deprecated (invite only)", alias=None,104 desc="Gated research preview for defensive cybersecurity (Project Glasswing); migrate to claude-mythos-5"),105 dict(id="claude-opus-5", display="Claude Opus 5", family="Opus", gen="5", slug="opus-5", released="2026-07-24",106 cutoff=("May 2026", "May 2026"), ctx=1_000_000, max_out=128_000, thinking="adaptive (on by default)", effort_default="high",107 effort=["low", "medium", "high", "xhigh", "max"], retirement="not sooner than 2027-07-24",108 bedrock=["anthropic.claude-opus-5"], vertex="claude-opus-5", foundry="claude-opus-5", cpaws="claude-opus-5",109 price=(5, 25, 6.25, 10, 0.5), latency="Moderate", lifecycle="Active (latest)", alias=None,110 desc="For complex agentic coding and enterprise work"),111 dict(id="claude-opus-4-8", display="Claude Opus 4.8", family="Opus", gen="4.8", slug="opus-4-8", released="2026-05-28",112 cutoff=("Jan 2026", "Jan 2026"), ctx=1_000_000, max_out=128_000, thinking="adaptive", effort_default="high",113 effort=["low", "medium", "high", "xhigh", "max"], retirement="not sooner than 2027-05-28",114 bedrock=["anthropic.claude-opus-4-8"], vertex="claude-opus-4-8", foundry="claude-opus-4-8", cpaws="claude-opus-4-8",115 price=(5, 25, 6.25, 10, 0.5), latency=None, lifecycle="Active (legacy)", alias=None, desc="Opus 4.x line; same tools/features as Opus 4.7"),116 dict(id="claude-opus-4-7", display="Claude Opus 4.7", family="Opus", gen="4.7", slug="opus-4-7", released="2026-04-16",117 cutoff=("Jan 2026", "Jan 2026"), ctx=1_000_000, max_out=128_000, thinking="adaptive", effort_default="high",118 effort=["low", "medium", "high", "xhigh", "max"], retirement="not sooner than 2027-04-16",119 bedrock=["anthropic.claude-opus-4-7"], vertex="claude-opus-4-7", foundry="claude-opus-4-7", cpaws="claude-opus-4-7",120 price=(5, 25, 6.25, 10, 0.5), latency=None, lifecycle="Active (legacy)", alias=None, desc="Introduced the new tokenizer (+~30% tokens), xhigh effort, high-res vision"),121 dict(id="claude-opus-4-6", display="Claude Opus 4.6", family="Opus", gen="4.6", slug="opus-4-6", released="2026-02-05",122 cutoff=("May 2025", "Aug 2025"), ctx=1_000_000, max_out=128_000, thinking="adaptive (manual extended deprecated)", effort_default="high",123 effort=["low", "medium", "high", "max"], retirement="not sooner than 2027-02-05",124 bedrock=["anthropic.claude-opus-4-6-v1"], vertex="claude-opus-4-6", foundry="claude-opus-4-6", cpaws="claude-opus-4-6",125 price=(5, 25, 6.25, 10, 0.5), latency=None, lifecycle="Active (legacy)", alias=None, desc="First dateless ID; last Bedrock ID with -v1 suffix"),126 dict(id="claude-opus-4-5-20251101", display="Claude Opus 4.5", family="Opus", gen="4.5", slug="opus-4-5", released="2025-11-24",127 cutoff=("May 2025", "Aug 2025"), ctx=200_000, max_out=64_000, thinking="extended (manual)", effort_default="high",128 effort=["low", "medium", "high"], retirement="not sooner than 2026-11-24",129 bedrock=["anthropic.claude-opus-4-5-20251101-v1:0"], vertex="claude-opus-4-5@20251101", foundry="claude-opus-4-5", cpaws="claude-opus-4-5",130 price=(5, 25, 6.25, 10, 0.5), latency=None, lifecycle="Active (legacy)", alias="claude-opus-4-5", desc="Last dated Opus snapshot"),131 dict(id="claude-sonnet-5", display="Claude Sonnet 5", family="Sonnet", gen="5", slug="sonnet-5", released="2026-06-30",132 cutoff=("Jan 2026", "Jan 2026"), ctx=1_000_000, max_out=128_000, thinking="adaptive (on by default)", effort_default="high",133 effort=["low", "medium", "high", "xhigh", "max"], retirement="not sooner than 2027-06-30",134 bedrock=["anthropic.claude-sonnet-5"], vertex="claude-sonnet-5", foundry="claude-sonnet-5", cpaws="claude-sonnet-5",135 price=(2, 10, 2.5, 4, 0.2), latency="Fast", lifecycle="Active (latest)", alias=None, desc="The best combination of speed and intelligence"),136 dict(id="claude-sonnet-4-6", display="Claude Sonnet 4.6", family="Sonnet", gen="4.6", slug="sonnet-4-6", released="2026-02-17",137 cutoff=("Aug 2025", "Jan 2026"), ctx=1_000_000, max_out=128_000, thinking="adaptive (manual extended deprecated)", effort_default="high",138 effort=["low", "medium", "high", "max"], retirement="not sooner than 2027-02-17",139 bedrock=["anthropic.claude-sonnet-4-6"], vertex="claude-sonnet-4-6", foundry="claude-sonnet-4-6", cpaws="claude-sonnet-4-6",140 price=(3, 15, 3.75, 6, 0.3), latency=None, lifecycle="Active (legacy)", alias=None, desc="First Sonnet with dateless ID"),141 dict(id="claude-sonnet-4-5-20250929", display="Claude Sonnet 4.5", family="Sonnet", gen="4.5", slug="sonnet-4-5", released="2025-09-29",142 cutoff=("Jan 2025", "Jul 2025"), ctx=200_000, max_out=64_000, thinking="extended (manual)", effort_default=None,143 effort=[], retirement="not sooner than 2026-09-29",144 bedrock=["anthropic.claude-sonnet-4-5-20250929-v1:0"], vertex="claude-sonnet-4-5@20250929", foundry="claude-sonnet-4-5", cpaws="claude-sonnet-4-5",145 price=(3, 15, 3.75, 6, 0.3), latency=None, lifecycle="Active (legacy)", alias="claude-sonnet-4-5", desc="1M context beta retired for this model on 2026-04-30"),146 dict(id="claude-haiku-4-5-20251001", display="Claude Haiku 4.5", family="Haiku", gen="4.5", slug="haiku-4-5", released="2025-10-15",147 cutoff=("Feb 2025", "Jul 2025"), ctx=200_000, max_out=64_000, thinking="extended (manual)", effort_default=None,148 effort=[], retirement="not sooner than 2026-10-15",149 bedrock=["anthropic.claude-haiku-4-5", "anthropic.claude-haiku-4-5-20251001-v1:0"], vertex="claude-haiku-4-5@20251001", foundry="claude-haiku-4-5", cpaws="claude-haiku-4-5",150 price=(1, 5, 1.25, 2, 0.1), latency="Fastest", lifecycle="Active (latest)", alias="claude-haiku-4-5", desc="The fastest model with near-frontier intelligence"),151]152153# Retired / legacy models (deprecations page + release notes). pricing only where the current pricing page still lists it.154LEGACY: list[dict] = [155 dict(id="claude-opus-4-1-20250805", display="Claude Opus 4.1", family="Opus", gen="4.1", released="2025-08-05", deprecated="2026-06-05", retired="2026-08-05",156 replacement="claude-opus-4-8", price=(15, 75, 18.75, 30, 1.5), ctx=200_000, max_out=32_000, alias="claude-opus-4-1",157 bedrock=["anthropic.claude-opus-4-1-20250805-v1:0"], vertex="claude-opus-4-1@20250805", cloud_note="retired on Claude API; still listed (deprecated) on Bedrock and Google Cloud"),158 dict(id="claude-opus-4-20250514", display="Claude Opus 4", family="Opus", gen="4", released="2025-05-22", deprecated="2026-04-14", retired="2026-06-15",159 replacement="claude-opus-4-8", price=(15, 75, 18.75, 30, 1.5), ctx=200_000, max_out=32_000, alias="claude-opus-4-0",160 bedrock=["anthropic.claude-opus-4-20250514-v1:0"], vertex="claude-opus-4@20250514", cloud_note="retired on Claude API and Bedrock; still listed (deprecated) on Google Cloud"),161 dict(id="claude-sonnet-4-20250514", display="Claude Sonnet 4", family="Sonnet", gen="4", released="2025-05-22", deprecated="2026-04-14", retired="2026-06-15",162 replacement="claude-sonnet-4-6", price=(3, 15, 3.75, 6, 0.3), ctx=200_000, max_out=64_000, alias="claude-sonnet-4-0",163 bedrock=["anthropic.claude-sonnet-4-20250514-v1:0"], vertex="claude-sonnet-4@20250514", cloud_note="retired on Claude API; still listed (deprecated) on Bedrock and Google Cloud; 1M context beta retired 2026-04-30"),164 dict(id="claude-3-7-sonnet-20250219", display="Claude Sonnet 3.7", family="Sonnet", gen="3.7", released="2025-02-24", deprecated="2025-10-28", retired="2026-02-19",165 replacement="claude-sonnet-4-6", price=None, ctx=200_000, max_out=None, alias="claude-3-7-sonnet-latest",166 bedrock=["anthropic.claude-3-7-sonnet-20250219-v1:0"], vertex=None, cloud_note="retired everywhere per Bedrock table"),167 dict(id="claude-3-5-haiku-20241022", display="Claude Haiku 3.5", family="Haiku", gen="3.5", released="2024-11-04", deprecated="2025-12-19", retired="2026-02-19",168 replacement="claude-haiku-4-5-20251001", price=(0.8, 4, 1.0, 1.6, 0.08), ctx=200_000, max_out=None, alias="claude-3-5-haiku-latest",169 bedrock=["anthropic.claude-3-5-haiku-20241022-v1:0"], vertex="claude-3-5-haiku@20241022", cloud_note="retired on Claude API; still listed (deprecated) on Bedrock and Google Cloud; counts cache reads toward ITPM"),170 dict(id="claude-3-haiku-20240307", display="Claude Haiku 3", family="Haiku", gen="3", released="2024-03-07", deprecated="2026-02-19", retired="2026-04-20",171 replacement="claude-haiku-4-5-20251001", price=None, ctx=200_000, max_out=None, alias=None, bedrock=None, vertex=None, cloud_note=None),172 dict(id="claude-3-5-sonnet-20241022", display="Claude Sonnet 3.5 (Oct 2024)", family="Sonnet", gen="3.5", released="2024-10-22", deprecated="2025-08-13", retired="2025-10-28",173 replacement="claude-sonnet-4-6", price=None, ctx=200_000, max_out=None, alias="claude-3-5-sonnet-latest", bedrock=None, vertex=None, cloud_note=None),174 dict(id="claude-3-5-sonnet-20240620", display="Claude Sonnet 3.5 (Jun 2024)", family="Sonnet", gen="3.5", released="2024-06-20", deprecated="2025-08-13", retired="2025-10-28",175 replacement="claude-sonnet-4-6", price=None, ctx=200_000, max_out=None, alias=None, bedrock=None, vertex=None, cloud_note=None),176 dict(id="claude-3-opus-20240229", display="Claude Opus 3", family="Opus", gen="3", released="2024-02-29", deprecated="2025-06-30", retired="2026-01-05",177 replacement="claude-opus-4-8", price=None, ctx=200_000, max_out=None, alias="claude-3-opus-latest", bedrock=None, vertex=None, cloud_note="researchers may request access via External Researcher Access Program"),178 dict(id="claude-3-sonnet-20240229", display="Claude Sonnet 3", family="Sonnet", gen="3", released="2024-02-29", deprecated="2025-01-21", retired="2025-07-21",179 replacement="claude-sonnet-4-6", price=None, ctx=200_000, max_out=None, alias=None, bedrock=None, vertex=None, cloud_note=None),180 dict(id="claude-2.1", display="Claude 2.1", family="Claude 2", gen="2.1", released=None, deprecated="2025-01-21", retired="2025-07-21", replacement="claude-opus-4-8", price=None, ctx=200_000, max_out=None, alias=None, bedrock=None, vertex=None, cloud_note=None),181 dict(id="claude-2.0", display="Claude 2.0", family="Claude 2", gen="2.0", released=None, deprecated="2025-01-21", retired="2025-07-21", replacement="claude-opus-4-8", price=None, ctx=None, max_out=None, alias=None, bedrock=None, vertex=None, cloud_note=None),182] + [dict(id=i, display=i, family="Claude 1 / Instant", gen=i.split("-")[-1], released=None, deprecated="2024-09-04", retired="2024-11-06", replacement="claude-haiku-4-5-20251001",183 price=None, ctx=None, max_out=None, alias=None, bedrock=None, vertex=None, cloud_note=None)184 for i in ["claude-1.0", "claude-1.1", "claude-1.2", "claude-1.3", "claude-instant-1.0", "claude-instant-1.1", "claude-instant-1.2"]]185186187def load_live() -> tuple[dict[str, dict], dict]:188 live = {m["id"]: m for m in json.loads(RAW.read_text())["data"]} if RAW.exists() else {}189 summary = json.loads(SUMMARY.read_text()) if SUMMARY.exists() else {}190 return live, summary191192193def cap(v: bool | str | None) -> bool | str:194 return "unknown" if v is None else v195196197def capabilities(m: dict, live: dict | None) -> dict:198 i = m["id"]199 lc = (live or {}).get("capabilities") or {}200 eff = lc.get("effort", {})201 th = lc.get("thinking", {}).get("types", {})202 cm = lc.get("context_management", {})203 haiku = i == "claude-haiku-4-5-20251001"204 c = {205 "text_input": True, "vision": True, "pdf_input": cap(lc.get("pdf_input", {}).get("supported")) if lc else True,206 "high_resolution_vision_2576px": i in GEN47P,207 "tool_use": True, "parallel_tool_use": True,208 "tool_choice_any_or_tool": i not in {"claude-fable-5-1", "claude-mythos-5-1"},209 "strict_tool_use": True, "structured_outputs_json": cap(lc.get("structured_outputs", {}).get("supported")) if lc else (i in GEN46P | GEN45),210 "fine_grained_tool_streaming": True,211 "thinking_extended_manual_budget": cap(th.get("enabled", {}).get("supported")) if lc else (i in GEN45 or i in {"claude-opus-4-6", "claude-sonnet-4-6"}),212 "thinking_adaptive": cap(th.get("adaptive", {}).get("supported")) if lc else (i in GEN46P),213 "thinking_always_on": i in ALWAYS_ON_THINKING,214 "thinking_on_by_default": i in GEN5,215 "thinking_can_be_disabled": (i not in ALWAYS_ON_THINKING) if i in CURRENT else "unknown",216 "interleaved_thinking": False if haiku else (True if i in GEN46P else "beta header interleaved-thinking-2025-05-14 with manual thinking"),217 "thinking_display_omitted_default": i in GEN47P,218 "progress_updates_between_tool_calls": i in PROGRESS_UPDATES,219 "effort_parameter": cap(eff.get("supported")) if lc else bool(m.get("effort")),220 "effort_levels": [lv for lv in ["low", "medium", "high", "xhigh", "max"] if eff.get(lv, {}).get("supported")] if lc else list(m.get("effort") or []),221 "effort_default": m.get("effort_default"),222 "per_message_effort_beta": i in PER_MESSAGE_EFFORT,223 "fast_mode_speed_fast": i in FAST_MODE_MODELS,224 "prompt_caching": True, "prompt_caching_1h_ttl": True, "automatic_caching_top_level_cache_control": True,225 "min_cacheable_tokens": CACHE_MIN.get(i),226 "batch_api": cap(lc.get("batch", {}).get("supported")) if lc else True,227 "batch_extended_output_300k_beta": i in BATCH_300K,228 "citations": cap(lc.get("citations", {}).get("supported")) if lc else True,229 "files_api": True,230 "web_search": True, "web_search_dynamic_filtering": i in GEN46P, "web_fetch": True, "web_fetch_dynamic_filtering": i in GEN46P,231 "code_execution": cap(lc.get("code_execution", {}).get("supported")) if lc else (i in CURRENT),232 "code_execution_docs": i in CURRENT,233 "programmatic_tool_calling": i in CURRENT and not haiku,234 "computer_use": i in (TOOLSET_MODELS | COMPUTER_20251124 | COMPUTER_20250124),235 "computer_use_toolset_ga": i in TOOLSET_MODELS,236 "browser_use": i in TOOLSET_MODELS,237 "memory_tool": True, "text_editor_tool": True, "bash_tool": True,238 "tool_search": i in CURRENT, "advisor_tool": i in CURRENT and i != "claude-mythos-preview",239 "mcp_connector": True, "agent_skills": i in CURRENT,240 "context_editing_clear_tool_uses": cap(cm.get("clear_tool_uses_20250919", {}).get("supported")) if lc else True,241 "context_editing_clear_thinking": cap(cm.get("clear_thinking_20251015", {}).get("supported")) if lc else True,242 "compaction_server_side": cap(cm.get("compact_20260112", {}).get("supported")) if lc else (i in GEN46P),243 "compact_on_demand_beta": i in GEN46P,244 "context_1m_default_no_beta": i in GEN46P,245 "inference_geo_data_residency": i in GEN46P,246 "mid_conversation_system_messages": i in MID_CONV_SYSTEM,247 "mid_conversation_tool_changes_beta": i in MID_CONV_TOOL_CHANGES,248 "task_budgets_beta": i in TASK_BUDGET_MODELS,249 "sampling_params_temperature_top_p_top_k": "rejected with 400 when non-default" if i in GEN47P else "accepted (incompatible with thinking on)",250 "assistant_prefill": False if (i in ALWAYS_ON_THINKING or i == "claude-opus-4-6" or i in GEN5) else "unknown",251 "priority_tier": i not in NO_PRIORITY_TIER,252 "zero_data_retention_eligible": (i not in RETENTION_30D) if i in CURRENT else "unknown",253 "tokenizer": "new tokenizer (Claude 4.7+, ~30% more tokens)" if i in GEN47P else "previous tokenizer",254 "multilingual": True,255 "latency_class": m.get("latency"),256 "output_modalities": ["text"],257 }258 return c259260261def tools_for(m: dict) -> list[dict]:262 i = m["id"]263 t: list[dict] = []264265 def add(type_: str, category: str, beta: str | None = None, note: str | None = None):266 d = {"type": type_, "category": category, "beta_header": beta}267 if note:268 d["note"] = note269 t.append(d)270271 for v in ["web_search_20260318", "web_search_20260209", "web_search_20250305"]:272 if v == "web_search_20250305" or i in GEN46P:273 add(v, "server", None, None if v == "web_search_20250305" else "dynamic filtering (code execution) on 4.6+")274 for v in ["web_fetch_20260318", "web_fetch_20260309", "web_fetch_20260209", "web_fetch_20250910"]:275 if v == "web_fetch_20250910" or i in GEN46P:276 add(v, "server")277 if i in CURRENT:278 for v in ["code_execution_20260521", "code_execution_20260120", "code_execution_20250825"]:279 add(v, "server", None, "Haiku 4.5: no programmatic tool calling / REPL persistence" if i == "claude-haiku-4-5-20251001" and v != "code_execution_20250825" else None)280 add("tool_search_tool_regex_20251119", "server"); add("tool_search_tool_bm25_20251119", "server")281 if i != "claude-mythos-preview":282 add("advisor_20260301", "server", "advisor-tool-2026-03-01")283 add("mcp_toolset", "mcp", "mcp-client-2025-11-20")284 add("memory_20250818", "client")285 add("bash_20250124", "client")286 add("text_editor_20250728", "client")287 if i in TOOLSET_MODELS:288 add("computer_toolset_20260801", "client"); add("browser_toolset_20260801", "client")289 if i in COMPUTER_20251124:290 add("computer_20251124", "client", "computer-use-2025-11-24")291 if i in COMPUTER_20250124:292 add("computer_20250124", "client", "computer-use-2025-01-24")293 return t294295296def pricing_block(p: tuple | None, i: str) -> dict | None:297 if not p:298 return None299 inp, out, w5, w1, rd = p300 d = {"currency": "USD", "unit": "per 1M tokens", "input": inp, "output": out, "cache_write_5m": w5, "cache_write_1h": w1, "cache_read": rd,301 "batch_input": round(inp / 2, 4), "batch_output": round(out / 2, 4), "batch_discount": 0.5,302 "long_context_over_200k": "standard pricing (no premium) for 1M-context models" if i in GEN46P else "n/a (200k context)",303 "inference_geo_us_multiplier": 1.1 if i in GEN46P else None,304 "priority_tier": "same token prices; capacity commitment, no longer sold" if i not in NO_PRIORITY_TIER else "not supported",305 "cache_read_multiplier": round(rd / inp, 4)}306 if i in FAST_MODE_MODELS:307 d["fast_mode"] = {"input": 10, "output": 50, "note": "speed: fast, research preview, Claude API only; caching/data-residency multipliers stack; not on Batch"}308 if i in TOOL_SYS_PROMPT_TOKENS:309 a, b = TOOL_SYS_PROMPT_TOKENS[i]310 d["tool_use_system_prompt_tokens"] = {"auto_or_none": a, "any_or_tool": b}311 return d312313314def build() -> tuple[list[dict], list[dict]]:315 live, summary = load_live()316 get_model = summary.get("get_model", {})317 msgs = summary.get("messages", {})318 verified_ts = summary.get("retrieved_at", LAST_VERIFIED)319 records: list[dict] = []320321 for m in MODELS:322 i = m["id"]323 lv = live.get(i)324 gm = get_model.get(i, {})325 status: list[str] = ["DOCUMENTED"]326 if lv:327 status.append("LIVE_VERIFIED")328 elif gm.get("status") == 404:329 status.append("ACCOUNT_RESTRICTED")330 if m["lifecycle"].startswith("Deprecated"):331 status.append("DEPRECATED")332 if "legacy" in m["lifecycle"]:333 status.append("LEGACY")334 if "invite" in m["lifecycle"] or i == "claude-mythos-preview":335 status.append("PREVIEW")336 ver = {"method": "live_api" if (lv or gm) else "docs_only", "verified_at": verified_ts,337 "result": "success" if lv else ("restricted" if gm.get("status") == 404 else "n/a"),338 "http_status": gm.get("status"), "request_note": f"GET /v1/models/{i}" + (f" -> {gm.get('status')}" if gm else " (not probed)")}339 if i in msgs:340 ver["messages_probe"] = {"http_status": msgs[i]["status"], "usage": msgs[i]["body"].get("usage"), "stop_reason": msgs[i]["body"].get("stop_reason")}341 discrepancies = []342 if lv:343 if lv["created_at"][:10] != m["released"]:344 discrepancies.append(f"live created_at {lv['created_at'][:10]} != documented release {m['released']}")345 if lv.get("max_input_tokens") != m["ctx"]:346 discrepancies.append(f"live max_input_tokens {lv.get('max_input_tokens')} != documented context window {m['ctx']}")347 if lv.get("max_tokens") != m["max_out"]:348 discrepancies.append(f"live max_tokens {lv.get('max_tokens')} != documented max output {m['max_out']}")349 if i == "claude-haiku-4-5-20251001" and not lv["capabilities"]["code_execution"]["supported"]:350 discrepancies.append("live capabilities.code_execution.supported=false while code-execution-tool docs list claude-haiku-4-5-20251001 as supported (without PTC/REPL persistence)")351 rec = {352 "provider": "anthropic", "id": i, "display_name": m["display"], "kind": "snapshot",353 "aliases": [m["alias"]] if m["alias"] else [], "snapshots": [i], "family": m["family"], "generation": m["gen"],354 "description": m["desc"], "status": status, "lifecycle_docs": m["lifecycle"],355 "release_date": m["released"], "created_at_live": lv["created_at"] if lv else None,356 "knowledge_cutoff": {"reliable": m["cutoff"][0], "training_data": m["cutoff"][1]},357 "context_window": m["ctx"], "context_window_note": "1M default, no beta header, standard pricing" if i in GEN46P else "200k",358 "max_output": m["max_out"], "max_output_batch_beta": 300_000 if i in BATCH_300K else None,359 "live_max_input_tokens": lv.get("max_input_tokens") if lv else None, "live_max_tokens": lv.get("max_tokens") if lv else None,360 "modalities": {"input": ["text", "image", "pdf"], "output": ["text"]},361 "thinking": m["thinking"],362 "capabilities": capabilities(m, lv), "live_capabilities": lv.get("capabilities") if lv else None,363 "tools": tools_for(m),364 "endpoints": ["POST /v1/messages", "POST /v1/messages/count_tokens", "POST /v1/messages/batches", "GET /v1/models/{model_id}"]365 + (["Managed Agents (/v1/agents, /v1/sessions) — see managed-agents docs for per-model support"] if i in CURRENT else []),366 "pricing": pricing_block(m["price"], i),367 "rate_limits": {"class": RATE_LIMIT_CLASS.get(i), "ref": "generated/fragments/rate-limits/anthropic-rate-limits.json", "doc": D + "api/rate-limits"},368 "beta_headers": sorted({t["beta_header"] for t in tools_for(m) if t["beta_header"]} | ({"fast-mode-2026-02-01"} if i in FAST_MODE_MODELS else set())369 | ({"output-300k-2026-03-24"} if i in BATCH_300K else set()) | ({"task-budgets-2026-03-13"} if i in TASK_BUDGET_MODELS else set())370 | ({"compact-2026-01-12", "compact-2026-09-04"} if i in GEN46P else set()) | ({"mid-conversation-output-config-2026-07-01"} if i in PER_MESSAGE_EFFORT else set())371 | ({"mid-conversation-tool-changes-2026-07-01"} if i in MID_CONV_TOOL_CHANGES else set()) | ({"thinking-display-updates-2026-08-18"} if i in PROGRESS_UPDATES else set())372 | ({"interleaved-thinking-2025-05-14"} if i in GEN45 and i != "claude-haiku-4-5-20251001" else set())),373 "restrictions": {"data_retention": "30-day retention required; not available under ZDR unless authorized" if i in RETENTION_30D else None,374 "access": "invite only (Project Glasswing)" if m["family"] == "Mythos" else None,375 "tool_choice": "any/tool return 400" if i in {"claude-fable-5-1", "claude-mythos-5-1"} else None,376 "thinking_disable": "not supported" if i in ALWAYS_ON_THINKING else ("only at effort high or below (400 at xhigh/max)" if i == "claude-opus-5" else None)},377 "availability": {"account": "available" if lv else ("not visible to our key (404)" if gm.get("status") == 404 else "unknown"),378 "platforms": ["Claude API"] + (["Amazon Bedrock"] if m["bedrock"] else []) + (["Google Cloud (Vertex AI)"] if m["vertex"] else [])379 + (["Microsoft Foundry"] if m["foundry"] else []) + (["Claude Platform on AWS"] if m["cpaws"] else []),380 "cloud_ids": {"bedrock": m["bedrock"], "vertex": m["vertex"], "foundry": m["foundry"], "claude_platform_on_aws": m["cpaws"]},381 "regions": "Claude API is global by default; inference_geo us/global on 4.6+; Bedrock/Vertex regional endpoints +10%"},382 "deprecation": {"state": m["lifecycle"], "deprecated_on": "2026-06-09" if i == "claude-mythos-preview" else None, "retirement": m["retirement"],383 "replacement": "claude-mythos-5" if i == "claude-mythos-preview" else None},384 "discrepancies_live_vs_docs": discrepancies,385 "last_verified": LAST_VERIFIED, "verification": ver,386 "sources": src("models/overview", f"models/{m['slug']}/overview" if m["slug"] else "about-claude/model-deprecations", "about-claude/pricing",387 "about-claude/model-deprecations", "api/models/list", "build-with-claude/thinking", "build-with-claude/effort",388 "agents-and-tools/tool-use/tool-reference", "build-with-claude/prompt-caching", "build-with-claude/context-windows"),389 }390 records.append(rec)391 # alias record392 if m["alias"]:393 ga = get_model.get(m["alias"], {})394 records.append({395 "provider": "anthropic", "id": m["alias"], "display_name": m["display"] + " (alias)", "kind": "alias", "resolves_to": i,396 "aliases": [], "snapshots": [i], "family": m["family"], "generation": m["gen"],397 "description": f"Convenience alias; GET /v1/models/{m['alias']} resolves to {i}. Aliases exist only for pre-4.6 models.",398 "status": ["DOCUMENTED"] + (["LIVE_VERIFIED"] if ga.get("status") == 200 else []),399 "release_date": m["released"], "context_window": m["ctx"], "max_output": m["max_out"], "pricing": "same as " + i,400 "endpoints": ["POST /v1/messages", "GET /v1/models/{model_id}"],401 "last_verified": LAST_VERIFIED,402 "verification": {"method": "live_api", "verified_at": verified_ts, "result": "success" if ga.get("status") == 200 else "n/a",403 "http_status": ga.get("status"), "request_note": f"GET /v1/models/{m['alias']} -> id {ga.get('resolved_id')}"},404 "sources": src("about-claude/models/model-ids-and-versions", f"models/{m['slug']}/overview"),405 })406407 for m in LEGACY:408 i = m["id"]409 gm = get_model.get(i, {})410 status = ["DOCUMENTED", "RETIRED"]411 if gm.get("status") == 404:412 status.append("LIVE_VERIFIED") # retirement verified: 404 not_found_error413 records.append({414 "provider": "anthropic", "id": i, "display_name": m["display"], "kind": "snapshot", "aliases": [m["alias"]] if m.get("alias") else [], "snapshots": [i],415 "family": m["family"], "generation": m["gen"], "status": status, "lifecycle_docs": "Retired",416 "release_date": m["released"], "knowledge_cutoff": None, "context_window": m["ctx"], "max_output": m["max_out"],417 "modalities": {"input": ["text", "image"] if not i.startswith("claude-2") and not i.startswith("claude-1") and not i.startswith("claude-instant") else ["text"], "output": ["text"]},418 "capabilities": {"note": "retired; capability matrix not maintained in current docs", "computer_use_computer_20250124": i in COMPUTER_20250124,419 "min_cacheable_tokens": CACHE_MIN.get(i)},420 "tools": [{"type": "computer_20250124", "category": "client", "beta_header": "computer-use-2025-01-24"}] if i in COMPUTER_20250124 else [],421 "endpoints": [], "pricing": pricing_block(m["price"], i),422 "pricing_note": None if m["price"] else "not listed on the current pricing page",423 "availability": {"account": "retired on Claude API (404 not_found_error)" if gm.get("status") == 404 else "retired (not probed)",424 "cloud_ids": {"bedrock": m.get("bedrock"), "vertex": m.get("vertex")}, "cloud_note": m.get("cloud_note")},425 "deprecation": {"state": "Retired", "deprecated_on": m["deprecated"], "retired_on": m["retired"], "replacement": m["replacement"]},426 "last_verified": LAST_VERIFIED,427 "verification": {"method": "live_api" if gm else "docs_only", "verified_at": verified_ts, "result": "success" if gm.get("status") == 404 else "n/a",428 "http_status": gm.get("status"), "request_note": f"GET /v1/models/{i} -> {gm.get('status')} {json.dumps(gm.get('body'))[:120]}" if gm else "not probed"},429 "sources": src("about-claude/model-deprecations", "about-claude/pricing", "release-notes/overview"),430 })431432 # ---------------- pricing records ----------------433 prices: list[dict] = []434435 def price(model_or_service, dimension, value, unit, tier="standard", notes=None, source="about-claude/pricing"):436 prices.append({"provider": "anthropic", "model_or_service": model_or_service, "dimension": dimension, "price": value, "currency": "USD",437 "unit": unit, "tier": tier, "effective_notes": notes, "source": D + source, "retrieved_at": RETRIEVED})438439 for m in MODELS + LEGACY:440 if not m.get("price"):441 continue442 inp, out, w5, w1, rd = m["price"]443 note = None444 if m["id"] in {x["id"] for x in LEGACY}:445 note = "retired on the Claude API; price kept for Bedrock/Google Cloud availability"446 if m["id"] == "claude-sonnet-5":447 note = "introductory $2/$10 made permanent on 2026-08-10 (planned $3/$15 increase cancelled)"448 price(m["id"], "input", inp, "per 1M tokens", notes=note)449 price(m["id"], "output", out, "per 1M tokens", notes=note)450 price(m["id"], "cached_input_write_5m", w5, "per 1M tokens", notes="1.25x base input")451 price(m["id"], "cached_input_write_1h", w1, "per 1M tokens", notes="2x base input")452 price(m["id"], "cached_input_read", rd, "per 1M tokens", notes="0.025x base input" if m["id"] in {"claude-fable-5-1", "claude-mythos-5-1"} else "0.1x base input")453 price(m["id"], "input", round(inp / 2, 4), "per 1M tokens", tier="batch", notes="Message Batches API, 50% off")454 price(m["id"], "output", round(out / 2, 4), "per 1M tokens", tier="batch", notes="Message Batches API, 50% off")455 if m["id"] in FAST_MODE_MODELS:456 price(m["id"], "input", 10, "per 1M tokens", tier="fast", notes="speed: fast (research preview); applies across full context; caching + data residency multipliers stack; not available on Batch or clouds")457 price(m["id"], "output", 50, "per 1M tokens", tier="fast", notes="speed: fast (research preview)")458 if m["id"] in TOOL_SYS_PROMPT_TOKENS:459 a, b = TOOL_SYS_PROMPT_TOKENS[m["id"]]460 price(m["id"], "tool_use_system_prompt_overhead_tokens", a, "input tokens per request", notes="tool_choice auto/none, at least one tool provided")461 price(m["id"], "tool_use_system_prompt_overhead_tokens", b, "input tokens per request", notes="tool_choice any/tool")462463 price("claude-opus-4-7", "fast_mode", None, "per 1M tokens", tier="fast", notes="fast mode removed 2026-07-24: speed: fast returns an error")464 price("claude-opus-4-6", "fast_mode", None, "per 1M tokens", tier="fast", notes="fast mode removed 2026-06-29: speed: fast runs at standard speed and standard price; usage.speed reports standard")465 price("long_context_1M", "input_over_200k_multiplier", 1.0, "multiplier", notes="Claude 4.6+ and Mythos Preview: full 1M context at standard pricing (no long-context premium); caching and batch discounts apply across the window")466 price("inference_geo=us", "all_token_dimensions_multiplier", 1.1, "multiplier", notes="Claude 4.6+ only; global (default) = 1.0; also Foundry US Data Zone Standard; 400 on earlier models", source="manage-claude/data-residency")467 price("bedrock_vertex_regional_endpoints", "regional_or_multiregion_premium", 0.10, "fraction over global endpoint price", notes="Sonnet 4.5 / Haiku 4.5 / Opus 4.5 and later on partner clouds; provider invoices")468 price("claude_platform_on_aws", "claude_consumption_unit", 0.01, "per CCU", notes="100 CCU = $1 of standard list price after discounts; hourly metering to AWS Marketplace")469 price("microsoft_foundry", "claude_consumption_unit", 0.01, "per CCU", notes="Azure Marketplace CCU billing, same conversion")470 price("web_search", "search", 10.0, "per 1,000 searches", notes="plus token costs for search results; errors not billed; each search = 1 use regardless of result count", source="agents-and-tools/tool-use/web-search-tool")471 price("web_fetch", "fetch", 0.0, "per fetch", notes="no extra charge; fetched content billed as input tokens (~2,500 tokens per 10 kB page)", source="agents-and-tools/tool-use/web-fetch-tool")472 price("code_execution", "container_hour", 0.05, "per hour per container", notes="beyond 1,550 free hours/org/month; 5-minute minimum per execution; billed even if tool not called when files are preloaded", source="agents-and-tools/tool-use/code-execution-tool")473 price("code_execution", "free_hours_per_month", 1550, "hours per organization per month", notes="free tier")474 price("code_execution", "with_web_search_or_web_fetch", 0.0, "per request", notes="free when web_search_20260209+/web_fetch_20260209+ is in the request (only token costs)")475 price("managed_agents", "session_runtime", 0.08, "per session-hour", notes="metered to the ms while status=running; replaces container-hour billing; tokens at model rates; no batch discount", source="about-claude/pricing")476 price("bash_20250124", "tool_definition_overhead_tokens", 325, "input tokens per request", notes="Opus 5 / Opus 4.8 / Opus 4.7")477 price("bash_20250124", "tool_definition_overhead_tokens", 244, "input tokens per request", notes="Opus 4.6, Sonnet 4.6 and earlier")478 price("text_editor_20250429", "tool_definition_overhead_tokens", 700, "input tokens per request", notes="Claude 4.x text editor")479 price("computer_toolset_20260801", "toolset_definition_overhead_tokens", 4500, "input tokens per request", notes="~4,520 on Fable 5/Mythos 5/Opus 5/Opus 4.8, ~4,590 on Sonnet 5; disabling zoom saves ~410; screenshots billed as image input")480 price("computer_20251124|computer_20250124", "tool_definition_overhead_tokens", 735, "input tokens per request", notes="plus 466-499 system prompt tokens (measured with computer_20250124)")481 price("browser_toolset_20260801", "toolset_definition_overhead_tokens", 6600, "input tokens per request", notes="~6,610 Fable 5/Mythos 5/Opus 5/Opus 4.8, ~6,670 Sonnet 5; all four optional members +~880")482 price("priority_tier", "capacity_commitment", None, "contract", tier="priority", notes="no longer available for purchase; existing commitments run to contract end; token prices unchanged; burndown: cache read 0.1, 5m write 1.25, 1h write 2.0, inference_geo us 1.1", source="api/service-tiers")483 price("files_api", "storage", None, "n/a", notes="no storage price documented on the pricing page; Files API ~500 RPM; files can expire via expires_in_seconds", source="build-with-claude/files")484 price("token_counting", "request", 0.0, "per request", notes="free; separate RPM limits (Start 5,000 / Build 10,000 / Scale 20,000)", source="build-with-claude/token-counting")485 price("claude_code", "n/a", None, "n/a", notes="not priced on the platform pricing page (consumer/Team plans; API usage at model rates)")486 return records, prices487488489# --------------------------------------------------------------------------------------------490def yn(v) -> str:491 if v is True:492 return "yes"493 if v is False:494 return "no"495 if v is None or v == "unknown":496 return "?"497 return str(v)498499500def write_doc(records: list[dict], prices: list[dict]) -> None:501 cur = [r for r in records if r.get("kind") == "snapshot" and "RETIRED" not in r["status"]]502 aliases = [r for r in records if r.get("kind") == "alias"]503 legacy = [r for r in records if "RETIRED" in r["status"]]504 L: list[str] = []505 L.append("# Anthropic models catalogue\n")506 L.append("**Status:** `DOCUMENTED` for every id below; `LIVE_VERIFIED` for the 11 ids returned by `GET /v1/models` on 2026-09-18 (each also probed with `GET /v1/models/{id}`; 5 of them with a minimal `POST /v1/messages`), `ACCOUNT_RESTRICTED` for the invite-only Mythos ids (404 with our key), `RETIRED` (+ 404 verified) for retired ids. ")507 L.append("**Sources:** models/overview, models/*/overview, about-claude/pricing, about-claude/model-deprecations, about-claude/models/model-ids-and-versions, api/models/list, build-with-claude/{thinking,effort,fast-mode,context-windows,prompt-caching,batch-processing,structured-outputs,vision}, agents-and-tools/tool-use/* (all under https://platform.claude.com/docs/en/), plus `sources/anthropic/models-api-raw.json` and `tmp-live/anthropic-models/summary.json`. ")508 L.append(f"**Last verified:** {LAST_VERIFIED} · Machine-readable twin: `generated/fragments/models/anthropic-models.json` (built by `scripts/gen_anthropic_models_fragment.py`).\n")509 L.append("## 1. Current lineup (documented, active or deprecated)\n")510 L.append("| id | Display | Family/gen | Status | Released (docs) | created_at (live) | Cutoff reliable / training | Context | Max out | Thinking | Effort default / levels | Retirement |")511 L.append("|---|---|---|---|---|---|---|---|---|---|---|---|")512 for r in cur:513 c = r["capabilities"]514 L.append(f"| `{r['id']}` | {r['display_name']} | {r['family']} {r['generation']} | {', '.join(r['status'])} | {r['release_date']} | {(r.get('created_at_live') or '—')[:10]} | {r['knowledge_cutoff']['reliable'] or '?'} / {r['knowledge_cutoff']['training_data'] or '?'} | {r['context_window']:,} | {r['max_output']:,}{' (300k batch beta)' if r['max_output_batch_beta'] else ''} | {r['thinking']} | {c['effort_default'] or '—'} / {','.join(c['effort_levels']) or '—'} | {r['deprecation']['retirement']} |")515 L.append("\n**Aliases (pre-4.6 only):** " + "; ".join(f"`{a['id']}` → `{a['resolves_to']}` (GET /v1/models → {a['verification']['http_status']})" for a in aliases) + ". Dateless 4.6+ ids are pinned snapshots, not aliases.\n")516 L.append("## 2. Live vs docs discrepancies (2026-09-18)\n")517 for r in cur:518 for d in r["discrepancies_live_vs_docs"]:519 L.append(f"- `{r['id']}`: {d}")520 L.append("- `claude-mythos-5-1`, `claude-mythos-5`, `claude-mythos-preview`: documented (invite-only) but `GET /v1/models/{id}` → 404 `not_found_error` with our key and absent from `GET /v1/models` (does not mean non-existent).")521 L.append("- `GET /v1/models` returns undocumented-but-referenced fields `max_input_tokens`, `max_tokens`, `capabilities{batch,citations,code_execution,context_management{clear_tool_uses_20250919,clear_thinking_20251015,compact_20260112},effort{low..max},image_input,pdf_input,structured_outputs,thinking{types{enabled,adaptive}}}` (added 2026-03-18). The reference example shows `max_input_tokens: 0`; live values are real numbers.")522 L.append("- Messages `usage` (live) contains `cache_creation{ephemeral_5m_input_tokens,ephemeral_1h_input_tokens}`, `output_tokens_details.thinking_tokens` (absent on Sonnet 4.6), `service_tier: \"standard\"`, `inference_geo: \"global\"`; top level `container: null`, `stop_details: null`. No `speed` field unless fast mode is requested.\n")523 L.append("## 3. Model × Capability matrix\n")524 caps = ["vision", "high_resolution_vision_2576px", "pdf_input", "thinking_extended_manual_budget", "thinking_adaptive", "thinking_always_on", "interleaved_thinking", "effort_parameter",525 "fast_mode_speed_fast", "structured_outputs_json", "fine_grained_tool_streaming", "prompt_caching_1h_ttl", "min_cacheable_tokens", "batch_api", "batch_extended_output_300k_beta",526 "citations", "code_execution", "programmatic_tool_calling", "computer_use", "browser_use", "tool_search", "advisor_tool", "compaction_server_side", "context_1m_default_no_beta",527 "inference_geo_data_residency", "mid_conversation_system_messages", "task_budgets_beta", "tool_choice_any_or_tool", "priority_tier", "zero_data_retention_eligible", "latency_class"]528 L.append("| Capability | " + " | ".join(r["display_name"].replace("Claude ", "") for r in cur) + " |")529 L.append("|---|" + "---|" * len(cur))530 for k in caps:531 L.append(f"| {k} | " + " | ".join(yn(r["capabilities"].get(k)) for r in cur) + " |")532 L.append("\n`code_execution` row = live `capabilities.code_execution.supported`; docs list Haiku 4.5 as supported (without programmatic tool calling / REPL persistence). \n`sampling params`: temperature/top_p/top_k non-default → 400 on Claude 4.7+ and Mythos Preview; incompatible with thinking on older models.\n")533 L.append("## 4. Model × Tool-version matrix (exact `type` strings)\n")534 all_tools = []535 for r in cur:536 for t in r["tools"]:537 if t["type"] not in all_tools:538 all_tools.append(t["type"])539 L.append("| tool `type` | beta header | " + " | ".join(r["display_name"].replace("Claude ", "") for r in cur) + " |")540 L.append("|---|---|" + "---|" * len(cur))541 for tt in all_tools:542 beta = next((t["beta_header"] for r in cur for t in r["tools"] if t["type"] == tt), None)543 L.append(f"| `{tt}` | {beta or '—'} | " + " | ".join("yes" if any(t["type"] == tt for t in r["tools"]) else "no" for r in cur) + " |")544 L.append("\nLegacy tool versions: `computer_20250124` (beta `computer-use-2025-01-24`) for Sonnet 4.5, Haiku 4.5, Opus 4.1, Sonnet 4, Opus 4; `computer_20241022`/`bash_20241022`/`text_editor_20241022` (beta `computer-use-2024-10-22`) only for Sonnet 3.5 (Oct 2024, retired); `text_editor_20250124` for Sonnet 3.7 (retired); `text_editor_20250429` Claude 4.x (superseded by `text_editor_20250728`); `code_execution_20250522` Python-only (legacy); `mcp-client-2025-04-04` deprecated. Undated aliases `tool_search_tool_regex` / `tool_search_tool_bm25` resolve to the latest dated version. Advisor tool: executor→advisor pairs are constrained (advisor must be at least as capable; see advisor-tool page).\n")545 L.append("## 5. Model × Endpoint matrix\n")546 L.append("| Endpoint | Applies to |")547 L.append("|---|---|")548 L.append("| `POST /v1/messages` | all active models (all 11 live ids verified 200 with `GET /v1/models/{id}`; 5 verified with a real message) |")549 L.append("| `POST /v1/messages/count_tokens` | all active models (verified on opus-5, sonnet-5, fable-5-1, opus-4-8, sonnet-4-6) |")550 L.append("| `POST /v1/messages/batches` | all active models; `output-300k-2026-03-24` on Opus 5/4.8/4.7/4.6, Sonnet 5/4.6 |")551 L.append("| `GET /v1/models`, `GET /v1/models/{id}` | lists 11 ids; aliases resolve; retired → 404 `not_found_error`; invite-only Mythos → 404 |")552 L.append("| `/v1/files` (GA 2026-08-19) | model-agnostic; files referenced from Messages / code execution |")553 L.append("| `/v1/skills` (GA 2026-08-19) | any model supporting code execution |")554 L.append("| Managed Agents `/v1/agents`, `/v1/sessions`, `/v1/environments` (beta `managed-agents-2026-04-01`) | model set documented per feature (Dreams: Fable 5, Sonnet 5, Opus 5) |")555 L.append("| `POST /v1/complete` (Text Completions) | legacy; removed from Python SDK v1.0 (2026-08-20) |\n")556 L.append("## 6. Model × Cloud matrix\n")557 L.append("| id | Amazon Bedrock | Google Cloud (Vertex) | Microsoft Foundry | Claude Platform on AWS |")558 L.append("|---|---|---|---|---|")559 for r in cur:560 ci = r["availability"]["cloud_ids"]561 L.append(f"| `{r['id']}` | {', '.join('`%s`' % b for b in ci['bedrock']) if ci['bedrock'] else '—'} | {'`%s`' % ci['vertex'] if ci['vertex'] else '—'} | {'`%s`' % ci['foundry'] if ci['foundry'] else '—'} | {'`%s`' % ci['claude_platform_on_aws'] if ci['claude_platform_on_aws'] else '—'} |")562 L.append("\nBedrock: Opus 4.7+ and Haiku 4.5 use the Messages-API endpoint ids (`anthropic.claude-…`, no `-v1:0`); Opus 4.6 is the last `-v1` id (`anthropic.claude-opus-4-6-v1`); dated models use `anthropic.claude-{name}-{YYYYMMDD}-v1:0` via InvokeModel. Vertex: dated models use `@YYYYMMDD`. Foundry and Claude Platform on AWS use the Claude API id (alias form where one exists). Partner clouds set their own retirement dates and +10% regional-endpoint pricing.\n")563 L.append("## 7. Retired models (deprecations page + release notes)\n")564 L.append("| id | Display | Deprecated | Retired | Replacement | Our probe | Cloud note |")565 L.append("|---|---|---|---|---|---|---|")566 for r in legacy:567 L.append(f"| `{r['id']}` | {r['display_name']} | {r['deprecation']['deprecated_on']} | {r['deprecation']['retired_on']} | `{r['deprecation']['replacement']}` | {r['verification']['http_status'] or '—'} | {r['availability'].get('cloud_note') or ''} |")568 L.append("\n## 8. Pricing snapshot (USD per MTok; full detail in docs/anthropic/pricing.md)\n")569 L.append("| id | input | output | 5m write | 1h write | cache read | batch in/out | fast in/out |")570 L.append("|---|---|---|---|---|---|---|---|")571 for r in cur:572 p = r["pricing"]573 if not p:574 L.append(f"| `{r['id']}` | not listed | | | | | | |")575 continue576 fm = p.get("fast_mode")577 L.append(f"| `{r['id']}` | {p['input']} | {p['output']} | {p['cache_write_5m']} | {p['cache_write_1h']} | {p['cache_read']} | {p['batch_input']} / {p['batch_output']} | {(str(fm['input']) + ' / ' + str(fm['output'])) if fm else '—'} |")578 L.append("\n## 9. Notes\n")579 L.append("- Model IDs: 4.6+ ids are dateless pinned snapshots (`claude-{name}-{major}[-{minor}]`); pre-4.6 ids carry `-YYYYMMDD` and have convenience aliases. Weights never change under an id; serving infrastructure may.")580 L.append("- Tokenizer: Claude 4.7+ and Mythos Preview use a new tokenizer (~30% more tokens for the same text); 1M tokens ≈ 555k words on it vs ≈ 750k words before.")581 L.append("- Thinking: adaptive is the only mode on Fable/Mythos 5.x (cannot be disabled; no budgets; no prefill); Opus 5 / Sonnet 5 have thinking on by default and reject `type: enabled`; Opus 4.6 / Sonnet 4.6 accept `enabled` but it is deprecated; 4.5 models are manual-budget only.")582 L.append("- Fast mode: only Opus 5 and Opus 4.8 (`speed: \"fast\"` + `fast-mode-2026-02-01`); Opus 4.7 → error since 2026-07-24; Opus 4.6 → silently standard since 2026-06-29.")583 L.append("- Rate-limit buckets: Fable 5.x shared; Mythos 5.x shared; Opus 5 own; Opus 4.8/4.7/4.6/4.5 shared; Sonnet 5 own; Sonnet 4.6/4.5 shared; Haiku 4.5 own.")584 L.append("- Data retention: Fable 5/5.1 and Mythos 5/5.1 require 30-day retention (no ZDR unless authorized).")585 L.append("- Watermarking: text from Fable 5.1 / Mythos 5.1 carries Anthropic's text watermark; code-execution media files carry C2PA credentials via the Files API.")586 OUT_DOC.parent.mkdir(parents=True, exist_ok=True)587 OUT_DOC.write_text("\n".join(L) + "\n")588589590def main() -> None:591 records, prices = build()592 OUT_MODELS.parent.mkdir(parents=True, exist_ok=True)593 OUT_PRICING.parent.mkdir(parents=True, exist_ok=True)594 OUT_MODELS.write_text(json.dumps({"record_type": "model", "provider": "anthropic", "generated_at": LAST_VERIFIED, "generator": "scripts/gen_anthropic_models_fragment.py",595 "count": len(records), "records": records}, indent=2, ensure_ascii=False) + "\n")596 OUT_PRICING.write_text(json.dumps({"record_type": "price", "provider": "anthropic", "generated_at": LAST_VERIFIED, "generator": "scripts/gen_anthropic_models_fragment.py",597 "count": len(prices), "records": prices}, indent=2, ensure_ascii=False) + "\n")598 write_doc(records, prices)599 print(f"models={len(records)} prices={len(prices)} -> {OUT_MODELS.relative_to(ROOT)}, {OUT_PRICING.relative_to(ROOT)}, {OUT_DOC.relative_to(ROOT)}")600601602if __name__ == "__main__":603 main()604