SPB Git forge

spb/ai-atlas

Public
41commits 1branches 0releases
4.6 MBsize
maindefault branch
12 days agolast push
HTML 77.2% TypeScript 10.5% Python 9.6% JavaScript 2.5%

AI Atlas foundation: schema, connector SDK, archive, temporal writer, LLM gateway, scheduler, registry, CLI, Anthropic connector

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed 12 days ago (Sep 11, 2026)

72 changed files +8,918 −0

added .env.example +25 −0
@@ -0,0 +1,25 @@
1 +# AI Atlas — local development. Copy to .env (never commit .env).
2 +APP_ENV=development
3 +AIA_SITE_URL=http://localhost:8320
4 +DATABASE_URL=postgresql+asyncpg://aiatlas:aiatlas@127.0.0.1:5432/aiatlas
5 +REDIS_URL=redis://127.0.0.1:6379/5
6 +AIA_DATA_DIR=./data
7 +AIA_API_HOST=127.0.0.1
8 +AIA_API_PORT=8321
9 +AIA_ADMIN_TOKEN=dev-admin-token
10 +AIA_LOG_JSON=0
11 +# Crawler identity (robots.txt is honoured; contact address is public)
12 +AIA_USER_AGENT="AIAtlasBot/0.1 (+https://www.ai-atlas.co/bot; contact@spboucher.ai)"
13 +# Local LLM factory (OpenAI-compatible; MacLustr llm-api.io). Optional — deterministic extraction works without it.
14 +AIA_LLM_BASE_URL=https://www.llm-api.io/v1
15 +AIA_LLM_API_KEY=
16 +AIA_LLM_SMALL_MODEL=qwen3-4b-instruct-2507-4bit
17 +AIA_LLM_MEDIUM_MODEL=qwen3.6-35b-a3b-4bit
18 +AIA_LLM_LARGE_MODEL=qwen3.8-27b-4bit
19 +AIA_EMBEDDING_MODEL=qwen3-embedding-0.6b-4bit
20 +# Optional escalation transports (never required)
21 +SCRAPFLY_API_KEY=
22 +FIRECRAWL_API_KEY=
23 +# Web
24 +API_URL=http://127.0.0.1:8321
25 +NEXT_PUBLIC_SITE_URL=http://localhost:8320
added .gitignore +22 −0
@@ -0,0 +1,22 @@
1 +.env
2 +.env.*
3 +!.env.example
4 +.venv/
5 +__pycache__/
6 +*.pyc
7 +/data/
8 +node_modules/
9 +.next/
10 +tmp/
11 +.DS_Store
12 +deploy/.admin-token
13 +deploy/.llm-key
14 +deploy/rendered/
15 +*.tsbuildinfo
16 +apps/web/next-env.d.ts
17 +apps/web/qa/screens/
18 +apps/web/AGENTS.md
19 +apps/web/CLAUDE.md
20 +.pytest_cache/
21 +.ruff_cache/
22 +*.egg-info/
added CLAUDE.md +52 −0
@@ -0,0 +1,52 @@
1 +# AI Atlas — project guide (condensed from the founding spec; the full architecture is in docs/ARCHITECTURE.md)
2 +
3 +**Mission**: the most comprehensive, structured, searchable and continuously updated map of the global AI ecosystem — Bloomberg × Wikipedia ×
4 +Crunchbase × Hugging Face × Papers With Code, purpose-built for AI. Not a tools directory, not a news aggregator, not an API wrapper.
5 +**The dataset is the product; the website and the API are interfaces to it.**
6 +
7 +## Non-negotiables
8 +
9 +1. No critical dependence on external data APIs — direct crawling first; Scrapfly/Firecrawl/browser are optional escalation only.
10 +2. Store provenance (source, snapshot, URL, tier, confidence, extractor) on every fact; store history (temporal claims, append-only prices/results, raw snapshots).
11 +3. Local LLM (MacLustr llm-api.io via the gateway) for large-scale extraction; deterministic extraction always runs first.
12 +4. **Never fabricate data.** Missing → "Unavailable". Conflicts → both claims stored and flagged; never a compromise value.
13 +5. Primary sources first (tier 1 official > 2 quality secondary > 3 community > 4 unverified). Connectors are owned IP with fixture tests.
14 +6. Live counters, stats, feeds and timelines come from the database — never hardcoded.
15 +7. Public information stays public (SEO); login only for watchlists/alerts/API keys later.
16 +8. Respectful crawling: robots.txt, per-domain rate limits, conditional requests, identified UA, no bypassing access controls, no private data.
17 +
18 +## Stack
19 +
20 +- Backend `src/aiatlas/` — Python 3.12, FastAPI, SQLAlchemy Core + asyncpg, Alembic (SQL, forward-only), Redis, APScheduler, selectolax, feedparser, pydantic.
21 + CLI `aia` (`.venv/bin/aia --help`). Connector SDK in `sdk/` (docs/CONNECTORS.md). API contract in docs/API.md.
22 +- Database: Postgres 17 + pgvector + pg_trgm. Internal ids = prefixed ULIDs (`model_…`); slugs stable and unique.
23 +- Frontend `apps/web/` — Next.js 16 (App Router, React 19, TypeScript strict, Tailwind v4). Guide: docs/FRONTEND.md. Dev on :8320, API on :8321.
24 +- Data outside the repo: `AIA_DATA_DIR` (`./data` in dev, `~/ai-atlas-data` in prod): raw/, text/, backups/, logs/, cache/, seed/.
25 +
26 +## Local development
27 +
28 +```bash
29 +uv venv --python 3.12 .venv && uv pip install --python .venv/bin/python -e ".[dev]"
30 +cp .env.example .env # local Postgres `aiatlas` (role aiatlas/aiatlas), Redis db 5
31 +.venv/bin/aia migrate && .venv/bin/aia seed
32 +.venv/bin/aia run anthropic # one connector, live · `--file key=path` uses a fixture · `aia crawl --priority 0` runs all P0 connectors
33 +.venv/bin/aia api --reload # http://127.0.0.1:8321/api/v1/docs
34 +pnpm install && pnpm dev:web # http://localhost:8320
35 +.venv/bin/pytest -q # fixtures only; `-m live` hits the network
36 +```
37 +
38 +## Production (MacLustr)
39 +
40 +Node **M2M32c** (dedicated), deployed by `mld` — manifest `deploy/ai-atlas.mld.json``M1M32:~/dispatch/apps/ai-atlas.json`. PM2 processes
41 +`ai-atlas-api` (uvicorn 127.0.0.1:8321), `ai-atlas-scheduler` (`aia schedule`), `ai-atlas-web` (next start :8320). Public route through the
42 +MacLustr Tunnel: `https://www.ai-atlas.co → M2M32c:8320`. See docs/DEPLOY.md. Secrets live only in the rendered manifest (`deploy/.admin-token`,
43 +`deploy/.llm-key`, git-ignored). LLM factory: `AIA_LLM_BASE_URL=https://www.llm-api.io/v1` (private MacLustr server on M1M64).
44 +
45 +## Conventions
46 +
47 +- Properties and relations use the shared vocabulary in docs/CONNECTORS.md; metrics use the `metric.` prefix (no events).
48 +- Every connector: `source_key` registered in `registry/sources.yaml`, organization in `registry/organizations.yaml`, fixture test in `tests/`.
49 +- Parser improved? bump `parser_version` and `aia reprocess <connector>` — never re-crawl for a code change.
50 +- Frontend: mobile-first (390/430/768/1440), DOM order = visual order, ≥ 44 px targets, no horizontal overflow, dark + light, premium
51 + institutional design (no generic SaaS cards). Every page: real data, loading + error + empty states, source attribution, `generateMetadata`.
52 +- Units: tokens, USD per 1M tokens, GB, GB/s, W, ISO dates (UTC). Openness vocabulary: open-weights | open-source | proprietary | restricted.
added README.md +39 −0
@@ -0,0 +1,39 @@
1 +# AI Atlas
2 +
3 +**www.ai-atlas.co — Explore the entire AI ecosystem.**
4 +
5 +AI Atlas is a continuously updated, historically versioned, machine-readable map of the global artificial intelligence ecosystem: models,
6 +companies, research, providers and prices, benchmarks, hardware, frameworks, datasets, tools — connected in one temporal knowledge graph,
7 +with provenance on every fact.
8 +
9 +- **First-party connectors** read official pages, docs, feeds, model cards and public files directly. No commercial data API is required.
10 +- **Raw historical archive**: every changed page is stored (content-addressed, compressed) and can be reprocessed when parsers improve.
11 +- **Temporal knowledge graph**: claims carry `valid_from`/`valid_to`, prices and benchmark results are append-only, every change is an event.
12 +- **Local LLM factory**: large-scale extraction runs on MacLustr's own inference servers through an engine-agnostic gateway.
13 +- **Interfaces**: the website, the public API (`/api/v1`), and — later — datasets and alerts.
14 +
15 +## Layout
16 +
17 +```
18 +registry/ curated YAML (sources, organizations, providers, benchmarks, hardware) — every entry cites its source
19 +src/aiatlas/ Python platform: sdk/ (connector SDK), connectors/, services/ (jobs, scheduler, LLM gateway, search, quality), api/, cli.py
20 +migrations/ forward-only SQL migrations
21 +apps/web/ Next.js 16 website
22 +tests/ pytest with saved fixtures
23 +deploy/ MacLustr (mld) manifest and scripts
24 +docs/ ARCHITECTURE.md · CONNECTORS.md · API.md · FRONTEND.md · DEPLOY.md
25 +```
26 +
27 +## Quick start
28 +
29 +```bash
30 +uv venv --python 3.12 .venv && uv pip install --python .venv/bin/python -e ".[dev]"
31 +cp .env.example .env && createdb -O aiatlas aiatlas
32 +.venv/bin/aia migrate && .venv/bin/aia seed
33 +.venv/bin/aia crawl --priority 0 # initial corpus: labs, Hugging Face, arXiv, providers, benchmarks…
34 +.venv/bin/aia api # http://127.0.0.1:8321/api/v1/docs
35 +pnpm install && pnpm dev:web # http://localhost:8320
36 +```
37 +
38 +© 2026 Simon-Pierre Boucher · contact@spboucher.ai · hosted on [MacLustr](https://www.maclustr.io). AI Atlas links to original sources and
39 +never republishes documents in full; extracted facts are provided as-is with their provenance.
added alembic.ini +31 −0
@@ -0,0 +1,31 @@
1 +[alembic]
2 +script_location = migrations
3 +prepend_sys_path = src
4 +path_separator = os
5 +
6 +[loggers]
7 +keys = root,alembic
8 +
9 +[handlers]
10 +keys = console
11 +
12 +[formatters]
13 +keys = generic
14 +
15 +[logger_root]
16 +level = WARN
17 +handlers = console
18 +
19 +[logger_alembic]
20 +level = INFO
21 +handlers =
22 +qualname = alembic
23 +
24 +[handler_console]
25 +class = StreamHandler
26 +args = (sys.stderr,)
27 +level = NOTSET
28 +formatter = generic
29 +
30 +[formatter_generic]
31 +format = %(levelname)-5.5s [%(name)s] %(message)s
added docs/API.md +119 −0
@@ -0,0 +1,119 @@
1 +# AI Atlas API — contract (v1)
2 +
3 +Base: `/api/v1` (FastAPI, `src/aiatlas/api`). JSON, UTF-8, ISO-8601 UTC timestamps, numbers as numbers (Postgres aggregates may arrive as
4 +strings — the web layer normalises). Public routes are cached in Redis (`aia:api:*`, 60–600 s) and rate-limited per IP on search.
5 +Admin routes require header `x-aia-admin-token: <AIA_ADMIN_TOKEN>`. OpenAPI at `/api/v1/docs`. Errors: `{"detail": "..."}` with 400/404/429/503.
6 +Never expose credentials, internal hostnames, raw archive content or `raw_path`s.
7 +
8 +## Shared shapes
9 +
10 +```ts
11 +type Num = number | string | null
12 +type Org = { id: string; slug: string; name: string } | null
13 +type EntitySummary = { id: string; entity_type: string; slug: string; name: string; description: string | null; status: string;
14 + organization: Org; attributes: Record<string, unknown>; quality: { score?: number; completeness?: number; primary_source_ratio?: number;
15 + freshness?: number; source_count?: number; conflicts?: number }; counts: { relations?: number; events?: number; claims?: number };
16 + first_seen_at: string; last_seen_at: string; updated_at: string }
17 +type Page<T> = { items: T[]; total: number; limit: number; offset: number }
18 +type Provenance = Record<string, { source_id: string | null; source_name?: string; url: string | null; observed_at: string; tier: number;
19 + confidence: string; extractor: string; unit?: string }>
20 +type ChangeEvent = { id: string; event_type: string; category: string; property: string | null; old_value: unknown; new_value: unknown;
21 + summary: string; importance: 0 | 1 | 2 | 3; observed_at: string; effective_at: string | null; source_url: string | null; connector_name: string | null;
22 + entity: EntitySummary | null; meta: Record<string, unknown> }
23 +type Price = { id: string; model: EntitySummary; provider: EntitySummary; provider_model_id: string | null; input_per_mtok: Num; output_per_mtok: Num;
24 + cached_input_per_mtok: Num; cache_write_per_mtok: Num; batch_input_per_mtok: Num; batch_output_per_mtok: Num; per_image: Num; currency: string;
25 + context_length: Num; max_output_tokens: Num; features: Record<string, unknown>; observed_at: string; valid_from: string; valid_to: string | null; source_url: string | null; tier: number }
26 +type BenchmarkResult = { id: string; model: EntitySummary; benchmark: EntitySummary; score: number; metric: string | null; unit: string | null;
27 + higher_is_better: boolean; config: Record<string, unknown>; evaluated_at: string | null; observed_at: string; source_url: string | null; tier: number; confidence: string }
28 +type Claim = { id: string; property: string; value: unknown; unit: string | null; tier: number; confidence: string; status: string; extractor: string;
29 + observed_at: string; effective_at: string | null; valid_from: string; valid_to: string | null; source_url: string | null; source_name: string | null }
30 +type SourceRef = { source_id: string | null; source_name: string | null; domain: string | null; tier: number | null; url: string; doc_type: string; last_observed_at: string | null; snapshots: number }
31 +```
32 +
33 +## Public routes
34 +
35 +| route | returns |
36 +|---|---|
37 +| `GET /health` | `{ status: "ok"|"degraded", version, db: bool, redis: bool, llm: { available, reachable? }, time }` |
38 +| `GET /stats` | `{ entities: Record<type, number>, entities_total, sources, connectors, connectors_enabled, documents, snapshots, claims, claims_current, relations, change_events, change_events_24h, change_events_7d, benchmark_results, prices_current, prices_total, review_pending, llm_jobs, llm_tokens, last_snapshot_at, last_event_at, first_entity_at, archive: { raw_bytes, raw_files, text_bytes, text_files }, computed_at }`**always live from the DB** |
39 +| `GET /stats/history?days=90` | `{ items: { day: string; counts: object }[] }` |
40 +| `GET /search?q=&type=&limit=30&offset=0` | `{ query: CompiledQuery, items: (EntitySummary & { rank: number })[], total: number }` — uses `services.search.compile_query` + `search_entities` (+ embedding when the gateway is up) |
41 +| `GET /search/suggest?q=` | `{ items: { id, entity_type, slug, name, organization_name }[] }` (≤ 8, prefix, fast) |
42 +| `GET /entities/{slug_or_id}` | `EntityDetail` (below). Also mounted as `/models/{slug}`, `/companies/{slug}`, `/papers/{slug}`, `/providers/{slug}`, `/benchmarks/{slug}`, `/hardware/{slug}`, `/frameworks/{slug}`, `/datasets/{slug}`, `/tools/{slug}` (404 if the type doesn't match) |
43 +| `GET /entities/{slug}/timeline?limit=50&before=` | `{ items: ChangeEvent[] }` (entity's own events + events of entities it develops for companies) |
44 +| `GET /entities/{slug}/history?property=` | `{ items: Claim[] }` — full claim history (all statuses), newest first |
45 +| `GET /entities/{slug}/asof?date=YYYY-MM-DD` | `{ existed: bool, first_seen_at, date, attributes: Record<string, unknown>, claims: Claim[] }` — state as known at that date |
46 +| `GET /entities/{slug}/graph?depth=1&limit=80` | `{ nodes: { id, slug, name, entity_type, organization_name? }[], edges: { source, target, predicate }[] }` (depth ≤ 2, cap nodes) |
47 +| `GET /entities/{slug}/sources` | `{ items: SourceRef[] }` |
48 +| `GET /entities/{slug}/related?limit=` | `{ items: EntitySummary[] }` (same org / same family / shared relations) |
49 +| `GET /models?q=&org=&family=&openness=&modality=&status=&min_params=&max_params=&min_context=&year_from=&year_to=&license=&sort=(updated|name|params|context|release|quality|downloads)&order=&limit=&offset=` | `Page<EntitySummary>` + `facets` when `facets=1`: `{ organizations: {slug,name,count}[], openness: {value,count}[], modalities, families, years, licenses, status }` |
50 +| `GET /companies?q=&country=&kind=&sort=(models|name|updated|quality)&limit=&offset=` | `Page<EntitySummary & { model_count: number; paper_count: number }>` (+`facets`: countries, kinds) |
51 +| `GET /papers?q=&category=&org=&since=&until=&sort=(published|updated)&limit=&offset=` | `Page<EntitySummary>` |
52 +| `GET /providers` | `{ items: (EntitySummary & { model_count: number; price_count: number; min_input_per_mtok: Num; min_output_per_mtok: Num })[] }` |
53 +| `GET /prices?model=&provider=&sort=(input|output|model|provider|observed)&limit=&offset=&current=1` | `Page<Price>` |
54 +| `GET /prices/history?model=&provider=` | `{ items: Price[] }` (all rows incl. closed, oldest first) |
55 +| `GET /prices/index?days=180` | `{ series: { day: string; median_input: Num; median_output: Num; min_input: Num; models: number }[]; movers: ChangeEvent[] }` computed from `prices` history |
56 +| `GET /benchmarks` | `{ items: (EntitySummary & { result_count: number; model_count: number; top: { model: EntitySummary; score: number } | null })[] }` |
57 +| `GET /benchmarks/{slug}/results?limit=&offset=&config=` | `Page<BenchmarkResult>` sorted by score (respecting `higher_is_better`), current rows only unless `history=1` |
58 +| `GET /benchmarks/{slug}/history?model=` | `{ items: BenchmarkResult[] }` over time |
59 +| `GET /hardware?kind=&manufacturer=&min_memory=&sort=` | `Page<EntitySummary>` |
60 +| `GET /hardware/fit?memory_gb=&quant=(4bit|8bit|fp16)&context=8192&limit=` | `{ inputs, assumptions: string[], items: { model: EntitySummary; parameter_count: number; estimated_memory_gb: number; fits: boolean; headroom_gb: number; quantization: string; note: string }[] }`**ESTIMATED**: bytes/param (4bit 0.5+overhead 1.15, 8bit 1.0, fp16 2.0) + KV cache estimate; label as estimated |
61 +| `GET /explore/types` | `{ items: { entity_type, count, label }[] }` |
62 +| `GET /explore/{type}?q=&org=&sort=&limit=&offset=` | `Page<EntitySummary>` generic listing for any type (datasets, frameworks, tools, repositories, regulation…) |
63 +| `GET /changes?category=&type=&entity_type=&importance_min=&since=&until=&q=&limit=50&before=<observed_at cursor>` | `Page<ChangeEvent>` newest first; `type` = comma list of event types; excludes `DOCUMENT_CHANGED` unless `include_documents=1` |
64 +| `GET /changes/daily?date=YYYY-MM-DD` | `{ date, counts: Record<category, number>, sections: { category, label, items: ChangeEvent[] }[], new_models: EntitySummary[] }` ("What changed in AI today", DB-generated only) |
65 +| `GET /changes/categories?days=7` | `{ items: { category, event_type, count }[] }` |
66 +| `GET /timeline?entity=&year=&category=&limit=` | `{ items: { month: string; events: ChangeEvent[] }[] }` grouped by month; global when no entity |
67 +| `GET /compare?ids=slug,slug,…` (2–6) | `{ entity_type, dimensions: { key, label, unit?, kind: "number"|"text"|"list"|"bool"|"date" }[], items: { entity: EntitySummary; values: Record<key, unknown>; provenance: Provenance; prices?: Price[]; results?: BenchmarkResult[] }[] }` — dimensions per type: model (params, active params, context, max output, openness, license, modalities, release date, knowledge cutoff, best price in/out, benchmark scores shared by all), provider (models, min prices, features), hardware (memory, bandwidth, tdp, runtimes), framework (version, license, stars), company (country, founded, models, papers) |
68 +| `GET /diff?a=YYYY-MM-DD&b=YYYY-MM-DD&scope=(all|models|org:<slug>|family:<name>)` | `{ a, b, new_entities: EntitySummary[], gone_entities: EntitySummary[], property_changes: ChangeEvent[], price_changes: ChangeEvent[], benchmark_changes: ChangeEvent[], counts }` |
69 +| `GET /sources` | `{ items: { key, name, domain, tier, kind, category, organization: Org, enabled, documents, last_crawled_at, connectors: { name, label, health, last_success_at, interval_seconds }[] }[] }` (public transparency page) |
70 +| `GET /methodology` | `{ metrics: metric_definitions[], confidence_levels, tiers, event_types, extractors }` |
71 +| `GET /trending?days=7&limit=12` | `{ items: (EntitySummary & { views: number })[] }` from `page_views` |
72 +| `POST /views` `{ path }` | `{ ok: true }` (beacon; 1 req/s/IP) |
73 +| `GET /sitemap?type=&limit=5000&offset=0` | `{ items: { slug, entity_type, updated_at }[], total }` |
74 +| `GET /api-keys/me` (header `x-api-key`) | `{ label, plan, rate_per_min, usage_count }` — developer keys (later); public routes work without a key |
75 +
76 +### `EntityDetail`
77 +
78 +```ts
79 +EntitySummary & {
80 + attributes: Record<string, unknown> // full
81 + provenance: Provenance
82 + aliases: string[]; identifiers: { scheme: string; value: string }[]
83 + relations: { predicate: string; direction: "out" | "in"; items: EntitySummary[]; total: number }[] // grouped, ≤ 24 per group
84 + sources: SourceRef[] // documents describing this entity (deduped by URL)
85 + timeline: ChangeEvent[] // latest 30
86 + quality: {...}; counts: {...}
87 + // type-specific blocks (present only when relevant)
88 + prices?: Price[] // current rows across providers (model) or for this provider (provider)
89 + price_history?: Price[] // closed + current, oldest first (model)
90 + results?: BenchmarkResult[] // model: its results · benchmark: leaderboard top 100
91 + lineage?: { ancestors: EntitySummary[]; descendants: EntitySummary[]; quantizations: EntitySummary[] } // model
92 + providers?: EntitySummary[] // model
93 + hardware_fit?: { hardware: EntitySummary; quantization: string; estimated_memory_gb: number; fits: boolean }[] // model, ESTIMATED
94 + models?: Page<EntitySummary> // company / provider / hardware(runnable)
95 + papers?: EntitySummary[] // company / model
96 + repositories?: EntitySummary[] // company / model / framework
97 +}
98 +```
99 +
100 +## Admin routes (`x-aia-admin-token`)
101 +
102 +| route | returns / action |
103 +|---|---|
104 +| `GET /admin/overview` | `{ stats, queue: Record<kind, Record<status, n>>, heartbeats, connectors: { ok, degraded, failing, disabled }, review_pending, recent_errors: n, llm: { jobs_24h, tokens_24h, by_stage } , archive }` |
105 +| `GET /admin/connectors` | full `connectors` rows + last run + docs/snapshots counts + source tier |
106 +| `POST /admin/connectors/{name}/run` `{ force?: bool }` | enqueue an immediate run (Redis flag `aia:run-now:<name>` consumed by the scheduler tick) → `{ queued: true }` |
107 +| `PATCH /admin/connectors/{name}` `{ enabled?, interval_seconds?, priority? }` | update |
108 +| `GET /admin/runs?connector=&limit=` · `GET /admin/errors?connector=&limit=` | rows |
109 +| `GET /admin/documents?connector=&status=&q=&limit=&offset=` · `GET /admin/documents/{id}` | documents (+ snapshots list); `GET /admin/snapshots/{id}` → metadata + `structured` + `diff` + first 20 kB of cleaned text (never raw HTML) |
110 +| `GET /admin/jobs?status=&kind=` · `POST /admin/jobs/{id}/retry` · `POST /admin/jobs/requeue-dead` | queue |
111 +| `GET /admin/llm-jobs?limit=` · `GET /admin/llm/health` | LLM factory accounting |
112 +| `GET /admin/review?status=pending&kind=` · `POST /admin/review/{id}` `{ action: "approve"|"reject"|"edit", resolution?: object }` | review queue; approving a `merge_candidate` calls `merge_entities(source, target)` (aliases/identifiers/claims/relations/events moved, `merged_into` set) |
113 +| `GET /admin/entities/duplicates?type=&limit=` | candidate pairs by normalized name similarity (`pg_trgm`) within a type |
114 +| `POST /admin/entities/merge` `{ source_id, target_id }` · `POST /admin/entities/{id}/claims/{claim_id}/retract` | curation |
115 +| `POST /admin/reprocess` `{ connector, url? }` | enqueue `reprocess_snapshot` |
116 +| `POST /admin/llm/enqueue` `{ limit?, task? }` | queue `llm_extract` for pending snapshots |
117 +| `GET /admin/infrastructure` | heartbeats, archive size, DB size (`pg_database_size`), table sizes, node hostname, uptime |
118 +| `POST /admin/cache/flush` | `{ flushed: n }` |
119 +| `POST /admin/stats/recompute` · `POST /admin/quality/recompute` | maintenance |
added docs/ARCHITECTURE.md +142 −0
@@ -0,0 +1,142 @@
1 +# AI Atlas — Technical architecture
2 +
3 +> The global intelligence layer for artificial intelligence: first-party connectors → raw historical archive → deterministic and
4 +> local-LLM extraction → temporal knowledge graph → search / compare / timeline → www.ai-atlas.co + API.
5 +
6 +## 1. Principles that shape the code
7 +
8 +1. **No critical dependence on third-party data APIs.** Every source is read directly (HTML, embedded JSON, JSON-LD, RSS/Atom, sitemaps,
9 + Markdown docs, raw Git files, public JSON/CSV files). Scrapfly / Firecrawl / a headless browser are *optional escalation transports*
10 + (`Fetcher(escalate=True)`), never the database.
11 +2. **Provenance first.** Every claim, relation, price, benchmark result and event stores `source_id`, `snapshot_id`, `source_url`, `tier`,
12 + `confidence`, `extractor` and `observed_at`. Entity pages can always answer "where does this number come from?".
13 +3. **History is never disposable.** Claims are temporal (`valid_from`/`valid_to`, statuses `current|superseded|conflicting|retracted`),
14 + prices and benchmark results are append-only, raw snapshots are content-addressed and kept forever, migrations are forward-only.
15 +4. **Deterministic before LLM.** Stage 1 (DOM, JSON-LD, tables, Markdown, feeds) runs on every document. The local LLM factory
16 + (MacLustr llm-api.io through an OpenAI-compatible gateway) only sees documents flagged `needs_llm`, through versioned pydantic schemas,
17 + with full token accounting.
18 +5. **Never fabricate.** Missing = missing. Conflicts between sources are stored side by side, flagged and queued for review — never averaged.
19 +
20 +## 2. Topology
21 +
22 +```
23 + ┌──────────────── aia schedule (PM2 ai-atlas-scheduler) ─────────────────┐
24 + public AI web ──► │ connectors (registry) → Fetcher (direct/escalate) → archive (raw+text) │
25 + │ → parse → extract (Facts) → FactWriter (resolve, version, diff) │
26 + │ → jobs (llm_extract, embed, reprocess) → worker → LLM gateway │
27 + └──────────────────────────────────────────────────────────────────────────┘
28 + │ Postgres 17 (+pgvector, pg_trgm) · Redis (cache/locks) · AIA_DATA_DIR
29 + ┌──────────────────────────────┴───────────────────────────────────────────┐
30 + │ FastAPI /api/v1 (PM2 ai-atlas-api :8321) ◄── Next.js 16 (PM2 ai-atlas-web :8320) ◄── MacLustr Tunnel (BHS64 Caddy)
31 + └──────────────────────────────────────────────────────────────────────────┘
32 +```
33 +
34 +Production node: **M2M32c** (Mac Studio M2, 12 c / 32 GB, dedicated), Postgres 17 + pgvector + Redis via Homebrew, data in
35 +`~/ai-atlas-data/` (raw, text, backups, logs). Public route `https://www.ai-atlas.co → M2M32c:8320` on the MacLustr Tunnel gateway BHS64.
36 +Workers can run on any node with database access (`aia worker`), which is how the LLM factory scales across the cluster.
37 +
38 +## 3. Repository layout
39 +
40 +```
41 +registry/ curated YAML: sources.yaml (domains, tiers, crawl policy), organizations.yaml (aliases, domains, hf/github orgs),
42 + providers.yaml, benchmarks.yaml, hardware.yaml — every entry carries its source_url
43 +migrations/versions/ forward-only SQL (0001_initial.py)
44 +src/aiatlas/
45 + config.py settings (AIA_*), ids.py (prefixed ULIDs, slugify, normalize_alias), logging.py, db/ (SQLAlchemy Core + asyncpg)
46 + sdk/ connector SDK
47 + fetch.py Fetcher: robots.txt, per-domain rate limit, ETag/If-Modified-Since, retries/backoff, escalation chain
48 + archive.py content-addressed gzip store (raw/, text/) with dedupe
49 + extract/ html (selectolax; meta, JSON-LD, embedded JSON, tables, links, text), feeds, sitemap, markdown (front matter, tables),
50 + numbers (70B, 128K, $3/1M), dates (partial precision)
51 + facts.py EntityRef, Claim, Relation, Event, PriceObs, ResultObs, Target, Facts (+ MATERIAL_PROPERTIES → event types)
52 + resolution.py Resolver: identifiers → aliases (org-disambiguated) → slug → create; ambiguity → review queue
53 + writer.py FactWriter: temporal claims, attributes/provenance materialisation, conflicts, prices, results, events
54 + connector.py BaseConnector.run(): documents, snapshots, hash change detection, structural diff, DOCUMENT_CHANGED,
55 + breakage detection, circuit breaker, adaptive interval, follow-up targets, --file overrides, reprocess mode
56 + connectors/ one package per group (labs/, hub/, research/, code/, providers/, benchmarks/, hardware/); CONNECTORS = [cls]
57 + schemas/extraction.py pydantic schemas: ModelPassport, PricingExtraction, CompanyPassport, PaperPassport, BenchmarkResultExtraction, HardwareSpec, …
58 + services/
59 + jobs.py Postgres queue (SKIP LOCKED), handlers.py (llm_extract, embed_entity, reprocess_snapshot, recompute_quality)
60 + llm/gateway.py LLMGateway: stage cascade small→medium→large, OpenAI-compatible engine, JSON validation, llm_jobs accounting
61 + embeddings.py local embeddings → pgvector · search.py FTS+trigram(+vector) and NL→filters compiler
62 + scheduler.py APScheduler: due connectors (Redis lock), worker, hourly stats/quality/embeddings, nightly pg_dump
63 + quality.py transparency scores (documented in metric_definitions) · stats.py live counters · backup.py · cache.py
64 + api/ FastAPI application (see docs/API.md)
65 + cli.py `aia`: migrate seed connectors run reprocess crawl status stats quality schedule worker api backup llm embed search review
66 +apps/web/ Next.js 16 site (see docs/FRONTEND.md)
67 +tests/ pytest with saved fixtures (tests/fixtures/<connector>/…); live tests behind `-m live`
68 +deploy/ mld manifest (ai-atlas.mld.json), render-manifest.sh, first-run.sh — see docs/DEPLOY.md
69 +```
70 +
71 +## 4. Data model (Postgres)
72 +
73 +| table | role |
74 +|---|---|
75 +| `entities` | unified graph node: `entity_type`, `canonical_name`, `slug`, `organization_id`, `attributes` (current value per property), `provenance` (per property), `quality`, `counts`, `first_seen_at`, `search` tsvector |
76 +| `entity_aliases`, `entity_identifiers` | resolution keys (normalized aliases; `(scheme, value)` unique: hf_repo, github_repo, arxiv, doi, anthropic_model_id, openrouter, pypi, domain…) |
77 +| `sources`, `connectors`, `connector_runs`, `connector_errors` | source registry with tiers; connector state (health, adaptive interval, circuit, parser_version, expected_min_records) |
78 +| `documents` | one row per URL: validators (etag/last-modified), `content_hash`, counters, `entity_id`, `needs_llm` |
79 +| `snapshots` | one row per *changed* fetch: `raw_path`, `text_path`, `structured` (deterministic summary), `diff`, `transport`, `parser_version`, `processing_status` |
80 +| `claims` | temporal facts: `(entity_id, property, value jsonb, unit, tier, confidence, status, valid_from, valid_to, snapshot_id, source_url, extractor)` |
81 +| `relations` | typed edges with validity: `develops, owns, operates, available_through, evaluated_on, described_by, derived_from, fine_tuned_from, quantized_from, superseded_by, runs_on, uses, manufactures, funded_by, acquired, authored, works_at, uses_dataset, evaluates_on, integrates` |
82 +| `change_events` | the event engine: `NEW_MODEL, MODEL_UPDATED, PRICE_CHANGED, PROVIDER_LISTED, CONTEXT_CHANGED, STATUS_CHANGED, LICENSE_CHANGED, DEPRECATION_ANNOUNCED, RETIREMENT_ANNOUNCED, BENCHMARK_RESULT, BENCHMARK_UPDATED, NEW_PAPER, ANNOUNCEMENT, RELEASE, VERSION_RELEASED, DOCUMENT_CHANGED, …` with `category`, `importance 0–3`, `dedupe_key` |
83 +| `prices` | append-only provider pricing (`valid_to` closes a row): per-1M-token input/output/cached/cache-write/batch, per image/request, context, features |
84 +| `benchmark_results` | append-only results with `config` (harness, prompting, judge…) — never compared blindly |
85 +| `jobs`, `llm_jobs` | work queue; LLM cost accounting (stage, model, node, tokens, duration, status) |
86 +| `review_queue` | merge candidates, conflicts, blocked sources, parser breakage, unusual changes |
87 +| `entity_embeddings` | pgvector(1024) local embeddings |
88 +| `domains`, `stats_snapshots`, `page_views`, `api_keys`, `metric_definitions` | trust graph, counters history, trending, developer keys, documented metrics |
89 +
90 +Identifiers: prefixed ULIDs (`model_01J…`, `company_…`, `paper_…`, `snap_…`, `evt_…`). Slugs are stable, readable and unique.
91 +
92 +### Temporal rules (FactWriter)
93 +
94 +```
95 +no current claim → insert current, set attribute, NEW_<TYPE> event when the entity is new
96 +same value → confirm (observed_at)
97 +different, source ≥ tier → supersede (valid_to = observed), insert current, CHANGE event for material properties
98 +different, worse source → store as `conflicting`, mark current `conflicted`, review-queue item — never overwrite
99 +soft text (description…) → first statement wins until its own source changes; never an event
100 +metric.* / stats.* → time series without events
101 +```
102 +
103 +Historical mode = `claims` filtered by `valid_from <= date < coalesce(valid_to, ∞)`; "did it exist?" = `entities.first_seen_at <= date`.
104 +Diff A→B = new/removed entities by `first_seen_at`, claims superseded between A and B, price rows opened/closed, results observed.
105 +
106 +## 5. Connector lifecycle
107 +
108 +`discover()` returns `Target`s (URL, doc_type, optional entity hint, `needs_llm`, `key` for fixtures). For each target `run()`:
109 +fetch (conditional) → unchanged? stop · changed → archive raw + text → snapshot row (+ structural diff vs previous) → `parse()`
110 +`extract()``FactWriter.write(facts)` → follow-up targets → optional `llm_extract` job. Blocked (401/403/451/robots) → document
111 +`blocked` + review item; 404/410 twice → `gone` (never deletes entities). Fewer records than `expected_min_records` → run `suspect`
112 ++ review item. Intervals adapt: ×0.7 on change (≥ min), ×1.5 after 3 unchanged runs (≤ max). Three failures open the circuit 30 min.
113 +
114 +Parser improvements: bump `parser_version`, then `aia reprocess <connector>` replays the latest stored snapshot of every document — no crawl.
115 +
116 +## 6. LLM factory
117 +
118 +`LLMGateway.extract(task_type, document, schema, stage)` → strict JSON validated by a pydantic schema; on schema errors the next stage
119 +model is tried (small → medium → large); transport failures do not escalate. Every call is recorded in `llm_jobs` (tokens, duration,
120 +node, status, output). `facts_from_llm()` maps outputs onto `Facts` with `extractor='llm'` and medium/low confidence, so deterministic
121 +tier-1 claims always win conflicts. Embeddings use the same gateway (`/v1/embeddings`, Qwen3-Embedding 1024-d) into pgvector.
122 +Without a configured gateway the platform degrades gracefully: deterministic extraction, FTS search, no embeddings.
123 +
124 +## 7. Quality, search, events
125 +
126 +* `quality.score` = 100·(0.25 completeness + 0.25 primary-source ratio + 0.20 freshness + 0.15 agreement + 0.15 source diversity),
127 + versioned and explained in `metric_definitions` and `/methodology`. It measures how well AI Atlas knows an entity, not the entity.
128 +* Search: tsvector (name A, family B, type/description C) + `pg_trgm` similarity + aliases (+ cosine on embeddings when present).
129 + `compile_query()` turns "open models released in 2026 with more than 100B parameters and 128k context" into structured filters.
130 +* Events power the homepage feed, entity timelines, `/changes`, the daily digest and, later, watchlists/alerts.
131 +
132 +## 8. Security & compliance
133 +
134 +Admin routes require `x-aia-admin-token`. The API binds to loopback; Next.js rewrites `/api/v1/*` to it. No credentials or internal
135 +addresses in responses. Crawling honours robots.txt, identifies itself (`AIAtlasBot/0.1 … contact@spboucher.ai`), rate-limits per domain,
136 +uses conditional requests, never bypasses access controls; blocked sources go to the review queue. Raw archive content is never exposed
137 +publicly — only extracted facts with links to the original page.
138 +
139 +## 9. Backups & durability
140 +
141 +Nightly `pg_dump -Fc` into `AIA_DATA_DIR/backups` (30 kept), off-node rsync (`scripts/backup-offnode.sh`), raw archive is append-only and
142 +content-addressed (rsync-friendly). The dataset is the product: restore = `pg_restore` + point `DATABASE_URL`.
added docs/CONNECTORS.md +97 −0
@@ -0,0 +1,97 @@
1 +# Writing a connector
2 +
3 +A connector is a Python class under `src/aiatlas/connectors/<group>/<name>.py`, listed in that module's `CONNECTORS = [Cls]`.
4 +The registry auto-discovers it; `aia seed` registers it in the database; `aia run <name>` runs it; the scheduler runs it on its interval.
5 +
6 +## Skeleton
7 +
8 +```python
9 +from aiatlas.registry import org_ref, provider_ref
10 +from aiatlas.sdk.connector import BaseConnector, Parsed, RunContext
11 +from aiatlas.sdk.facts import Facts, Target
12 +from aiatlas.sdk.fetch import FetchResult
13 +
14 +class ExampleConnector(BaseConnector):
15 + name = "example" # unique, snake_case, stable (used in documents/claims/events)
16 + label = "Example Lab — models & news"
17 + description = "Official docs and blog of Example Lab."
18 + source_key = "example.com" # must exist in registry/sources.yaml (tier, rate limit, org)
19 + version = "1"; parser_version = "1" # bump parser_version when extraction improves → `aia reprocess example`
20 + interval_seconds = 3600; min_interval_seconds = 1800; max_interval_seconds = 86400
21 + rate_per_min = 15; tier = 1; priority = 0 | 1 | 2
22 + expected_min_records = 5 # breakage detection: fewer entities/prices/results ⇒ run "suspect", nothing deleted
23 + concurrency = 2
24 +
25 + async def discover(self, ctx: RunContext) -> list[Target]:
26 + return [Target(url="https://example.com/models", doc_type="model_docs", key="models", min_bytes=2000),
27 + Target(url="https://example.com/blog/rss.xml", doc_type="feed", key="feed")]
28 +
29 + async def extract(self, ctx: RunContext, target: Target, res: FetchResult, parsed: Parsed) -> Facts:
30 + facts = Facts()
31 + org = org_ref("example") # registry organization → deterministic identifiers
32 + facts.entities.append(org)
33 + if target.key == "models" and parsed.html:
34 + for row in parsed.html.tables[0]["rows"]: ...
35 + model = facts.entity("model", name, identifiers={"example_model_id": api_id}, organization=org)
36 + facts.relate(org, "develops", model)
37 + facts.claim(model, "context_length", 128000, unit="tokens")
38 + facts.price(model=model, provider=provider_ref("example"), input_per_mtok=1.0, output_per_mtok=4.0)
39 + facts.follow(detail_url, doc_type="model_page", entity=model, needs_llm=True, meta={"llm_task": "model_passport"})
40 + elif target.key == "feed" and parsed.kind == "feed":
41 + announcement_events(facts, org, parsed.feed_items, source_name="example.com/blog") # from connectors/labs/_common.py
42 + return facts
43 +
44 +CONNECTORS = [ExampleConnector]
45 +```
46 +
47 +## What `Parsed` gives you
48 +
49 +| `parsed.kind` | fields |
50 +|---|---|
51 +| `html` | `parsed.html: HtmlDoc``title, canonical, description, meta, og, json_ld, embedded_json (__NEXT_DATA__, data-props…), headings, tables [{headers, rows}], links [(href, text)], text`, `css()`, `links_matching()` ; `find_in_json(obj, key)` helper |
52 +| `markdown` | `parsed.markdown: MarkdownDoc``front_matter, headings, tables, links, text, section(pattern)` |
53 +| `feed` | `parsed.feed_items: list[FeedItem]` (`url, title, summary, published_at, categories, authors`) |
54 +| `json` | `parsed.json` |
55 +| `pdf` / `text` / `xml` | `parsed.text` |
56 +
57 +Helpers: `aiatlas.sdk.extract.numbers` (`parse_param_count("70B")`, `parse_active_params("235B-A22B")`, `parse_context_length("128K")`,
58 +`parse_money_per_mtok("$3 / 1M tokens")`, `parse_percent`), `aiatlas.sdk.extract.dates` (`parse_datetime`, `parse_date` with precision),
59 +`connectors/labs/_common.py` (`announcement_events`, `transpose_feature_table`, `kv_tables`, `clean_cell`, `money`, `tokens`, `month_year`, `parse_retirement`, `model_ref`).
60 +
61 +## Rules
62 +
63 +1. **Direct mode first.** Use official pages, feeds, sitemaps, Markdown/raw files, embedded JSON. Public JSON files (e.g. `openrouter.ai/api/v1/models`,
64 + `pypi.org/pypi/<pkg>/json`, arXiv Atom) are fine — they are public documents, not commercial APIs. Never require an API key.
65 + Set `Target(escalate=True)` only for pages known to block bots *and* only if a key is configured; otherwise let the document be `blocked`.
66 +2. **Never fabricate.** Only emit a claim when the page states it. Unknown → no claim. Don't infer parameter counts from names unless the
67 + name literally contains them (`Qwen3-235B-A22B` → 235e9 / 22e9 is fine; "Large" is not).
68 +3. **Identifiers make resolution deterministic.** Give models the provider's API id (`{provider}_model_id`), HF repo (`hf_repo`), arXiv id
69 + (`arxiv`), GitHub repo (`github_repo`), PyPI name (`pypi`). Organizations always come from `org_ref(<registry key>)` (add missing orgs to
70 + `registry/organizations.yaml` with a `source_url`).
71 +4. **Properties are shared vocabulary** (see below). Add new ones sparingly; prefix metrics with `metric.` (downloads, likes, stars) so they
72 + never generate events.
73 +5. **Events**: NEW_*, PRICE_CHANGED, CONTEXT_CHANGED… are emitted automatically by the writer. Emit `ANNOUNCEMENT`/`RELEASE` events yourself for
74 + feed items (`announcement_events`) with `effective_at` = publication date and a `dedupe_key` (URL).
75 +6. **Follow-ups** (`facts.follow`) let a listing discover detail pages; keep `max_targets` reasonable (`ctx.max_targets`, default 2000).
76 +7. **Every connector has a fixture test**: save real responses under `tests/fixtures/<connector>/…` and assert extracted facts
77 + (see `tests/test_anthropic.py`). Run connectors with `--file key=path` to use fixtures instead of the network.
78 +8. Respect `rate_per_min` from `registry/sources.yaml`; arXiv ≤ 4/min; Hugging Face ≤ 30/min; GitHub ≤ 20/min.
79 +
80 +## Property vocabulary (entities.attributes)
81 +
82 +**model**: `family, version, release_date (ISO, may be YYYY-MM), status (active|preview|deprecated|retired|announced|limited-availability), openness
83 +(open-weights|open-source|proprietary|restricted), license, architecture, parameter_count (int), active_parameter_count, is_moe, modalities
84 +(list of text|image|audio|video|code|embedding), modalities_input, modalities_output, context_length (tokens), max_output_tokens, knowledge_cutoff
85 +(YYYY-MM), training_data_cutoff, languages, tool_calling, structured_output, reasoning, vision, audio, fine_tuning_available, tokenizer,
86 +api_model_id, api_alias, official_url, model_card_url, paper_url, repository_url, hf_repo, pipeline_tag, base_model, quantization, quant_format
87 +(gguf|mlx|awq|gptq|fp8), file_size_gb, deprecation_date, retirement_date, retirement_tentative, metric.downloads, metric.likes`
88 +
89 +**company / organization / lab**: `country (ISO-2), headquarters, founded, website, domains, hf_org, github_org, org_kind, legal_name, founders, leadership, employee_count`
90 +
91 +**provider**: `website, pricing_url, docs_url, regions, features` · **paper**: `authors, published_at, updated_at, abstract, arxiv_id, doi, categories, primary_category, pdf_url, code_url, venue`
92 +· **benchmark**: `category, task, metric, unit, creator, website, paper, known_limitations, methodology` · **hardware**: `kind, architecture, release_date, memory_gb,
93 +memory_type, memory_bandwidth_gbs, tdp_watts, runtimes, manufacturer, spec_url, price_usd, compute_fp16_tflops` · **framework / repository**: `repository_url, latest_version,
94 +latest_release_at, license, language, description, topics, pypi, metric.stars, metric.forks` · **dataset**: `license, modality, size, publisher, task, hf_repo`
95 +
96 +Relations: `develops, owns, operates, available_through, evaluated_on, described_by, derived_from, fine_tuned_from, quantized_from, distilled_from,
97 +merged_from, superseded_by, runs_on, uses, manufactures, funded_by, acquired, authored, works_at, uses_dataset, evaluates_on, integrates, published_by`.
added migrations/env.py +45 −0
@@ -0,0 +1,45 @@
1 +"""Alembic environment (async engine). Migrations are plain SQL executed through `op.execute`."""
2 +from __future__ import annotations
3 +
4 +import asyncio
5 +from logging.config import fileConfig
6 +
7 +from alembic import context
8 +from sqlalchemy.ext.asyncio import create_async_engine
9 +
10 +from aiatlas.config import settings
11 +
12 +config = context.config
13 +if config.config_file_name is not None:
14 + fileConfig(config.config_file_name)
15 +
16 +target_metadata = None
17 +
18 +
19 +def run_migrations_offline() -> None:
20 + context.configure(url=settings.sync_database_url, literal_binds=True, dialect_opts={"paramstyle": "named"})
21 + with context.begin_transaction():
22 + context.run_migrations()
23 +
24 +
25 +def do_run_migrations(connection) -> None: # type: ignore[no-untyped-def]
26 + context.configure(connection=connection, target_metadata=target_metadata, transaction_per_migration=True)
27 + with context.begin_transaction():
28 + context.run_migrations()
29 +
30 +
31 +async def run_async_migrations() -> None:
32 + engine = create_async_engine(settings.database_url, poolclass=None)
33 + async with engine.connect() as connection:
34 + await connection.run_sync(do_run_migrations)
35 + await engine.dispose()
36 +
37 +
38 +def run_migrations_online() -> None:
39 + asyncio.run(run_async_migrations())
40 +
41 +
42 +if context.is_offline_mode():
43 + run_migrations_offline()
44 +else:
45 + run_migrations_online()
added migrations/script.py.mako +21 −0
@@ -0,0 +1,21 @@
1 +"""${message}
2 +
3 +Revision ID: ${up_revision}
4 +Revises: ${down_revision | comma,n}
5 +"""
6 +from __future__ import annotations
7 +
8 +from alembic import op
9 +
10 +revision = ${repr(up_revision)}
11 +down_revision = ${repr(down_revision)}
12 +branch_labels = ${repr(branch_labels)}
13 +depends_on = ${repr(depends_on)}
14 +
15 +
16 +def upgrade() -> None:
17 + ${upgrades if upgrades else "pass"}
18 +
19 +
20 +def downgrade() -> None:
21 + raise RuntimeError("forward-only")
added migrations/versions/0001_initial.py +502 −0
@@ -0,0 +1,502 @@
1 +"""AI Atlas initial schema — entities, aliases, identifiers, sources, connectors, documents, snapshots, claims, relations,
2 +change events, benchmark results, prices, jobs, LLM jobs, review queue, stats.
3 +
4 +Revision ID: 0001
5 +"""
6 +from __future__ import annotations
7 +
8 +from alembic import op
9 +
10 +revision = "0001"
11 +down_revision = None
12 +branch_labels = None
13 +depends_on = None
14 +
15 +SQL = r"""
16 +create extension if not exists pg_trgm;
17 +create extension if not exists "uuid-ossp";
18 +do $$ begin
19 + create extension if not exists vector;
20 +exception when others then
21 + raise notice 'pgvector unavailable: %', sqlerrm;
22 +end $$;
23 +
24 +-- ---------------------------------------------------------------------------------------------- reference: sources & connectors
25 +create table if not exists sources (
26 + id text primary key,
27 + key text not null unique, -- e.g. 'openai.com', 'huggingface.co', 'arxiv.org'
28 + name text not null,
29 + domain text not null,
30 + organization_id text, -- entity id of the owning organization (domain trust graph)
31 + tier smallint not null default 2, -- 1 official primary, 2 quality secondary, 3 community, 4 unverified
32 + kind text not null default 'website', -- website|docs|feed|repository|registry|dataset|leaderboard|regulator
33 + category text not null default 'lab',
34 + base_url text,
35 + robots_policy text not null default 'respect', -- respect|documented-exception
36 + rate_limit_per_min integer not null default 30,
37 + crawl_interval_s integer not null default 86400,
38 + enabled boolean not null default true,
39 + priority smallint not null default 2, -- 0 = P0
40 + notes text,
41 + meta jsonb not null default '{}'::jsonb,
42 + created_at timestamptz not null default now(),
43 + updated_at timestamptz not null default now()
44 +);
45 +
46 +create table if not exists connectors (
47 + name text primary key,
48 + source_id text references sources(id),
49 + label text not null,
50 + description text,
51 + enabled boolean not null default true,
52 + priority smallint not null default 2,
53 + interval_seconds integer not null default 3600,
54 + min_interval_seconds integer not null default 900,
55 + max_interval_seconds integer not null default 604800,
56 + parser_version text not null default '1',
57 + rate_limit_per_min integer not null default 30,
58 + owner text not null default 'ai-atlas',
59 + expected_min_records integer not null default 0, -- breakage detection: fewer records than this = suspected failure
60 + last_attempt_at timestamptz,
61 + last_success_at timestamptz,
62 + last_change_at timestamptz,
63 + next_run_at timestamptz,
64 + last_duration_ms integer,
65 + consecutive_failures integer not null default 0,
66 + consecutive_unchanged integer not null default 0,
67 + circuit_open_until timestamptz,
68 + health text not null default 'unknown', -- ok|degraded|failing|disabled|unknown
69 + meta jsonb not null default '{}'::jsonb,
70 + created_at timestamptz not null default now(),
71 + updated_at timestamptz not null default now()
72 +);
73 +
74 +create table if not exists connector_runs (
75 + id text primary key,
76 + connector_name text not null references connectors(name),
77 + started_at timestamptz not null,
78 + finished_at timestamptz,
79 + status text not null, -- running|success|unchanged|failed|skipped|suspect
80 + duration_ms integer,
81 + docs_discovered integer not null default 0,
82 + docs_fetched integer not null default 0,
83 + docs_changed integer not null default 0,
84 + docs_unchanged integer not null default 0,
85 + docs_failed integer not null default 0,
86 + entities_created integer not null default 0,
87 + entities_updated integer not null default 0,
88 + claims_written integer not null default 0,
89 + relations_written integer not null default 0,
90 + events_emitted integer not null default 0,
91 + error text,
92 + meta jsonb not null default '{}'::jsonb
93 +);
94 +create index if not exists connector_runs_name_idx on connector_runs (connector_name, started_at desc);
95 +
96 +create table if not exists connector_errors (
97 + id bigserial primary key,
98 + connector_name text not null,
99 + run_id text,
100 + url text,
101 + error_type text not null,
102 + message text not null,
103 + created_at timestamptz not null default now()
104 +);
105 +create index if not exists connector_errors_name_idx on connector_errors (connector_name, created_at desc);
106 +
107 +-- ---------------------------------------------------------------------------------------------- entities (unified graph)
108 +create table if not exists entities (
109 + id text primary key,
110 + entity_type text not null,
111 + canonical_name text not null,
112 + slug text not null unique,
113 + description text,
114 + status text not null default 'active', -- active|deprecated|retired|announced|unknown|merged
115 + organization_id text references entities(id),
116 + attributes jsonb not null default '{}'::jsonb, -- current value per property (materialised from claims)
117 + provenance jsonb not null default '{}'::jsonb, -- property -> {source, snapshot_id, url, observed_at, tier, confidence}
118 + quality jsonb not null default '{}'::jsonb, -- source_count, primary_source_ratio, freshness, completeness, agreement, score
119 + counts jsonb not null default '{}'::jsonb, -- cached relation / claim / event counts
120 + first_seen_at timestamptz not null default now(),
121 + last_seen_at timestamptz not null default now(),
122 + merged_into text references entities(id),
123 + search tsvector,
124 + created_at timestamptz not null default now(),
125 + updated_at timestamptz not null default now()
126 +);
127 +create index if not exists entities_type_idx on entities (entity_type, canonical_name);
128 +create index if not exists entities_org_idx on entities (organization_id);
129 +create index if not exists entities_search_idx on entities using gin (search);
130 +create index if not exists entities_name_trgm_idx on entities using gin (canonical_name gin_trgm_ops);
131 +create index if not exists entities_attrs_idx on entities using gin (attributes jsonb_path_ops);
132 +create index if not exists entities_updated_idx on entities (updated_at desc);
133 +create index if not exists entities_first_seen_idx on entities (first_seen_at desc);
134 +
135 +create table if not exists entity_aliases (
136 + id bigserial primary key,
137 + entity_id text not null references entities(id) on delete cascade,
138 + alias text not null,
139 + alias_norm text not null,
140 + kind text not null default 'alias', -- alias|former_name|abbreviation|localized|typo
141 + snapshot_id text,
142 + created_at timestamptz not null default now(),
143 + unique (entity_id, alias_norm)
144 +);
145 +create index if not exists entity_aliases_norm_idx on entity_aliases (alias_norm);
146 +
147 +create table if not exists entity_identifiers (
148 + id bigserial primary key,
149 + entity_id text not null references entities(id) on delete cascade,
150 + scheme text not null, -- hf_repo|github_repo|arxiv|doi|openrouter|domain|pypi|wikidata|url|provider_model_id
151 + value text not null,
152 + snapshot_id text,
153 + created_at timestamptz not null default now(),
154 + unique (scheme, value)
155 +);
156 +create index if not exists entity_identifiers_entity_idx on entity_identifiers (entity_id);
157 +
158 +-- ---------------------------------------------------------------------------------------------- documents & snapshots (raw archive)
159 +create table if not exists documents (
160 + id text primary key,
161 + source_id text references sources(id),
162 + connector_name text references connectors(name),
163 + url text not null unique,
164 + canonical_url text,
165 + doc_type text not null default 'page', -- page|feed|feed_item|model_card|docs|pricing|release|paper|pdf|json|sitemap|repo|readme|leaderboard
166 + title text,
167 + entity_id text references entities(id),
168 + status text not null default 'active', -- active|gone|blocked|error
169 + first_seen_at timestamptz not null default now(),
170 + last_fetched_at timestamptz,
171 + last_changed_at timestamptz,
172 + last_status integer,
173 + etag text,
174 + last_modified text,
175 + content_hash text,
176 + fetch_count integer not null default 0,
177 + change_count integer not null default 0,
178 + fail_count integer not null default 0,
179 + fetch_interval_s integer,
180 + next_fetch_at timestamptz,
181 + priority smallint not null default 2,
182 + needs_llm boolean not null default false,
183 + meta jsonb not null default '{}'::jsonb
184 +);
185 +create index if not exists documents_connector_idx on documents (connector_name, last_fetched_at desc);
186 +create index if not exists documents_entity_idx on documents (entity_id);
187 +create index if not exists documents_next_idx on documents (next_fetch_at) where status = 'active';
188 +
189 +create table if not exists snapshots (
190 + id text primary key,
191 + document_id text not null references documents(id) on delete cascade,
192 + run_id text,
193 + url text not null,
194 + final_url text,
195 + observed_at timestamptz not null default now(),
196 + http_status integer,
197 + headers jsonb not null default '{}'::jsonb,
198 + content_type text,
199 + content_hash text not null,
200 + byte_size integer not null default 0,
201 + raw_path text, -- content-addressed gzip under AIA_DATA_DIR/raw
202 + text_path text, -- cleaned text (gzip) under AIA_DATA_DIR/text
203 + text_hash text,
204 + structured jsonb, -- deterministic extraction (json-ld, meta, tables, embedded json)
205 + parser_version text not null default '1',
206 + connector_version text not null default '1',
207 + transport text not null default 'direct', -- direct|browser|scrapfly|firecrawl|file|git
208 + changed boolean not null default true,
209 + diff jsonb, -- structural diff vs previous changed snapshot
210 + processing_status text not null default 'stored', -- stored|extracted|llm_pending|llm_done|failed
211 + created_at timestamptz not null default now()
212 +);
213 +create index if not exists snapshots_doc_idx on snapshots (document_id, observed_at desc);
214 +create index if not exists snapshots_hash_idx on snapshots (content_hash);
215 +create index if not exists snapshots_status_idx on snapshots (processing_status) where processing_status in ('stored','llm_pending');
216 +
217 +-- ---------------------------------------------------------------------------------------------- temporal facts
218 +create table if not exists claims (
219 + id text primary key,
220 + entity_id text not null references entities(id) on delete cascade,
221 + property text not null,
222 + value jsonb not null,
223 + value_text text,
224 + value_num double precision,
225 + unit text,
226 + source_id text references sources(id),
227 + snapshot_id text references snapshots(id),
228 + source_url text,
229 + tier smallint not null default 2,
230 + confidence text not null default 'medium', -- verified|high|medium|low|conflicted
231 + status text not null default 'current', -- current|superseded|conflicting|retracted
232 + extractor text not null default 'deterministic',
233 + extractor_version text not null default '1',
234 + observed_at timestamptz not null default now(),
235 + effective_at timestamptz,
236 + valid_from timestamptz not null default now(),
237 + valid_to timestamptz,
238 + created_at timestamptz not null default now()
239 +);
240 +create index if not exists claims_entity_prop_idx on claims (entity_id, property, valid_from desc);
241 +create index if not exists claims_current_idx on claims (entity_id, property) where status = 'current';
242 +create index if not exists claims_snapshot_idx on claims (snapshot_id);
243 +create index if not exists claims_observed_idx on claims (observed_at desc);
244 +
245 +create table if not exists relations (
246 + id text primary key,
247 + subject_id text not null references entities(id) on delete cascade,
248 + predicate text not null,
249 + object_id text not null references entities(id) on delete cascade,
250 + attributes jsonb not null default '{}'::jsonb,
251 + source_id text references sources(id),
252 + snapshot_id text references snapshots(id),
253 + source_url text,
254 + tier smallint not null default 2,
255 + confidence text not null default 'medium',
256 + observed_at timestamptz not null default now(),
257 + valid_from timestamptz not null default now(),
258 + valid_to timestamptz,
259 + created_at timestamptz not null default now()
260 +);
261 +create unique index if not exists relations_live_uniq on relations (subject_id, predicate, object_id) where valid_to is null;
262 +create index if not exists relations_subject_idx on relations (subject_id, predicate);
263 +create index if not exists relations_object_idx on relations (object_id, predicate);
264 +
265 +create table if not exists change_events (
266 + id text primary key,
267 + entity_id text references entities(id) on delete cascade,
268 + event_type text not null, -- NEW_MODEL|MODEL_UPDATED|PRICE_CHANGED|CONTEXT_CHANGED|NEW_PAPER|RELEASE|BENCHMARK_RESULT|NEW_PROVIDER|DOCUMENT_CHANGED|…
269 + category text not null default 'update', -- model|price|benchmark|paper|release|company|hardware|framework|provider|dataset|regulation|incident|repository
270 + property text,
271 + old_value jsonb,
272 + new_value jsonb,
273 + summary text,
274 + importance smallint not null default 2, -- 0 minor … 3 major
275 + observed_at timestamptz not null default now(),
276 + effective_at timestamptz,
277 + source_id text references sources(id),
278 + snapshot_id text references snapshots(id),
279 + source_url text,
280 + connector_name text,
281 + dedupe_key text unique,
282 + meta jsonb not null default '{}'::jsonb
283 +);
284 +create index if not exists change_events_observed_idx on change_events (observed_at desc);
285 +create index if not exists change_events_entity_idx on change_events (entity_id, observed_at desc);
286 +create index if not exists change_events_type_idx on change_events (event_type, observed_at desc);
287 +create index if not exists change_events_category_idx on change_events (category, observed_at desc);
288 +
289 +-- ---------------------------------------------------------------------------------------------- domain tables
290 +create table if not exists benchmark_results (
291 + id text primary key,
292 + model_id text not null references entities(id) on delete cascade,
293 + benchmark_id text not null references entities(id) on delete cascade,
294 + score double precision not null,
295 + metric text,
296 + unit text,
297 + higher_is_better boolean not null default true,
298 + config jsonb not null default '{}'::jsonb, -- prompting, judge, tool use, sampling, harness, model variant string
299 + evaluated_at timestamptz,
300 + observed_at timestamptz not null default now(),
301 + source_id text references sources(id),
302 + snapshot_id text references snapshots(id),
303 + source_url text,
304 + tier smallint not null default 2,
305 + confidence text not null default 'medium',
306 + dedupe_key text unique,
307 + valid_to timestamptz
308 +);
309 +create index if not exists benchmark_results_model_idx on benchmark_results (model_id, benchmark_id, observed_at desc);
310 +create index if not exists benchmark_results_bench_idx on benchmark_results (benchmark_id, score desc);
311 +
312 +create table if not exists prices (
313 + id text primary key,
314 + model_id text not null references entities(id) on delete cascade,
315 + provider_id text not null references entities(id) on delete cascade,
316 + provider_model_id text,
317 + input_per_mtok double precision,
318 + output_per_mtok double precision,
319 + cached_input_per_mtok double precision,
320 + cache_write_per_mtok double precision,
321 + batch_input_per_mtok double precision,
322 + batch_output_per_mtok double precision,
323 + per_image double precision,
324 + per_request double precision,
325 + currency text not null default 'USD',
326 + context_length integer,
327 + max_output_tokens integer,
328 + features jsonb not null default '{}'::jsonb,
329 + observed_at timestamptz not null default now(),
330 + valid_from timestamptz not null default now(),
331 + valid_to timestamptz,
332 + source_id text references sources(id),
333 + snapshot_id text references snapshots(id),
334 + source_url text,
335 + tier smallint not null default 2,
336 + meta jsonb not null default '{}'::jsonb
337 +);
338 +create unique index if not exists prices_live_uniq on prices (model_id, provider_id, coalesce(provider_model_id, '')) where valid_to is null;
339 +create index if not exists prices_provider_idx on prices (provider_id, valid_from desc);
340 +create index if not exists prices_model_idx on prices (model_id, valid_from desc);
341 +
342 +create table if not exists domains (
343 + domain text primary key,
344 + organization_id text references entities(id),
345 + trust_tier smallint not null default 3,
346 + category text,
347 + notes text,
348 + created_at timestamptz not null default now()
349 +);
350 +
351 +-- ---------------------------------------------------------------------------------------------- work queues
352 +create table if not exists jobs (
353 + id text primary key,
354 + kind text not null, -- fetch_document|llm_extract|embed_entity|reprocess_snapshot|recompute_quality|resolve_entity
355 + payload jsonb not null default '{}'::jsonb,
356 + priority smallint not null default 5, -- 0 highest
357 + status text not null default 'queued', -- queued|running|done|failed|dead
358 + attempts integer not null default 0,
359 + max_attempts integer not null default 3,
360 + run_after timestamptz not null default now(),
361 + locked_by text,
362 + locked_at timestamptz,
363 + started_at timestamptz,
364 + finished_at timestamptz,
365 + error text,
366 + batch_id text,
367 + dedupe_key text,
368 + created_at timestamptz not null default now()
369 +);
370 +create index if not exists jobs_pick_idx on jobs (status, priority, run_after) where status = 'queued';
371 +create unique index if not exists jobs_dedupe_idx on jobs (dedupe_key) where status in ('queued','running');
372 +create index if not exists jobs_batch_idx on jobs (batch_id);
373 +
374 +create table if not exists llm_jobs (
375 + id text primary key,
376 + job_id text,
377 + task_type text not null,
378 + stage text not null, -- small|medium|large
379 + engine text not null,
380 + model text not null,
381 + node text,
382 + schema_name text,
383 + snapshot_id text references snapshots(id),
384 + entity_id text references entities(id),
385 + input_tokens integer,
386 + output_tokens integer,
387 + duration_ms integer,
388 + status text not null, -- ok|failed|invalid_json|schema_error
389 + output jsonb,
390 + error text,
391 + created_at timestamptz not null default now()
392 +);
393 +create index if not exists llm_jobs_created_idx on llm_jobs (created_at desc);
394 +
395 +create table if not exists review_queue (
396 + id text primary key,
397 + kind text not null, -- merge_candidate|conflict|blocked_source|parser_breakage|unusual_change|new_source
398 + entity_ids text[] not null default '{}',
399 + payload jsonb not null default '{}'::jsonb,
400 + reason text not null,
401 + status text not null default 'pending', -- pending|approved|rejected|edited
402 + resolution jsonb,
403 + created_at timestamptz not null default now(),
404 + resolved_at timestamptz,
405 + dedupe_key text unique
406 +);
407 +create index if not exists review_queue_status_idx on review_queue (status, created_at desc);
408 +
409 +-- ---------------------------------------------------------------------------------------------- embeddings (optional; local models)
410 +do $$ begin
411 + if exists (select 1 from pg_extension where extname = 'vector') then
412 + execute 'create table if not exists entity_embeddings (
413 + entity_id text primary key references entities(id) on delete cascade,
414 + model text not null,
415 + embedding vector(1024) not null,
416 + text_hash text not null,
417 + created_at timestamptz not null default now())';
418 + end if;
419 +end $$;
420 +
421 +-- ---------------------------------------------------------------------------------------------- stats, views, api keys
422 +create table if not exists stats_snapshots (
423 + id bigserial primary key,
424 + computed_at timestamptz not null default now(),
425 + counts jsonb not null
426 +);
427 +
428 +create table if not exists page_views (
429 + path text not null,
430 + day date not null,
431 + views integer not null default 0,
432 + primary key (path, day)
433 +);
434 +
435 +create table if not exists api_keys (
436 + id text primary key,
437 + key_hash text not null unique,
438 + label text not null,
439 + owner_email text,
440 + plan text not null default 'developer',
441 + rate_per_min integer not null default 60,
442 + enabled boolean not null default true,
443 + created_at timestamptz not null default now(),
444 + last_used_at timestamptz,
445 + usage_count bigint not null default 0
446 +);
447 +
448 +create table if not exists metric_definitions (
449 + key text primary key,
450 + label text not null,
451 + version text not null,
452 + description text not null,
453 + formula text,
454 + created_at timestamptz not null default now()
455 +);
456 +
457 +-- ---------------------------------------------------------------------------------------------- search vector maintenance
458 +create or replace function entities_search_update() returns trigger language plpgsql as $$
459 +begin
460 + new.search :=
461 + setweight(to_tsvector('simple', coalesce(new.canonical_name, '')), 'A') ||
462 + setweight(to_tsvector('simple', coalesce(new.attributes->>'family', '')), 'B') ||
463 + setweight(to_tsvector('simple', coalesce(new.entity_type, '')), 'C') ||
464 + setweight(to_tsvector('english', left(coalesce(new.description, ''), 4000)), 'C');
465 + new.updated_at := now();
466 + return new;
467 +end $$;
468 +drop trigger if exists entities_search_trg on entities;
469 +create trigger entities_search_trg before insert or update of canonical_name, description, attributes, entity_type on entities
470 + for each row execute function entities_search_update();
471 +"""
472 +
473 +
474 +def upgrade() -> None:
475 + for statement in _split(SQL):
476 + op.execute(statement)
477 +
478 +
479 +def downgrade() -> None:
480 + raise RuntimeError("AI Atlas migrations are forward-only: historical data is never disposable")
481 +
482 +
483 +def _split(sql: str) -> list[str]:
484 + """Split on semicolons outside `$$ … $$` blocks."""
485 + out: list[str] = []
486 + buf: list[str] = []
487 + in_dollar = False
488 + for line in sql.splitlines():
489 + stripped = line.strip()
490 + if stripped.count("$$") % 2 == 1:
491 + in_dollar = not in_dollar
492 + buf.append(line)
493 + if not in_dollar and stripped.endswith(";"):
494 + body = [ln for ln in buf if not ln.strip().startswith("--") or in_dollar]
495 + stmt = "\n".join(body).strip()
496 + if stmt:
497 + out.append(stmt)
498 + buf = []
499 + tail = "\n".join(ln for ln in buf if not ln.strip().startswith("--")).strip()
500 + if tail:
501 + out.append(tail)
502 + return out
added package.json +15 −0
@@ -0,0 +1,15 @@
1 +{
2 + "name": "ai-atlas",
3 + "version": "0.1.0",
4 + "private": true,
5 + "description": "AI Atlas — explore the entire AI ecosystem. Web workspace (backend is Python, see pyproject.toml).",
6 + "packageManager": "pnpm@11.1.2",
7 + "engines": { "node": ">=22" },
8 + "scripts": {
9 + "dev:web": "pnpm --filter @ai-atlas/web run dev",
10 + "build": "pnpm --filter @ai-atlas/web run build",
11 + "start:web": "pnpm --filter @ai-atlas/web run start",
12 + "typecheck": "pnpm -r run typecheck",
13 + "qa": "pnpm --filter @ai-atlas/web run qa"
14 + }
15 +}
added pnpm-workspace.yaml +2 −0
@@ -0,0 +1,2 @@
1 +packages:
2 + - apps/*
added pyproject.toml +55 −0
@@ -0,0 +1,55 @@
1 +[project]
2 +name = "aiatlas"
3 +version = "0.1.0"
4 +description = "AI Atlas — the global intelligence layer for artificial intelligence: first-party connectors, raw historical archive, temporal knowledge graph, local LLM extraction factory and public API"
5 +requires-python = ">=3.12"
6 +dependencies = [
7 + "fastapi>=0.115",
8 + "uvicorn[standard]>=0.30",
9 + "pydantic>=2.8",
10 + "pydantic-settings>=2.4",
11 + "sqlalchemy[asyncio]>=2.0.35",
12 + "asyncpg>=0.30",
13 + "alembic>=1.13",
14 + "httpx[http2]>=0.27",
15 + "orjson>=3.10",
16 + "typer>=0.12",
17 + "rich>=13",
18 + "redis>=5.1",
19 + "apscheduler>=3.10,<4",
20 + "python-ulid>=2.7",
21 + "pyyaml>=6",
22 + "python-dateutil>=2.9",
23 + "tenacity>=9",
24 + "python-slugify>=8",
25 + "selectolax>=0.3.21",
26 + "feedparser>=6.0.11",
27 + "markdown-it-py>=3.0",
28 + "pypdf>=5.0",
29 + "rapidfuzz>=3.9",
30 + "pgvector>=0.3",
31 + "numpy>=2",
32 +]
33 +
34 +[project.optional-dependencies]
35 +dev = ["pytest>=8", "pytest-asyncio>=0.24", "ruff>=0.6", "respx>=0.21"]
36 +browser = ["playwright>=1.47"]
37 +
38 +[project.scripts]
39 +aia = "aiatlas.cli:app"
40 +
41 +[build-system]
42 +requires = ["hatchling"]
43 +build-backend = "hatchling.build"
44 +
45 +[tool.hatch.build.targets.wheel]
46 +packages = ["src/aiatlas"]
47 +
48 +[tool.ruff]
49 +line-length = 120
50 +target-version = "py312"
51 +
52 +[tool.pytest.ini_options]
53 +testpaths = ["tests"]
54 +asyncio_mode = "auto"
55 +markers = ["live: hits real external endpoints (skipped unless -m live)"]
added registry/benchmarks.d/.gitkeep +0 −0
added registry/benchmarks.yaml +173 −0
@@ -0,0 +1,173 @@
1 +# Benchmark definitions (entities of type `benchmark`). Results come from connectors; definitions are curated with sources.
2 +benchmarks:
3 + - key: mmlu
4 + name: MMLU
5 + aliases: [Massive Multitask Language Understanding]
6 + category: knowledge
7 + task: 57-subject multiple-choice questions
8 + metric: accuracy
9 + unit: "%"
10 + creator: Hendrycks et al.
11 + website: https://github.com/hendrycks/test
12 + paper: https://arxiv.org/abs/2009.03300
13 + known_limitations: Widespread training-data contamination; saturated at the frontier.
14 + source_url: https://arxiv.org/abs/2009.03300
15 + - key: mmlu-pro
16 + name: MMLU-Pro
17 + category: knowledge
18 + task: harder, 10-option MMLU variant
19 + metric: accuracy
20 + unit: "%"
21 + website: https://github.com/TIGER-AI-Lab/MMLU-Pro
22 + paper: https://arxiv.org/abs/2406.01574
23 + source_url: https://arxiv.org/abs/2406.01574
24 + - key: gpqa
25 + name: GPQA
26 + aliases: [GPQA Diamond]
27 + category: reasoning
28 + task: graduate-level science questions
29 + metric: accuracy
30 + unit: "%"
31 + website: https://github.com/idavidrein/gpqa
32 + paper: https://arxiv.org/abs/2311.12022
33 + source_url: https://arxiv.org/abs/2311.12022
34 + - key: humaneval
35 + name: HumanEval
36 + category: coding
37 + task: Python function synthesis from docstrings
38 + metric: pass@1
39 + unit: "%"
40 + website: https://github.com/openai/human-eval
41 + paper: https://arxiv.org/abs/2107.03374
42 + known_limitations: Saturated; small (164 problems).
43 + source_url: https://arxiv.org/abs/2107.03374
44 + - key: swe-bench-verified
45 + name: SWE-bench Verified
46 + aliases: [SWE-bench]
47 + category: coding
48 + task: resolve real GitHub issues (500 human-validated instances)
49 + metric: resolved
50 + unit: "%"
51 + website: https://www.swebench.com
52 + paper: https://arxiv.org/abs/2310.06770
53 + known_limitations: Scaffold/agent dependent; results are not comparable across harnesses.
54 + source_url: https://www.swebench.com/
55 + - key: aider-polyglot
56 + name: Aider polyglot
57 + aliases: [Aider polyglot coding leaderboard]
58 + category: coding
59 + task: 225 Exercism exercises in 6 languages, edit-format aware
60 + metric: pass rate (2 attempts)
61 + unit: "%"
62 + website: https://aider.chat/docs/leaderboards/
63 + known_limitations: Depends on aider's edit format and prompting; cost column depends on provider pricing.
64 + source_url: https://aider.chat/docs/leaderboards/
65 + - key: livebench
66 + name: LiveBench
67 + category: general
68 + task: contamination-limited, monthly refreshed questions across 6 categories
69 + metric: average score
70 + unit: "%"
71 + website: https://livebench.ai
72 + paper: https://arxiv.org/abs/2406.19314
73 + source_url: https://livebench.ai/
74 + - key: math-500
75 + name: MATH-500
76 + aliases: [MATH]
77 + category: math
78 + task: competition mathematics
79 + metric: accuracy
80 + unit: "%"
81 + paper: https://arxiv.org/abs/2103.03874
82 + source_url: https://arxiv.org/abs/2103.03874
83 + - key: aime-2025
84 + name: AIME 2025
85 + aliases: [AIME]
86 + category: math
87 + task: American Invitational Mathematics Examination problems
88 + metric: accuracy
89 + unit: "%"
90 + known_limitations: 30 problems per year; high variance; often reported with majority voting.
91 + source_url: https://maa.org/maa-invitational-competitions/
92 + - key: arc-agi
93 + name: ARC-AGI
94 + aliases: [ARC-AGI-1, ARC-AGI-2, Abstraction and Reasoning Corpus]
95 + category: reasoning
96 + task: novel visual abstraction puzzles
97 + metric: accuracy
98 + unit: "%"
99 + website: https://arcprize.org
100 + source_url: https://arcprize.org/
101 + - key: humanitys-last-exam
102 + name: Humanity's Last Exam
103 + aliases: [HLE]
104 + category: knowledge
105 + task: expert-written frontier questions
106 + metric: accuracy
107 + unit: "%"
108 + website: https://lastexam.ai
109 + paper: https://arxiv.org/abs/2501.14249
110 + source_url: https://lastexam.ai/
111 + - key: lmarena-text
112 + name: LMArena text leaderboard
113 + aliases: [Chatbot Arena, LMSYS Chatbot Arena, Arena Elo]
114 + category: preference
115 + task: crowdsourced pairwise human preference
116 + metric: Elo / Bradley–Terry score
117 + unit: ""
118 + website: https://lmarena.ai
119 + known_limitations: Style bias; sampling of prompts by users.
120 + source_url: https://lmarena.ai/
121 + - key: mmmu
122 + name: MMMU
123 + category: multimodal
124 + task: college-level multimodal understanding
125 + metric: accuracy
126 + unit: "%"
127 + website: https://mmmu-benchmark.github.io
128 + paper: https://arxiv.org/abs/2311.16502
129 + source_url: https://arxiv.org/abs/2311.16502
130 + - key: tau-bench
131 + name: τ-bench
132 + aliases: [tau-bench, TAU-bench]
133 + category: agentic
134 + task: tool-agent-user interaction in retail/airline domains
135 + metric: pass^1
136 + unit: "%"
137 + paper: https://arxiv.org/abs/2406.12045
138 + source_url: https://arxiv.org/abs/2406.12045
139 + - key: terminal-bench
140 + name: Terminal-Bench
141 + category: agentic
142 + task: terminal tasks solved by agents
143 + metric: accuracy
144 + unit: "%"
145 + website: https://www.tbench.ai
146 + source_url: https://www.tbench.ai/
147 + - key: ifeval
148 + name: IFEval
149 + category: instruction-following
150 + task: verifiable instruction following
151 + metric: prompt-level strict accuracy
152 + unit: "%"
153 + paper: https://arxiv.org/abs/2311.07911
154 + source_url: https://arxiv.org/abs/2311.07911
155 + - key: mteb
156 + name: MTEB
157 + aliases: [Massive Text Embedding Benchmark]
158 + category: embeddings
159 + task: embedding tasks across retrieval, classification, clustering…
160 + metric: mean score
161 + unit: ""
162 + website: https://huggingface.co/spaces/mteb/leaderboard
163 + paper: https://arxiv.org/abs/2210.07316
164 + source_url: https://arxiv.org/abs/2210.07316
165 + - key: artificial-analysis-intelligence-index
166 + name: Artificial Analysis Intelligence Index
167 + category: composite
168 + task: composite of several evaluations run by Artificial Analysis
169 + metric: index
170 + unit: ""
171 + website: https://artificialanalysis.ai
172 + known_limitations: Proprietary composite; methodology versions change.
173 + source_url: https://artificialanalysis.ai/methodology
added registry/hardware.d/.gitkeep +0 −0
added registry/hardware.yaml +259 −0
@@ -0,0 +1,259 @@
1 +# Curated hardware registry (entities of type `hardware`), used by the hardware compatibility engine.
2 +# Only manufacturer-published figures; each entry cites the spec page it was read from. Fields not published are omitted.
3 +# memory_gb may be a list when the product ships with several configurations.
4 +hardware:
5 + # ---------------------------------------------------------------- Apple Silicon (unified memory)
6 + - key: apple-m1
7 + name: Apple M1
8 + manufacturer: apple
9 + kind: soc
10 + architecture: Apple Silicon (Firestorm/Icestorm)
11 + release_date: "2020-11"
12 + memory_gb: [8, 16]
13 + memory_bandwidth_gbs: 68.25
14 + runtimes: [mlx, llama.cpp, coreml]
15 + source_url: https://support.apple.com/en-us/111883
16 + - key: apple-m1-pro
17 + name: Apple M1 Pro
18 + manufacturer: apple
19 + kind: soc
20 + release_date: "2021-10"
21 + memory_gb: [16, 32]
22 + memory_bandwidth_gbs: 200
23 + runtimes: [mlx, llama.cpp, coreml]
24 + source_url: https://support.apple.com/en-us/111902
25 + - key: apple-m1-max
26 + name: Apple M1 Max
27 + manufacturer: apple
28 + kind: soc
29 + release_date: "2021-10"
30 + memory_gb: [32, 64]
31 + memory_bandwidth_gbs: 400
32 + runtimes: [mlx, llama.cpp, coreml]
33 + source_url: https://support.apple.com/en-us/111902
34 + - key: apple-m1-ultra
35 + name: Apple M1 Ultra
36 + manufacturer: apple
37 + kind: soc
38 + release_date: "2022-03"
39 + memory_gb: [64, 128]
40 + memory_bandwidth_gbs: 800
41 + runtimes: [mlx, llama.cpp, coreml]
42 + source_url: https://support.apple.com/en-us/111900
43 + - key: apple-m2
44 + name: Apple M2
45 + manufacturer: apple
46 + kind: soc
47 + release_date: "2022-06"
48 + memory_gb: [8, 16, 24]
49 + memory_bandwidth_gbs: 100
50 + runtimes: [mlx, llama.cpp, coreml]
51 + source_url: https://support.apple.com/en-us/111837
52 + - key: apple-m2-pro
53 + name: Apple M2 Pro
54 + manufacturer: apple
55 + kind: soc
56 + release_date: "2023-01"
57 + memory_gb: [16, 32]
58 + memory_bandwidth_gbs: 200
59 + runtimes: [mlx, llama.cpp, coreml]
60 + source_url: https://support.apple.com/en-us/111837
61 + - key: apple-m2-max
62 + name: Apple M2 Max
63 + manufacturer: apple
64 + kind: soc
65 + release_date: "2023-01"
66 + memory_gb: [32, 64, 96]
67 + memory_bandwidth_gbs: 400
68 + runtimes: [mlx, llama.cpp, coreml]
69 + source_url: https://support.apple.com/en-us/111835
70 + - key: apple-m2-ultra
71 + name: Apple M2 Ultra
72 + manufacturer: apple
73 + kind: soc
74 + release_date: "2023-06"
75 + memory_gb: [64, 128, 192]
76 + memory_bandwidth_gbs: 800
77 + runtimes: [mlx, llama.cpp, coreml]
78 + source_url: https://support.apple.com/en-us/111835
79 + - key: apple-m3
80 + name: Apple M3
81 + manufacturer: apple
82 + kind: soc
83 + release_date: "2023-10"
84 + memory_gb: [8, 16, 24]
85 + memory_bandwidth_gbs: 100
86 + runtimes: [mlx, llama.cpp, coreml]
87 + source_url: https://support.apple.com/en-us/117735
88 + - key: apple-m3-pro
89 + name: Apple M3 Pro
90 + manufacturer: apple
91 + kind: soc
92 + release_date: "2023-10"
93 + memory_gb: [18, 36]
94 + memory_bandwidth_gbs: 150
95 + runtimes: [mlx, llama.cpp, coreml]
96 + source_url: https://support.apple.com/en-us/117736
97 + - key: apple-m3-max
98 + name: Apple M3 Max
99 + manufacturer: apple
100 + kind: soc
101 + release_date: "2023-10"
102 + memory_gb: [36, 48, 64, 96, 128]
103 + memory_bandwidth_gbs: 400
104 + runtimes: [mlx, llama.cpp, coreml]
105 + source_url: https://support.apple.com/en-us/117736
106 + - key: apple-m3-ultra
107 + name: Apple M3 Ultra
108 + manufacturer: apple
109 + kind: soc
110 + release_date: "2025-03"
111 + memory_gb: [96, 256, 512]
112 + memory_bandwidth_gbs: 819
113 + runtimes: [mlx, llama.cpp, coreml]
114 + source_url: https://www.apple.com/mac-studio/specs/
115 + - key: apple-m4
116 + name: Apple M4
117 + manufacturer: apple
118 + kind: soc
119 + release_date: "2024-05"
120 + memory_gb: [16, 24, 32]
121 + memory_bandwidth_gbs: 120
122 + runtimes: [mlx, llama.cpp, coreml]
123 + source_url: https://www.apple.com/mac-mini/specs/
124 + - key: apple-m4-pro
125 + name: Apple M4 Pro
126 + manufacturer: apple
127 + kind: soc
128 + release_date: "2024-10"
129 + memory_gb: [24, 48, 64]
130 + memory_bandwidth_gbs: 273
131 + runtimes: [mlx, llama.cpp, coreml]
132 + source_url: https://www.apple.com/mac-mini/specs/
133 + - key: apple-m4-max
134 + name: Apple M4 Max
135 + manufacturer: apple
136 + kind: soc
137 + release_date: "2024-10"
138 + memory_gb: [36, 48, 64, 128]
139 + memory_bandwidth_gbs: 546
140 + runtimes: [mlx, llama.cpp, coreml]
141 + source_url: https://www.apple.com/mac-studio/specs/
142 + # ---------------------------------------------------------------- NVIDIA data center
143 + - key: nvidia-a100-80gb
144 + name: NVIDIA A100 80GB
145 + manufacturer: nvidia
146 + kind: gpu
147 + architecture: Ampere
148 + release_date: "2020-11"
149 + memory_gb: 80
150 + memory_type: HBM2e
151 + memory_bandwidth_gbs: 2039
152 + tdp_watts: 400
153 + runtimes: [cuda, tensorrt-llm, vllm, sglang, llama.cpp]
154 + source_url: https://www.nvidia.com/en-us/data-center/a100/
155 + - key: nvidia-h100-sxm
156 + name: NVIDIA H100 SXM
157 + manufacturer: nvidia
158 + kind: gpu
159 + architecture: Hopper
160 + release_date: "2022-09"
161 + memory_gb: 80
162 + memory_type: HBM3
163 + memory_bandwidth_gbs: 3350
164 + tdp_watts: 700
165 + runtimes: [cuda, tensorrt-llm, vllm, sglang, llama.cpp]
166 + source_url: https://www.nvidia.com/en-us/data-center/h100/
167 + - key: nvidia-h200
168 + name: NVIDIA H200
169 + manufacturer: nvidia
170 + kind: gpu
171 + architecture: Hopper
172 + release_date: "2024"
173 + memory_gb: 141
174 + memory_type: HBM3e
175 + memory_bandwidth_gbs: 4800
176 + tdp_watts: 700
177 + runtimes: [cuda, tensorrt-llm, vllm, sglang, llama.cpp]
178 + source_url: https://www.nvidia.com/en-us/data-center/h200/
179 + - key: nvidia-b200
180 + name: NVIDIA B200
181 + manufacturer: nvidia
182 + kind: gpu
183 + architecture: Blackwell
184 + release_date: "2024-03"
185 + memory_gb: 180
186 + memory_type: HBM3e
187 + runtimes: [cuda, tensorrt-llm, vllm, sglang]
188 + source_url: https://www.nvidia.com/en-us/data-center/dgx-b200/
189 + - key: nvidia-rtx-4090
190 + name: NVIDIA GeForce RTX 4090
191 + manufacturer: nvidia
192 + kind: gpu
193 + architecture: Ada Lovelace
194 + release_date: "2022-10"
195 + memory_gb: 24
196 + memory_type: GDDR6X
197 + memory_bandwidth_gbs: 1008
198 + tdp_watts: 450
199 + runtimes: [cuda, vllm, llama.cpp, exllama]
200 + source_url: https://www.nvidia.com/en-us/geforce/graphics-cards/40-series/rtx-4090/
201 + - key: nvidia-rtx-5090
202 + name: NVIDIA GeForce RTX 5090
203 + manufacturer: nvidia
204 + kind: gpu
205 + architecture: Blackwell
206 + release_date: "2025-01"
207 + memory_gb: 32
208 + memory_type: GDDR7
209 + memory_bandwidth_gbs: 1792
210 + tdp_watts: 575
211 + runtimes: [cuda, vllm, llama.cpp, exllama]
212 + source_url: https://www.nvidia.com/en-us/geforce/graphics-cards/50-series/rtx-5090/
213 + - key: nvidia-rtx-3090
214 + name: NVIDIA GeForce RTX 3090
215 + manufacturer: nvidia
216 + kind: gpu
217 + architecture: Ampere
218 + release_date: "2020-09"
219 + memory_gb: 24
220 + memory_type: GDDR6X
221 + memory_bandwidth_gbs: 936
222 + tdp_watts: 350
223 + runtimes: [cuda, vllm, llama.cpp, exllama]
224 + source_url: https://www.nvidia.com/en-us/geforce/graphics-cards/30-series/rtx-3090-3090ti/
225 + - key: nvidia-dgx-spark
226 + name: NVIDIA DGX Spark
227 + manufacturer: nvidia
228 + kind: system
229 + architecture: Grace Blackwell (GB10)
230 + release_date: "2025"
231 + memory_gb: 128
232 + memory_type: LPDDR5x
233 + memory_bandwidth_gbs: 273
234 + runtimes: [cuda, tensorrt-llm, vllm, llama.cpp]
235 + source_url: https://www.nvidia.com/en-us/products/workstations/dgx-spark/
236 + # ---------------------------------------------------------------- AMD
237 + - key: amd-instinct-mi300x
238 + name: AMD Instinct MI300X
239 + manufacturer: amd
240 + kind: gpu
241 + architecture: CDNA 3
242 + release_date: "2023-12"
243 + memory_gb: 192
244 + memory_type: HBM3
245 + memory_bandwidth_gbs: 5300
246 + tdp_watts: 750
247 + runtimes: [rocm, vllm, sglang, llama.cpp]
248 + source_url: https://www.amd.com/en/products/accelerators/instinct/mi300/mi300x.html
249 + - key: amd-instinct-mi325x
250 + name: AMD Instinct MI325X
251 + manufacturer: amd
252 + kind: gpu
253 + architecture: CDNA 3
254 + release_date: "2024-10"
255 + memory_gb: 256
256 + memory_type: HBM3e
257 + memory_bandwidth_gbs: 6000
258 + runtimes: [rocm, vllm, sglang]
259 + source_url: https://www.amd.com/en/products/accelerators/instinct/mi300/mi325x.html
added registry/organizations.d/.gitkeep +0 −0
added registry/organizations.yaml +619 −0
@@ -0,0 +1,619 @@
1 +# Canonical organizations (companies, labs, universities, foundations). Deterministic aliases and identifiers feed entity resolution;
2 +# every factual attribute carries the page it was read from (`source_url`). Fields not known are omitted — never guessed.
3 +organizations:
4 + - key: openai
5 + name: OpenAI
6 + type: company
7 + aliases: [OpenAI Inc., OpenAI, L.P., OpenAI OpCo]
8 + domains: [openai.com, platform.openai.com, chatgpt.com]
9 + hf_org: openai
10 + github_org: openai
11 + country: US
12 + headquarters: San Francisco, California
13 + founded: "2015"
14 + website: https://openai.com
15 + source_url: https://openai.com/about/
16 + - key: anthropic
17 + name: Anthropic
18 + type: company
19 + aliases: [Anthropic PBC]
20 + domains: [anthropic.com, claude.com, docs.claude.com, claude.ai]
21 + hf_org: Anthropic
22 + github_org: anthropics
23 + country: US
24 + headquarters: San Francisco, California
25 + founded: "2021"
26 + website: https://www.anthropic.com
27 + source_url: https://www.anthropic.com/company
28 + - key: google
29 + name: Google
30 + type: company
31 + aliases: [Google LLC, Alphabet, Google AI, Google Research]
32 + domains: [google.com, ai.google, ai.google.dev, research.google, blog.google, cloud.google.com]
33 + hf_org: google
34 + github_org: google
35 + country: US
36 + headquarters: Mountain View, California
37 + website: https://ai.google
38 + source_url: https://ai.google/
39 + - key: google-deepmind
40 + name: Google DeepMind
41 + type: lab
42 + aliases: [DeepMind, DeepMind Technologies, Google Brain]
43 + domains: [deepmind.google, deepmind.com]
44 + github_org: google-deepmind
45 + parent: google
46 + country: GB
47 + headquarters: London
48 + founded: "2010"
49 + website: https://deepmind.google
50 + source_url: https://deepmind.google/about/
51 + - key: meta
52 + name: Meta Platforms
53 + type: company
54 + aliases: [Meta, Facebook, Facebook Inc.]
55 + domains: [meta.com, about.fb.com]
56 + country: US
57 + headquarters: Menlo Park, California
58 + website: https://about.meta.com
59 + source_url: https://about.meta.com/company-info/
60 + - key: meta-ai
61 + name: Meta AI
62 + type: lab
63 + aliases: [FAIR, Facebook AI Research, Meta FAIR, Meta AI Research]
64 + domains: [ai.meta.com, llama.com, ai.facebook.com]
65 + hf_org: meta-llama
66 + github_org: facebookresearch
67 + parent: meta
68 + country: US
69 + website: https://ai.meta.com
70 + source_url: https://ai.meta.com/about/
71 + - key: microsoft
72 + name: Microsoft
73 + type: company
74 + aliases: [Microsoft Corporation, Microsoft Research, Microsoft AI, Azure AI]
75 + domains: [microsoft.com, azure.microsoft.com, learn.microsoft.com]
76 + hf_org: microsoft
77 + github_org: microsoft
78 + country: US
79 + headquarters: Redmond, Washington
80 + founded: "1975"
81 + website: https://www.microsoft.com
82 + source_url: https://www.microsoft.com/en-us/about
83 + - key: nvidia
84 + name: NVIDIA
85 + type: company
86 + aliases: [NVIDIA Corporation, Nvidia, NVIDIA AI, NVIDIA Research]
87 + domains: [nvidia.com, developer.nvidia.com, blogs.nvidia.com, build.nvidia.com]
88 + hf_org: nvidia
89 + github_org: NVIDIA
90 + country: US
91 + headquarters: Santa Clara, California
92 + founded: "1993"
93 + website: https://www.nvidia.com
94 + source_url: https://www.nvidia.com/en-us/about-nvidia/
95 + - key: apple
96 + name: Apple
97 + type: company
98 + aliases: [Apple Inc., Apple Machine Learning Research]
99 + domains: [apple.com, machinelearning.apple.com]
100 + hf_org: apple
101 + github_org: apple
102 + country: US
103 + headquarters: Cupertino, California
104 + founded: "1976"
105 + website: https://www.apple.com
106 + source_url: https://www.apple.com/newsroom/
107 + - key: mistral
108 + name: Mistral AI
109 + type: company
110 + aliases: [Mistral, MistralAI]
111 + domains: [mistral.ai, docs.mistral.ai, console.mistral.ai]
112 + hf_org: mistralai
113 + github_org: mistralai
114 + country: FR
115 + headquarters: Paris
116 + founded: "2023"
117 + website: https://mistral.ai
118 + source_url: https://mistral.ai/company
119 + - key: alibaba
120 + name: Alibaba Group
121 + type: company
122 + aliases: [Alibaba, Alibaba Cloud, Aliyun]
123 + domains: [alibabacloud.com, alibaba.com]
124 + country: CN
125 + headquarters: Hangzhou
126 + website: https://www.alibabagroup.com
127 + source_url: https://www.alibabagroup.com/en-US/about-alibaba
128 + - key: qwen
129 + name: Qwen
130 + type: lab
131 + aliases: [Qwen Team, Alibaba Qwen, Tongyi Qianwen, QwenLM]
132 + domains: [qwenlm.github.io, qwen.ai, chat.qwen.ai]
133 + hf_org: Qwen
134 + github_org: QwenLM
135 + parent: alibaba
136 + country: CN
137 + website: https://qwenlm.github.io
138 + source_url: https://qwenlm.github.io/
139 + - key: deepseek
140 + name: DeepSeek
141 + type: company
142 + aliases: [DeepSeek AI, DeepSeek-AI, Hangzhou DeepSeek Artificial Intelligence]
143 + domains: [deepseek.com, api-docs.deepseek.com, chat.deepseek.com]
144 + hf_org: deepseek-ai
145 + github_org: deepseek-ai
146 + country: CN
147 + headquarters: Hangzhou
148 + founded: "2023"
149 + website: https://www.deepseek.com
150 + source_url: https://www.deepseek.com/
151 + - key: cohere
152 + name: Cohere
153 + type: company
154 + aliases: [Cohere Inc., Cohere For AI, C4AI]
155 + domains: [cohere.com, docs.cohere.com, cohere.ai]
156 + hf_org: CohereLabs
157 + github_org: cohere-ai
158 + country: CA
159 + headquarters: Toronto
160 + founded: "2019"
161 + website: https://cohere.com
162 + source_url: https://cohere.com/about
163 + - key: xai
164 + name: xAI
165 + type: company
166 + aliases: [x.ai, xAI Corp]
167 + domains: [x.ai, docs.x.ai]
168 + hf_org: xai-org
169 + github_org: xai-org
170 + country: US
171 + founded: "2023"
172 + website: https://x.ai
173 + source_url: https://x.ai/about
174 + - key: huggingface
175 + name: Hugging Face
176 + type: company
177 + aliases: [HuggingFace, HF]
178 + domains: [huggingface.co, hf.co]
179 + hf_org: HuggingFaceTB
180 + github_org: huggingface
181 + country: US
182 + headquarters: New York
183 + founded: "2016"
184 + website: https://huggingface.co
185 + source_url: https://huggingface.co/huggingface
186 + - key: stability-ai
187 + name: Stability AI
188 + type: company
189 + aliases: [StabilityAI]
190 + domains: [stability.ai]
191 + hf_org: stabilityai
192 + github_org: Stability-AI
193 + country: GB
194 + website: https://stability.ai
195 + source_url: https://stability.ai/about
196 + - key: ai21
197 + name: AI21 Labs
198 + type: company
199 + aliases: [AI21]
200 + domains: [ai21.com]
201 + hf_org: ai21labs
202 + github_org: AI21Labs
203 + country: IL
204 + headquarters: Tel Aviv
205 + website: https://www.ai21.com
206 + source_url: https://www.ai21.com/about
207 + - key: together-ai
208 + name: Together AI
209 + type: company
210 + aliases: [Together, Together Computer]
211 + domains: [together.ai, together.xyz]
212 + hf_org: togethercomputer
213 + github_org: togethercomputer
214 + country: US
215 + website: https://www.together.ai
216 + source_url: https://www.together.ai/about
217 + - key: fireworks-ai
218 + name: Fireworks AI
219 + type: company
220 + aliases: [Fireworks]
221 + domains: [fireworks.ai]
222 + hf_org: fireworks-ai
223 + github_org: fw-ai
224 + country: US
225 + website: https://fireworks.ai
226 + source_url: https://fireworks.ai/about
227 + - key: groq
228 + name: Groq
229 + type: company
230 + aliases: [Groq Inc., GroqCloud]
231 + domains: [groq.com, console.groq.com]
232 + github_org: groq
233 + country: US
234 + headquarters: Mountain View, California
235 + website: https://groq.com
236 + source_url: https://groq.com/about-us/
237 + - key: cerebras
238 + name: Cerebras Systems
239 + type: company
240 + aliases: [Cerebras]
241 + domains: [cerebras.ai, cerebras.net]
242 + hf_org: cerebras
243 + github_org: Cerebras
244 + country: US
245 + website: https://www.cerebras.ai
246 + source_url: https://www.cerebras.ai/company
247 + - key: sambanova
248 + name: SambaNova Systems
249 + type: company
250 + aliases: [SambaNova]
251 + domains: [sambanova.ai]
252 + country: US
253 + website: https://sambanova.ai
254 + source_url: https://sambanova.ai/about
255 + - key: perplexity
256 + name: Perplexity AI
257 + type: company
258 + aliases: [Perplexity]
259 + domains: [perplexity.ai]
260 + hf_org: perplexity-ai
261 + country: US
262 + website: https://www.perplexity.ai
263 + source_url: https://www.perplexity.ai/hub
264 + - key: openrouter
265 + name: OpenRouter
266 + type: company
267 + aliases: [OpenRouter.ai]
268 + domains: [openrouter.ai]
269 + country: US
270 + website: https://openrouter.ai
271 + source_url: https://openrouter.ai/docs
272 + - key: deepinfra
273 + name: DeepInfra
274 + type: company
275 + domains: [deepinfra.com]
276 + website: https://deepinfra.com
277 + source_url: https://deepinfra.com/about
278 + - key: replicate
279 + name: Replicate
280 + type: company
281 + domains: [replicate.com]
282 + github_org: replicate
283 + country: US
284 + website: https://replicate.com
285 + source_url: https://replicate.com/about
286 + - key: cloudflare
287 + name: Cloudflare
288 + type: company
289 + aliases: [Cloudflare Workers AI]
290 + domains: [cloudflare.com, developers.cloudflare.com]
291 + country: US
292 + website: https://www.cloudflare.com
293 + source_url: https://www.cloudflare.com/about-overview/
294 + - key: amazon
295 + name: Amazon Web Services
296 + type: company
297 + aliases: [AWS, Amazon Bedrock, Amazon, Amazon.com]
298 + domains: [aws.amazon.com, amazon.com]
299 + hf_org: amazon
300 + github_org: aws
301 + country: US
302 + website: https://aws.amazon.com
303 + source_url: https://aws.amazon.com/about-aws/
304 + - key: elevenlabs
305 + name: ElevenLabs
306 + type: company
307 + domains: [elevenlabs.io]
308 + country: US
309 + website: https://elevenlabs.io
310 + source_url: https://elevenlabs.io/about
311 + - key: runway
312 + name: Runway
313 + type: company
314 + aliases: [Runway ML, RunwayML]
315 + domains: [runwayml.com]
316 + country: US
317 + website: https://runwayml.com
318 + source_url: https://runwayml.com/about
319 + - key: amd
320 + name: AMD
321 + type: company
322 + aliases: [Advanced Micro Devices]
323 + domains: [amd.com]
324 + hf_org: amd
325 + github_org: ROCm
326 + country: US
327 + headquarters: Santa Clara, California
328 + website: https://www.amd.com
329 + source_url: https://www.amd.com/en/corporate.html
330 + - key: intel
331 + name: Intel
332 + type: company
333 + aliases: [Intel Corporation]
334 + domains: [intel.com]
335 + hf_org: Intel
336 + github_org: intel
337 + country: US
338 + website: https://www.intel.com
339 + source_url: https://www.intel.com/content/www/us/en/company-overview/company-overview.html
340 + - key: arxiv
341 + name: arXiv
342 + type: organization
343 + aliases: [arXiv.org, Cornell arXiv]
344 + domains: [arxiv.org, export.arxiv.org, rss.arxiv.org]
345 + website: https://arxiv.org
346 + source_url: https://info.arxiv.org/about/index.html
347 + - key: openreview
348 + name: OpenReview
349 + type: organization
350 + domains: [openreview.net]
351 + website: https://openreview.net
352 + source_url: https://openreview.net/about
353 + - key: github
354 + name: GitHub
355 + type: company
356 + aliases: [GitHub Inc.]
357 + domains: [github.com, raw.githubusercontent.com]
358 + parent: microsoft
359 + country: US
360 + website: https://github.com
361 + source_url: https://github.com/about
362 + - key: python-software-foundation
363 + name: Python Software Foundation
364 + type: organization
365 + aliases: [PSF, PyPI]
366 + domains: [pypi.org, python.org]
367 + website: https://www.python.org/psf/
368 + source_url: https://www.python.org/psf/about/
369 + - key: aider
370 + name: Aider
371 + type: organization
372 + aliases: [Aider AI]
373 + domains: [aider.chat]
374 + github_org: Aider-AI
375 + website: https://aider.chat
376 + source_url: https://aider.chat/
377 + - key: swe-bench
378 + name: SWE-bench
379 + type: organization
380 + aliases: [SWE-bench team, Princeton SWE-bench]
381 + domains: [swebench.com]
382 + github_org: SWE-bench
383 + website: https://www.swebench.com
384 + source_url: https://www.swebench.com/
385 + - key: livebench
386 + name: LiveBench
387 + type: organization
388 + domains: [livebench.ai]
389 + github_org: LiveBench
390 + website: https://livebench.ai
391 + source_url: https://livebench.ai/
392 + - key: artificial-analysis
393 + name: Artificial Analysis
394 + type: company
395 + domains: [artificialanalysis.ai]
396 + website: https://artificialanalysis.ai
397 + source_url: https://artificialanalysis.ai/
398 + - key: ai-atlas
399 + name: AI Atlas
400 + type: organization
401 + domains: [ai-atlas.co]
402 + website: https://www.ai-atlas.co
403 + source_url: https://www.ai-atlas.co/methodology
404 + - key: pytorch-foundation
405 + name: PyTorch Foundation
406 + type: organization
407 + aliases: [PyTorch, Linux Foundation PyTorch]
408 + domains: [pytorch.org]
409 + github_org: pytorch
410 + website: https://pytorch.org
411 + source_url: https://pytorch.org/foundation
412 + - key: ggml
413 + name: ggml.ai
414 + type: organization
415 + aliases: [ggml, ggml-org, llama.cpp project]
416 + domains: [ggml.ai]
417 + github_org: ggml-org
418 + website: https://ggml.ai
419 + source_url: https://ggml.ai/
420 + - key: vllm
421 + name: vLLM project
422 + type: organization
423 + aliases: [vLLM]
424 + domains: [vllm.ai, docs.vllm.ai]
425 + github_org: vllm-project
426 + website: https://docs.vllm.ai
427 + source_url: https://docs.vllm.ai/
428 + - key: ollama
429 + name: Ollama
430 + type: company
431 + domains: [ollama.com]
432 + github_org: ollama
433 + website: https://ollama.com
434 + source_url: https://ollama.com/
435 + - key: langchain
436 + name: LangChain
437 + type: company
438 + aliases: [LangChain Inc., LangGraph]
439 + domains: [langchain.com]
440 + github_org: langchain-ai
441 + country: US
442 + website: https://www.langchain.com
443 + source_url: https://www.langchain.com/about
444 + - key: llamaindex
445 + name: LlamaIndex
446 + type: company
447 + aliases: [Llama Index, run-llama]
448 + domains: [llamaindex.ai]
449 + github_org: run-llama
450 + website: https://www.llamaindex.ai
451 + source_url: https://www.llamaindex.ai/
452 + - key: sglang
453 + name: SGLang project
454 + type: organization
455 + aliases: [SGLang, LMSYS]
456 + domains: [sglang.ai, lmsys.org]
457 + github_org: sgl-project
458 + website: https://docs.sglang.ai
459 + source_url: https://docs.sglang.ai/
460 + - key: unsloth
461 + name: Unsloth
462 + type: company
463 + domains: [unsloth.ai]
464 + hf_org: unsloth
465 + github_org: unslothai
466 + website: https://unsloth.ai
467 + source_url: https://unsloth.ai/
468 + - key: bartowski
469 + name: bartowski
470 + type: organization
471 + aliases: [Bartowski quantizations]
472 + hf_org: bartowski
473 + website: https://huggingface.co/bartowski
474 + source_url: https://huggingface.co/bartowski
475 + - key: mlx-community
476 + name: MLX Community
477 + type: organization
478 + aliases: [mlx-community]
479 + hf_org: mlx-community
480 + github_org: ml-explore
481 + website: https://huggingface.co/mlx-community
482 + source_url: https://huggingface.co/mlx-community
483 + - key: allenai
484 + name: Allen Institute for AI
485 + type: lab
486 + aliases: [AI2, AllenAI, Ai2]
487 + domains: [allenai.org]
488 + hf_org: allenai
489 + github_org: allenai
490 + country: US
491 + headquarters: Seattle, Washington
492 + website: https://allenai.org
493 + source_url: https://allenai.org/about
494 + - key: nous-research
495 + name: Nous Research
496 + type: company
497 + domains: [nousresearch.com]
498 + hf_org: NousResearch
499 + github_org: NousResearch
500 + website: https://nousresearch.com
501 + source_url: https://nousresearch.com/
502 + - key: zhipu
503 + name: Z.ai (Zhipu AI)
504 + type: company
505 + aliases: [Zhipu AI, Zhipu, THUDM, Z.ai, ChatGLM]
506 + domains: [z.ai, zhipuai.cn, bigmodel.cn]
507 + hf_org: zai-org
508 + github_org: zai-org
509 + country: CN
510 + headquarters: Beijing
511 + website: https://z.ai
512 + source_url: https://z.ai/
513 + - key: moonshot
514 + name: Moonshot AI
515 + type: company
516 + aliases: [Moonshot, Kimi]
517 + domains: [moonshot.cn, moonshot.ai, kimi.com]
518 + hf_org: moonshotai
519 + github_org: MoonshotAI
520 + country: CN
521 + headquarters: Beijing
522 + website: https://www.moonshot.ai
523 + source_url: https://www.moonshot.ai/
524 + - key: minimax
525 + name: MiniMax
526 + type: company
527 + aliases: [MiniMax AI]
528 + domains: [minimax.io, minimaxi.com]
529 + hf_org: MiniMaxAI
530 + github_org: MiniMax-AI
531 + country: CN
532 + website: https://www.minimax.io
533 + source_url: https://www.minimax.io/
534 + - key: bytedance
535 + name: ByteDance
536 + type: company
537 + aliases: [ByteDance Seed, Seed, Doubao]
538 + domains: [bytedance.com, seed.bytedance.com]
539 + hf_org: ByteDance-Seed
540 + github_org: bytedance
541 + country: CN
542 + website: https://www.bytedance.com
543 + source_url: https://www.bytedance.com/en/
544 + - key: baidu
545 + name: Baidu
546 + type: company
547 + aliases: [Baidu ERNIE, ERNIE]
548 + domains: [baidu.com, ernie.baidu.com]
549 + hf_org: baidu
550 + github_org: PaddlePaddle
551 + country: CN
552 + website: https://www.baidu.com
553 + source_url: https://ir.baidu.com/company-overview
554 + - key: tencent
555 + name: Tencent
556 + type: company
557 + aliases: [Tencent Hunyuan, Hunyuan]
558 + domains: [tencent.com, hunyuan.tencent.com]
559 + hf_org: tencent
560 + github_org: Tencent-Hunyuan
561 + country: CN
562 + website: https://www.tencent.com
563 + source_url: https://www.tencent.com/en-us/about.html
564 + - key: ibm
565 + name: IBM
566 + type: company
567 + aliases: [IBM Research, IBM Granite]
568 + domains: [ibm.com, research.ibm.com]
569 + hf_org: ibm-granite
570 + github_org: ibm-granite
571 + country: US
572 + website: https://www.ibm.com
573 + source_url: https://www.ibm.com/about
574 + - key: databricks
575 + name: Databricks
576 + type: company
577 + aliases: [Mosaic, MosaicML]
578 + domains: [databricks.com]
579 + hf_org: databricks
580 + github_org: databricks
581 + country: US
582 + website: https://www.databricks.com
583 + source_url: https://www.databricks.com/company/about-us
584 + - key: salesforce
585 + name: Salesforce
586 + type: company
587 + aliases: [Salesforce AI Research]
588 + domains: [salesforce.com]
589 + hf_org: Salesforce
590 + github_org: salesforce
591 + country: US
592 + website: https://www.salesforce.com
593 + source_url: https://www.salesforce.com/company/
594 + - key: black-forest-labs
595 + name: Black Forest Labs
596 + type: company
597 + aliases: [BFL, FLUX]
598 + domains: [blackforestlabs.ai, bfl.ai]
599 + hf_org: black-forest-labs
600 + github_org: black-forest-labs
601 + country: DE
602 + website: https://bfl.ai
603 + source_url: https://bfl.ai/
604 + - key: liquid-ai
605 + name: Liquid AI
606 + type: company
607 + domains: [liquid.ai]
608 + hf_org: LiquidAI
609 + country: US
610 + website: https://www.liquid.ai
611 + source_url: https://www.liquid.ai/company
612 + - key: ml-explore
613 + name: Apple ML Explore (MLX)
614 + type: lab
615 + aliases: [MLX, ml-explore]
616 + github_org: ml-explore
617 + parent: apple
618 + website: https://ml-explore.github.io/mlx
619 + source_url: https://github.com/ml-explore/mlx
added registry/providers.d/.gitkeep +0 −0
added registry/providers.yaml +176 −0
@@ -0,0 +1,176 @@
1 +# Inference / API providers (entities of type `provider`). Pricing comes from connectors; this file only fixes identity.
2 +providers:
3 + - key: openai
4 + name: OpenAI API
5 + organization: openai
6 + aliases: [OpenAI Platform, OpenAI]
7 + website: https://platform.openai.com
8 + pricing_url: https://openai.com/api/pricing/
9 + docs_url: https://platform.openai.com/docs/models
10 + openrouter_slug: openai
11 + - key: anthropic
12 + name: Anthropic API
13 + organization: anthropic
14 + aliases: [Claude API, Claude Developer Platform, Anthropic]
15 + website: https://docs.claude.com
16 + pricing_url: https://docs.claude.com/en/docs/about-claude/pricing
17 + docs_url: https://docs.claude.com/en/docs/about-claude/models/overview
18 + openrouter_slug: anthropic
19 + - key: google-gemini-api
20 + name: Google Gemini API
21 + organization: google
22 + aliases: [Gemini API, Google AI Studio, Google]
23 + website: https://ai.google.dev
24 + pricing_url: https://ai.google.dev/gemini-api/docs/pricing
25 + docs_url: https://ai.google.dev/gemini-api/docs/models
26 + openrouter_slug: google
27 + - key: google-vertex-ai
28 + name: Google Vertex AI
29 + organization: google
30 + aliases: [Vertex AI]
31 + website: https://cloud.google.com/vertex-ai
32 + pricing_url: https://cloud.google.com/vertex-ai/generative-ai/pricing
33 + openrouter_slug: google-vertex
34 + - key: azure-openai
35 + name: Azure AI Foundry (Azure OpenAI)
36 + organization: microsoft
37 + aliases: [Azure OpenAI Service, Azure AI Foundry, Azure]
38 + website: https://azure.microsoft.com/en-us/products/ai-foundry
39 + openrouter_slug: azure
40 + - key: amazon-bedrock
41 + name: Amazon Bedrock
42 + organization: amazon
43 + aliases: [Bedrock, AWS Bedrock]
44 + website: https://aws.amazon.com/bedrock/
45 + pricing_url: https://aws.amazon.com/bedrock/pricing/
46 + openrouter_slug: amazon-bedrock
47 + - key: mistral
48 + name: Mistral AI La Plateforme
49 + organization: mistral
50 + aliases: [Mistral API, La Plateforme, Mistral]
51 + website: https://console.mistral.ai
52 + pricing_url: https://mistral.ai/pricing
53 + docs_url: https://docs.mistral.ai/getting-started/models/models_overview/
54 + openrouter_slug: mistral
55 + - key: deepseek
56 + name: DeepSeek API
57 + organization: deepseek
58 + aliases: [DeepSeek Platform, DeepSeek]
59 + website: https://platform.deepseek.com
60 + pricing_url: https://api-docs.deepseek.com/quick_start/pricing
61 + openrouter_slug: deepseek
62 + - key: cohere
63 + name: Cohere API
64 + organization: cohere
65 + aliases: [Cohere Platform, Cohere]
66 + website: https://docs.cohere.com
67 + pricing_url: https://cohere.com/pricing
68 + docs_url: https://docs.cohere.com/docs/models
69 + openrouter_slug: cohere
70 + - key: xai
71 + name: xAI API
72 + organization: xai
73 + aliases: [Grok API, xAI]
74 + website: https://docs.x.ai
75 + docs_url: https://docs.x.ai/docs/models
76 + openrouter_slug: xai
77 + - key: together-ai
78 + name: Together AI
79 + organization: together-ai
80 + website: https://www.together.ai
81 + pricing_url: https://www.together.ai/pricing
82 + openrouter_slug: together
83 + - key: fireworks-ai
84 + name: Fireworks AI
85 + organization: fireworks-ai
86 + website: https://fireworks.ai
87 + pricing_url: https://fireworks.ai/pricing
88 + openrouter_slug: fireworks
89 + - key: groq
90 + name: GroqCloud
91 + organization: groq
92 + aliases: [Groq]
93 + website: https://console.groq.com
94 + pricing_url: https://groq.com/pricing
95 + docs_url: https://console.groq.com/docs/models
96 + openrouter_slug: groq
97 + - key: cerebras
98 + name: Cerebras Inference
99 + organization: cerebras
100 + aliases: [Cerebras]
101 + website: https://inference.cerebras.ai
102 + openrouter_slug: cerebras
103 + - key: sambanova
104 + name: SambaNova Cloud
105 + organization: sambanova
106 + aliases: [SambaNova]
107 + website: https://cloud.sambanova.ai
108 + openrouter_slug: sambanova
109 + - key: openrouter
110 + name: OpenRouter
111 + organization: openrouter
112 + website: https://openrouter.ai
113 + pricing_url: https://openrouter.ai/models
114 + - key: deepinfra
115 + name: DeepInfra
116 + organization: deepinfra
117 + website: https://deepinfra.com
118 + openrouter_slug: deepinfra
119 + - key: replicate
120 + name: Replicate
121 + organization: replicate
122 + website: https://replicate.com
123 + openrouter_slug: replicate
124 + - key: cloudflare-workers-ai
125 + name: Cloudflare Workers AI
126 + organization: cloudflare
127 + aliases: [Workers AI, Cloudflare]
128 + website: https://developers.cloudflare.com/workers-ai/
129 + openrouter_slug: cloudflare
130 + - key: huggingface-inference
131 + name: Hugging Face Inference Providers
132 + organization: huggingface
133 + aliases: [HF Inference, Hugging Face Inference API]
134 + website: https://huggingface.co/docs/inference-providers
135 + - key: perplexity
136 + name: Perplexity API
137 + organization: perplexity
138 + aliases: [Sonar API, Perplexity]
139 + website: https://docs.perplexity.ai
140 + openrouter_slug: perplexity
141 + - key: ai21
142 + name: AI21 Studio
143 + organization: ai21
144 + aliases: [AI21]
145 + website: https://studio.ai21.com
146 + openrouter_slug: ai21
147 + - key: nvidia-nim
148 + name: NVIDIA NIM / build.nvidia.com
149 + organization: nvidia
150 + aliases: [NVIDIA NIM, NVIDIA API Catalog, NVIDIA]
151 + website: https://build.nvidia.com
152 + openrouter_slug: nvidia
153 + - key: alibaba-model-studio
154 + name: Alibaba Cloud Model Studio
155 + organization: alibaba
156 + aliases: [DashScope, Alibaba Cloud, Alibaba]
157 + website: https://www.alibabacloud.com/en/product/modelstudio
158 + openrouter_slug: alibaba
159 + - key: moonshot
160 + name: Moonshot AI Platform
161 + organization: moonshot
162 + aliases: [Kimi API, Moonshot]
163 + website: https://platform.moonshot.ai
164 + openrouter_slug: moonshotai
165 + - key: zai
166 + name: Z.ai API
167 + organization: zhipu
168 + aliases: [Zhipu API, BigModel, Z.ai]
169 + website: https://docs.z.ai
170 + openrouter_slug: z-ai
171 + - key: minimax
172 + name: MiniMax API
173 + organization: minimax
174 + aliases: [MiniMax]
175 + website: https://www.minimax.io/platform
176 + openrouter_slug: minimax
added registry/sources.d/.gitkeep +0 −0
added registry/sources.yaml +387 −0
@@ -0,0 +1,387 @@
1 +# Source registry — every domain AI Atlas crawls, with trust tier (1 official primary … 4 unverified), crawl policy and owner org.
2 +# `key` is stable; `organization` refers to registry/organizations.yaml keys. Rate limits are requests/minute per domain.
3 +sources:
4 + # ---------------------------------------------------------------- major AI labs (tier 1, official)
5 + - key: openai.com
6 + name: OpenAI — news & developer platform
7 + domain: openai.com
8 + organization: openai
9 + tier: 1
10 + kind: website
11 + category: lab
12 + base_url: https://openai.com
13 + rate_limit_per_min: 20
14 + crawl_interval_s: 1800
15 + priority: 0
16 + - key: platform.openai.com
17 + name: OpenAI Platform docs
18 + domain: platform.openai.com
19 + organization: openai
20 + tier: 1
21 + kind: docs
22 + category: lab
23 + base_url: https://platform.openai.com
24 + rate_limit_per_min: 12
25 + crawl_interval_s: 3600
26 + priority: 0
27 + - key: anthropic.com
28 + name: Anthropic — news
29 + domain: anthropic.com
30 + organization: anthropic
31 + tier: 1
32 + kind: website
33 + category: lab
34 + base_url: https://www.anthropic.com
35 + rate_limit_per_min: 20
36 + crawl_interval_s: 1800
37 + priority: 0
38 + - key: docs.claude.com
39 + name: Claude Developer Platform docs
40 + domain: docs.claude.com
41 + organization: anthropic
42 + tier: 1
43 + kind: docs
44 + category: lab
45 + base_url: https://docs.claude.com
46 + rate_limit_per_min: 20
47 + crawl_interval_s: 3600
48 + priority: 0
49 + - key: deepmind.google
50 + name: Google DeepMind — blog
51 + domain: deepmind.google
52 + organization: google-deepmind
53 + tier: 1
54 + kind: website
55 + category: lab
56 + base_url: https://deepmind.google
57 + rate_limit_per_min: 20
58 + crawl_interval_s: 3600
59 + priority: 0
60 + - key: ai.google.dev
61 + name: Google AI for Developers (Gemini API docs)
62 + domain: ai.google.dev
63 + organization: google
64 + tier: 1
65 + kind: docs
66 + category: lab
67 + base_url: https://ai.google.dev
68 + rate_limit_per_min: 20
69 + crawl_interval_s: 3600
70 + priority: 0
71 + - key: ai.meta.com
72 + name: Meta AI — blog & research
73 + domain: ai.meta.com
74 + organization: meta-ai
75 + tier: 1
76 + kind: website
77 + category: lab
78 + base_url: https://ai.meta.com
79 + rate_limit_per_min: 15
80 + crawl_interval_s: 3600
81 + priority: 0
82 + - key: llama.com
83 + name: Llama — official site
84 + domain: llama.com
85 + organization: meta-ai
86 + tier: 1
87 + kind: website
88 + category: lab
89 + base_url: https://www.llama.com
90 + rate_limit_per_min: 15
91 + crawl_interval_s: 7200
92 + priority: 0
93 + - key: microsoft.com/research
94 + name: Microsoft Research — publications & blog
95 + domain: microsoft.com
96 + organization: microsoft
97 + tier: 1
98 + kind: feed
99 + category: lab
100 + base_url: https://www.microsoft.com/en-us/research
101 + rate_limit_per_min: 15
102 + crawl_interval_s: 7200
103 + priority: 1
104 + - key: blogs.nvidia.com
105 + name: NVIDIA — blog & developer blog
106 + domain: nvidia.com
107 + organization: nvidia
108 + tier: 1
109 + kind: feed
110 + category: hardware
111 + base_url: https://blogs.nvidia.com
112 + rate_limit_per_min: 15
113 + crawl_interval_s: 7200
114 + priority: 1
115 + - key: machinelearning.apple.com
116 + name: Apple Machine Learning Research
117 + domain: machinelearning.apple.com
118 + organization: apple
119 + tier: 1
120 + kind: feed
121 + category: lab
122 + base_url: https://machinelearning.apple.com
123 + rate_limit_per_min: 15
124 + crawl_interval_s: 21600
125 + priority: 1
126 + - key: mistral.ai
127 + name: Mistral AI — news, models & pricing
128 + domain: mistral.ai
129 + organization: mistral
130 + tier: 1
131 + kind: website
132 + category: lab
133 + base_url: https://mistral.ai
134 + rate_limit_per_min: 15
135 + crawl_interval_s: 3600
136 + priority: 0
137 + - key: docs.mistral.ai
138 + name: Mistral AI docs
139 + domain: docs.mistral.ai
140 + organization: mistral
141 + tier: 1
142 + kind: docs
143 + category: lab
144 + base_url: https://docs.mistral.ai
145 + rate_limit_per_min: 15
146 + crawl_interval_s: 3600
147 + priority: 0
148 + - key: qwenlm.github.io
149 + name: Qwen — official blog
150 + domain: qwenlm.github.io
151 + organization: qwen
152 + tier: 1
153 + kind: feed
154 + category: lab
155 + base_url: https://qwenlm.github.io
156 + rate_limit_per_min: 15
157 + crawl_interval_s: 3600
158 + priority: 0
159 + - key: deepseek.com
160 + name: DeepSeek — site & API docs
161 + domain: deepseek.com
162 + organization: deepseek
163 + tier: 1
164 + kind: docs
165 + category: lab
166 + base_url: https://api-docs.deepseek.com
167 + rate_limit_per_min: 15
168 + crawl_interval_s: 3600
169 + priority: 0
170 + - key: cohere.com
171 + name: Cohere — docs & blog
172 + domain: cohere.com
173 + organization: cohere
174 + tier: 1
175 + kind: docs
176 + category: lab
177 + base_url: https://docs.cohere.com
178 + rate_limit_per_min: 15
179 + crawl_interval_s: 7200
180 + priority: 1
181 + - key: x.ai
182 + name: xAI — docs
183 + domain: x.ai
184 + organization: xai
185 + tier: 1
186 + kind: docs
187 + category: lab
188 + base_url: https://docs.x.ai
189 + rate_limit_per_min: 12
190 + crawl_interval_s: 7200
191 + priority: 1
192 + # ---------------------------------------------------------------- model & code ecosystems
193 + - key: huggingface.co
194 + name: Hugging Face Hub (public pages, model cards, papers)
195 + domain: huggingface.co
196 + organization: huggingface
197 + tier: 2
198 + kind: repository
199 + category: hub
200 + base_url: https://huggingface.co
201 + rate_limit_per_min: 30
202 + crawl_interval_s: 3600
203 + priority: 0
204 + notes: Model cards are tier-1 statements by their authors; hub metadata (downloads, likes) is community signal.
205 + - key: github.com
206 + name: GitHub public repositories (HTML, releases.atom, raw files)
207 + domain: github.com
208 + organization: github
209 + tier: 2
210 + kind: repository
211 + category: code
212 + base_url: https://github.com
213 + rate_limit_per_min: 20
214 + crawl_interval_s: 3600
215 + priority: 0
216 + - key: pypi.org
217 + name: PyPI public package metadata
218 + domain: pypi.org
219 + organization: python-software-foundation
220 + tier: 2
221 + kind: registry
222 + category: code
223 + base_url: https://pypi.org
224 + rate_limit_per_min: 30
225 + crawl_interval_s: 21600
226 + priority: 1
227 + # ---------------------------------------------------------------- research
228 + - key: arxiv.org
229 + name: arXiv (Atom API + RSS)
230 + domain: arxiv.org
231 + organization: arxiv
232 + tier: 1
233 + kind: feed
234 + category: research
235 + base_url: https://export.arxiv.org
236 + rate_limit_per_min: 4
237 + crawl_interval_s: 21600
238 + priority: 0
239 + notes: arXiv asks for ≤ 1 request / 3 s on the export API.
240 + - key: openreview.net
241 + name: OpenReview
242 + domain: openreview.net
243 + organization: openreview
244 + tier: 1
245 + kind: registry
246 + category: research
247 + base_url: https://api2.openreview.net
248 + rate_limit_per_min: 10
249 + crawl_interval_s: 86400
250 + priority: 1
251 + # ---------------------------------------------------------------- providers (pricing pages, model lists)
252 + - key: openrouter.ai
253 + name: OpenRouter public model & pricing listing
254 + domain: openrouter.ai
255 + organization: openrouter
256 + tier: 2
257 + kind: registry
258 + category: provider
259 + base_url: https://openrouter.ai
260 + rate_limit_per_min: 10
261 + crawl_interval_s: 3600
262 + priority: 0
263 + notes: Aggregated secondary pricing across providers; tier 2 by design — official provider pages win conflicts.
264 + - key: groq.com
265 + name: Groq — docs & pricing
266 + domain: groq.com
267 + organization: groq
268 + tier: 1
269 + kind: docs
270 + category: provider
271 + base_url: https://console.groq.com
272 + rate_limit_per_min: 12
273 + crawl_interval_s: 7200
274 + priority: 1
275 + - key: together.ai
276 + name: Together AI — pricing
277 + domain: together.ai
278 + organization: together-ai
279 + tier: 1
280 + kind: website
281 + category: provider
282 + base_url: https://www.together.ai
283 + rate_limit_per_min: 12
284 + crawl_interval_s: 7200
285 + priority: 1
286 + - key: fireworks.ai
287 + name: Fireworks AI — pricing
288 + domain: fireworks.ai
289 + organization: fireworks-ai
290 + tier: 1
291 + kind: website
292 + category: provider
293 + base_url: https://fireworks.ai
294 + rate_limit_per_min: 12
295 + crawl_interval_s: 7200
296 + priority: 1
297 + # ---------------------------------------------------------------- benchmarks / leaderboards
298 + - key: aider.chat
299 + name: Aider polyglot leaderboard (data file on GitHub)
300 + domain: aider.chat
301 + organization: aider
302 + tier: 2
303 + kind: leaderboard
304 + category: benchmark
305 + base_url: https://aider.chat/docs/leaderboards/
306 + rate_limit_per_min: 10
307 + crawl_interval_s: 21600
308 + priority: 1
309 + - key: swebench.com
310 + name: SWE-bench leaderboards
311 + domain: swebench.com
312 + organization: swe-bench
313 + tier: 2
314 + kind: leaderboard
315 + category: benchmark
316 + base_url: https://www.swebench.com
317 + rate_limit_per_min: 10
318 + crawl_interval_s: 21600
319 + priority: 1
320 + - key: livebench.ai
321 + name: LiveBench
322 + domain: livebench.ai
323 + organization: livebench
324 + tier: 2
325 + kind: leaderboard
326 + category: benchmark
327 + base_url: https://livebench.ai
328 + rate_limit_per_min: 10
329 + crawl_interval_s: 43200
330 + priority: 2
331 + - key: artificialanalysis.ai
332 + name: Artificial Analysis
333 + domain: artificialanalysis.ai
334 + organization: artificial-analysis
335 + tier: 2
336 + kind: leaderboard
337 + category: benchmark
338 + base_url: https://artificialanalysis.ai
339 + rate_limit_per_min: 6
340 + crawl_interval_s: 43200
341 + priority: 2
342 + # ---------------------------------------------------------------- hardware manufacturers
343 + - key: apple.com
344 + name: Apple — Mac tech specs
345 + domain: apple.com
346 + organization: apple
347 + tier: 1
348 + kind: website
349 + category: hardware
350 + base_url: https://www.apple.com
351 + rate_limit_per_min: 10
352 + crawl_interval_s: 86400
353 + priority: 1
354 + - key: nvidia.com
355 + name: NVIDIA — data center product pages
356 + domain: nvidia.com
357 + organization: nvidia
358 + tier: 1
359 + kind: website
360 + category: hardware
361 + base_url: https://www.nvidia.com
362 + rate_limit_per_min: 10
363 + crawl_interval_s: 86400
364 + priority: 1
365 + - key: amd.com
366 + name: AMD — Instinct accelerators
367 + domain: amd.com
368 + organization: amd
369 + tier: 1
370 + kind: website
371 + category: hardware
372 + base_url: https://www.amd.com
373 + rate_limit_per_min: 6
374 + crawl_interval_s: 86400
375 + priority: 2
376 + # ---------------------------------------------------------------- curated registries (AI Atlas itself)
377 + - key: ai-atlas.registry
378 + name: AI Atlas curated registry (YAML, versioned in git, every entry carries its source URL)
379 + domain: ai-atlas.co
380 + organization: ai-atlas
381 + tier: 2
382 + kind: registry
383 + category: registry
384 + base_url: https://www.ai-atlas.co/sources
385 + rate_limit_per_min: 1000
386 + crawl_interval_s: 86400
387 + priority: 1
added src/aiatlas/__init__.py +3 −0
@@ -0,0 +1,3 @@
1 +"""AI Atlas — the global intelligence layer for artificial intelligence."""
2 +
3 +__version__ = "0.1.0"
added src/aiatlas/cli.py +295 −0
@@ -0,0 +1,295 @@
1 +"""`aia` — AI Atlas operations CLI."""
2 +from __future__ import annotations
3 +
4 +import asyncio
5 +import json
6 +import logging
7 +from pathlib import Path
8 +from typing import Annotated
9 +
10 +import typer
11 +from rich.console import Console
12 +from rich.table import Table
13 +
14 +from aiatlas.config import settings
15 +from aiatlas.logging import setup_logging
16 +
17 +app = typer.Typer(name="aia", help="AI Atlas — the global intelligence layer for AI.", no_args_is_help=True, add_completion=False)
18 +console = Console(stderr=True)
19 +out = Console()
20 +
21 +
22 +@app.callback()
23 +def _main(verbose: Annotated[bool, typer.Option("--verbose", "-v")] = False) -> None:
24 + setup_logging(level=logging.DEBUG if verbose else logging.INFO, service="aia-cli")
25 + settings.ensure_dirs()
26 +
27 +
28 +def _run(coro): # type: ignore[no-untyped-def]
29 + from aiatlas.db import dispose
30 + from aiatlas.services import cache
31 +
32 + async def wrapper(): # type: ignore[no-untyped-def]
33 + try:
34 + return await coro
35 + finally:
36 + await dispose()
37 + await cache.close()
38 +
39 + return asyncio.run(wrapper())
40 +
41 +
42 +@app.command()
43 +def migrate(revision: str = "head") -> None:
44 + """Apply database migrations (forward-only)."""
45 + from alembic import command
46 + from alembic.config import Config
47 +
48 + root = Path(__file__).resolve().parents[2]
49 + cfg = Config(str(root / "alembic.ini"))
50 + cfg.set_main_option("script_location", str(root / "migrations"))
51 + command.upgrade(cfg, revision)
52 + out.print("[green]migrations applied[/]")
53 +
54 +
55 +@app.command()
56 +def seed() -> None:
57 + """Seed sources, connectors and curated registries (idempotent)."""
58 + from aiatlas.db import transaction
59 + from aiatlas.registry.seed import seed as _seed
60 +
61 + async def go(): # type: ignore[no-untyped-def]
62 + async with transaction() as conn:
63 + return await _seed(conn)
64 +
65 + res = _run(go())
66 + out.print(f"[green]seeded[/] {json.dumps(res)}")
67 +
68 +
69 +@app.command()
70 +def connectors() -> None:
71 + """List registered connectors (code) and their database state."""
72 + from aiatlas.connectors import registry
73 + from aiatlas.db import fetch_all, transaction
74 +
75 + async def go(): # type: ignore[no-untyped-def]
76 + async with transaction() as conn:
77 + return await fetch_all(conn, "select * from connectors order by priority, name")
78 +
79 + rows = {r["name"]: r for r in _run(go())}
80 + t = Table(title="connectors")
81 + for col in ("name", "tier", "enabled", "health", "interval", "last success", "last change", "failures", "parser"):
82 + t.add_column(col)
83 + for name, cls in registry().items():
84 + r = rows.get(name)
85 + t.add_row(name, str(cls.tier), "✓" if (r and r["enabled"]) else "✗", r["health"] if r else "—", f"{(r['interval_seconds'] if r else cls.interval_seconds) // 60} min",
86 + r["last_success_at"].strftime("%m-%d %H:%M") if r and r["last_success_at"] else "—",
87 + r["last_change_at"].strftime("%m-%d %H:%M") if r and r["last_change_at"] else "—",
88 + str(r["consecutive_failures"]) if r else "—", cls.parser_version)
89 + out.print(t)
90 +
91 +
92 +@app.command()
93 +def run(name: str, force: bool = typer.Option(False, "--force", help="ignore enabled/circuit/conditional headers"),
94 + file: list[str] = typer.Option(None, "--file", help="key=path or url=path local override (fixtures / seed snapshots)"),
95 + max_targets: int = typer.Option(0, "--max-targets"), url: list[str] = typer.Option(None, "--url", help="only these URLs")) -> None:
96 + """Run one connector now."""
97 + from aiatlas.connectors import get
98 +
99 + overrides = dict(f.split("=", 1) for f in (file or []))
100 + ctx = _run(get(name).run(force=force, file_overrides=overrides, max_targets=max_targets or None, only_urls=url or None))
101 + out.print(json.dumps({k: v for k, v in ctx.stats.__dict__.items()}, default=str, indent=1))
102 +
103 +
104 +@app.command()
105 +def reprocess(name: str, url: list[str] = typer.Option(None, "--url")) -> None:
106 + """Re-extract from stored snapshots (no network) — after a parser improvement."""
107 + from aiatlas.connectors import get
108 +
109 + ctx = _run(get(name).run(reprocess=True, force=True, only_urls=url or None))
110 + out.print(json.dumps({k: v for k, v in ctx.stats.__dict__.items()}, default=str, indent=1))
111 +
112 +
113 +@app.command()
114 +def crawl(priority: int = typer.Option(9, "--priority", help="run connectors with priority <= this"), force: bool = False,
115 + only: list[str] = typer.Option(None, "--only")) -> None:
116 + """Run every enabled connector once, in priority order (initial corpus build)."""
117 + from aiatlas.connectors import get, registry
118 + from aiatlas.db import fetch_all, transaction
119 +
120 + async def go(): # type: ignore[no-untyped-def]
121 + async with transaction() as conn:
122 + rows = await fetch_all(conn, "select name, enabled, priority from connectors order by priority, name")
123 + results = {}
124 + for r in rows:
125 + if r["name"] not in registry() or (not r["enabled"] and not force) or r["priority"] > priority or (only and r["name"] not in only):
126 + continue
127 + console.print(f"[cyan]▶ {r['name']}[/]")
128 + try:
129 + ctx = await get(r["name"]).run(force=force)
130 + results[r["name"]] = {k: v for k, v in ctx.stats.__dict__.items() if k != "meta"}
131 + except Exception as exc: # noqa: BLE001
132 + results[r["name"]] = {"error": str(exc)[:300]}
133 + return results
134 +
135 + out.print(json.dumps(_run(go()), default=str, indent=1))
136 +
137 +
138 +@app.command()
139 +def status() -> None:
140 + """Connector health table and queue depth."""
141 + from aiatlas.db import fetch_all, transaction
142 + from aiatlas.services.jobs import queue_depth
143 +
144 + async def go(): # type: ignore[no-untyped-def]
145 + async with transaction() as conn:
146 + rows = await fetch_all(conn, """select c.name, c.enabled, c.health, c.last_success_at, c.next_run_at, c.consecutive_failures,
147 + (select count(*) from documents d where d.connector_name = c.name) as docs,
148 + (select count(*) from snapshots s join documents d on d.id = s.document_id where d.connector_name = c.name) as snaps,
149 + (select status from connector_runs r where r.connector_name = c.name order by started_at desc limit 1) as last_status
150 + from connectors c order by c.priority, c.name""")
151 + return rows, await queue_depth(conn)
152 +
153 + rows, depth = _run(go())
154 + t = Table(title="AI Atlas connectors")
155 + for col in ("connector", "on", "health", "last run", "last success", "next run", "docs", "snapshots", "fails"):
156 + t.add_column(col)
157 + for r in rows:
158 + t.add_row(r["name"], "✓" if r["enabled"] else "✗", r["health"], r["last_status"] or "—",
159 + r["last_success_at"].strftime("%m-%d %H:%M") if r["last_success_at"] else "—",
160 + r["next_run_at"].strftime("%m-%d %H:%M") if r["next_run_at"] else "—", str(r["docs"]), str(r["snaps"]), str(r["consecutive_failures"]))
161 + out.print(t)
162 + out.print(f"queue: {json.dumps(depth)}")
163 +
164 +
165 +@app.command()
166 +def stats() -> None:
167 + """Live counters (from the database) and archive size."""
168 + from aiatlas.services.stats import compute_stats
169 +
170 + out.print(json.dumps(_run(compute_stats()), default=str, indent=1))
171 +
172 +
173 +@app.command()
174 +def quality(limit: int = 20000) -> None:
175 + """Recompute entity quality scores."""
176 + from aiatlas.services.quality import recompute
177 +
178 + out.print(json.dumps(_run(recompute(limit=limit))))
179 +
180 +
181 +@app.command()
182 +def schedule(no_worker: bool = typer.Option(False, "--no-worker")) -> None:
183 + """Long-running scheduler: due connectors, job worker, hourly stats/quality, nightly backup."""
184 + from aiatlas.services.scheduler import main
185 +
186 + setup_logging(service="aia-scheduler")
187 + asyncio.run(main(with_worker=not no_worker))
188 +
189 +
190 +@app.command()
191 +def worker(concurrency: int = typer.Option(0, "--concurrency"), kind: list[str] = typer.Option(None, "--kind")) -> None:
192 + """Job worker only (LLM extraction, embeddings, reprocessing). Run on any node with database access."""
193 + from aiatlas.services.jobs import run_worker
194 +
195 + setup_logging(service="aia-worker")
196 + asyncio.run(run_worker(concurrency=concurrency or None, kinds=kind or None))
197 +
198 +
199 +@app.command()
200 +def api(host: str = "", port: int = 0, reload: bool = False, workers: int = 1) -> None:
201 + """Serve the FastAPI application."""
202 + import uvicorn
203 +
204 + uvicorn.run("aiatlas.api.main:app", host=host or settings.api_host, port=port or settings.api_port, reload=reload, workers=workers if not reload else 1,
205 + log_level="info", access_log=False, proxy_headers=True)
206 +
207 +
208 +@app.command()
209 +def backup() -> None:
210 + """pg_dump into AIA_DATA_DIR/backups (keeps 30)."""
211 + from aiatlas.services.backup import backup_database
212 +
213 + out.print(str(backup_database()))
214 +
215 +
216 +@app.command()
217 +def llm(text: str = typer.Argument("", help="optional text to classify"), health: bool = typer.Option(True)) -> None:
218 + """Check the local LLM factory gateway (and optionally classify a snippet)."""
219 + from aiatlas.services.llm import gateway
220 +
221 + async def go(): # type: ignore[no-untyped-def]
222 + h = await gateway.health()
223 + if text:
224 + h["classification"] = await gateway.classify(text=text, labels=["model_release", "pricing", "research_paper", "company_news", "other"])
225 + return h
226 +
227 + out.print(json.dumps(_run(go()), indent=1))
228 +
229 +
230 +@app.command()
231 +def embed(limit: int = 200) -> None:
232 + """Embed entities missing vectors (requires the LLM gateway)."""
233 + from aiatlas.services.embeddings import embed_entities, pending_entity_ids
234 +
235 + async def go(): # type: ignore[no-untyped-def]
236 + ids = await pending_entity_ids(limit)
237 + return await embed_entities(ids) if ids else {"embedded": 0}
238 +
239 + out.print(json.dumps(_run(go())))
240 +
241 +
242 +@app.command()
243 +def search(q: str, limit: int = 10) -> None:
244 + """Search entities (natural-language filters are compiled deterministically)."""
245 + from aiatlas.db import transaction
246 + from aiatlas.services.search import compile_query, search_entities
247 +
248 + async def go(): # type: ignore[no-untyped-def]
249 + query = compile_query(q)
250 + async with transaction() as conn:
251 + return query.as_dict(), await search_entities(conn, query, limit=limit)
252 +
253 + query, rows = _run(go())
254 + out.print(json.dumps(query))
255 + for r in rows:
256 + out.print(f" {r['entity_type']:<10} {r['canonical_name']:<50} {r.get('organization_name') or ''} /{r['slug']}")
257 +
258 +
259 +@app.command()
260 +def review(status: str = "pending", limit: int = 30) -> None:
261 + """Show the human review queue."""
262 + from aiatlas.db import fetch_all, transaction
263 +
264 + async def go(): # type: ignore[no-untyped-def]
265 + async with transaction() as conn:
266 + return await fetch_all(conn, "select id, kind, reason, created_at from review_queue where status = :s order by created_at desc limit :n", s=status, n=limit)
267 +
268 + for r in _run(go()):
269 + out.print(f"{r['created_at']:%m-%d %H:%M} {r['kind']:<16} {r['reason']}")
270 +
271 +
272 +@app.command()
273 +def enqueue_llm(limit: int = 500, task: str = "auto") -> None:
274 + """Queue LLM extraction for snapshots that are still `llm_pending`/`stored` on documents flagged needs_llm."""
275 + from aiatlas.db import fetch_all, transaction
276 + from aiatlas.services.jobs import enqueue
277 +
278 + async def go(): # type: ignore[no-untyped-def]
279 + async with transaction() as conn:
280 + rows = await fetch_all(conn, """select s.id, d.entity_id, d.connector_name from snapshots s join documents d on d.id = s.document_id
281 + where s.processing_status in ('llm_pending','stored') and d.needs_llm and s.changed
282 + and s.id = (select id from snapshots s2 where s2.document_id = s.document_id and s2.changed order by observed_at desc limit 1)
283 + order by s.observed_at desc limit :n""", n=limit)
284 + n = 0
285 + for r in rows:
286 + if await enqueue(conn, "llm_extract", {"snapshot_id": r["id"], "task": task, "entity_id": r["entity_id"], "connector": r["connector_name"]},
287 + priority=5, dedupe_key=f"llm_extract:{r['id']}"):
288 + n += 1
289 + return {"queued": n, "candidates": len(rows)}
290 +
291 + out.print(json.dumps(_run(go())))
292 +
293 +
294 +if __name__ == "__main__":
295 + app()
added src/aiatlas/config.py +94 −0
@@ -0,0 +1,94 @@
1 +"""Runtime settings (environment variables, `AIA_` prefix). Never log `settings.model_dump()` — it contains secrets."""
2 +from __future__ import annotations
3 +
4 +from functools import lru_cache
5 +from pathlib import Path
6 +
7 +from pydantic import Field
8 +from pydantic_settings import BaseSettings, SettingsConfigDict
9 +
10 +
11 +class Settings(BaseSettings):
12 + model_config = SettingsConfigDict(env_file=(".env",), env_file_encoding="utf-8", extra="ignore")
13 +
14 + app_env: str = Field("development", alias="APP_ENV")
15 + site_url: str = Field("https://www.ai-atlas.co", alias="AIA_SITE_URL")
16 +
17 + database_url: str = Field("postgresql+asyncpg://aiatlas:aiatlas@127.0.0.1:5432/aiatlas", alias="DATABASE_URL")
18 + redis_url: str = Field("redis://127.0.0.1:6379/5", alias="REDIS_URL")
19 +
20 + data_dir: Path = Field(Path("./data"), alias="AIA_DATA_DIR")
21 + api_host: str = Field("127.0.0.1", alias="AIA_API_HOST")
22 + api_port: int = Field(8321, alias="AIA_API_PORT")
23 + admin_token: str = Field("", alias="AIA_ADMIN_TOKEN")
24 + log_json: bool = Field(True, alias="AIA_LOG_JSON")
25 + tz: str = Field("America/Toronto", alias="AIA_TZ")
26 +
27 + # Crawler
28 + user_agent: str = Field("AIAtlasBot/0.1 (+https://www.ai-atlas.co/bot; contact@spboucher.ai)", alias="AIA_USER_AGENT")
29 + http_timeout_s: float = Field(45.0, alias="AIA_HTTP_TIMEOUT")
30 + max_body_bytes: int = Field(25 * 1024 * 1024, alias="AIA_MAX_BODY_BYTES")
31 + default_rate_per_min: int = Field(30, alias="AIA_DEFAULT_RATE_PER_MIN")
32 + respect_robots: bool = Field(True, alias="AIA_RESPECT_ROBOTS")
33 + fetch_concurrency: int = Field(8, alias="AIA_FETCH_CONCURRENCY")
34 +
35 + # Escalation transports (optional; never required)
36 + scrapfly_api_key: str = Field("", alias="SCRAPFLY_API_KEY")
37 + firecrawl_api_key: str = Field("", alias="FIRECRAWL_API_KEY")
38 + browser_enabled: bool = Field(False, alias="AIA_BROWSER_ENABLED")
39 +
40 + # Local LLM factory (OpenAI-compatible endpoint, e.g. MacLustr llm-api.io). Optional.
41 + llm_base_url: str = Field("", alias="AIA_LLM_BASE_URL")
42 + llm_api_key: str = Field("", alias="AIA_LLM_API_KEY")
43 + llm_small_model: str = Field("qwen3-4b-instruct-2507-4bit", alias="AIA_LLM_SMALL_MODEL")
44 + llm_medium_model: str = Field("qwen3.6-35b-a3b-4bit", alias="AIA_LLM_MEDIUM_MODEL")
45 + llm_large_model: str = Field("qwen3.8-27b-4bit", alias="AIA_LLM_LARGE_MODEL")
46 + llm_timeout_s: float = Field(600.0, alias="AIA_LLM_TIMEOUT")
47 + llm_enabled: bool = Field(True, alias="AIA_LLM_ENABLED")
48 + embedding_model: str = Field("qwen3-embedding-0.6b-4bit", alias="AIA_EMBEDDING_MODEL")
49 + embedding_dim: int = Field(1024, alias="AIA_EMBEDDING_DIM")
50 +
51 + # Scheduler
52 + scheduler_tick_s: int = Field(30, alias="AIA_SCHEDULER_TICK_S")
53 + worker_concurrency: int = Field(4, alias="AIA_WORKER_CONCURRENCY")
54 + backup_cron: str = Field("40 4 * * *", alias="AIA_BACKUP_CRON")
55 +
56 + @property
57 + def raw_dir(self) -> Path:
58 + return self.data_dir / "raw"
59 +
60 + @property
61 + def text_dir(self) -> Path:
62 + return self.data_dir / "text"
63 +
64 + @property
65 + def logs_dir(self) -> Path:
66 + return self.data_dir / "logs"
67 +
68 + @property
69 + def backups_dir(self) -> Path:
70 + return self.data_dir / "backups"
71 +
72 + @property
73 + def cache_dir(self) -> Path:
74 + return self.data_dir / "cache"
75 +
76 + @property
77 + def sync_database_url(self) -> str:
78 + return self.database_url.replace("+asyncpg", "")
79 +
80 + @property
81 + def llm_available(self) -> bool:
82 + return bool(self.llm_enabled and self.llm_base_url and self.llm_api_key)
83 +
84 + def ensure_dirs(self) -> None:
85 + for d in (self.raw_dir, self.text_dir, self.logs_dir, self.backups_dir, self.cache_dir, self.data_dir / "seed"):
86 + d.mkdir(parents=True, exist_ok=True)
87 +
88 +
89 +@lru_cache
90 +def get_settings() -> Settings:
91 + return Settings()
92 +
93 +
94 +settings = get_settings()
added src/aiatlas/connectors/__init__.py +46 −0
@@ -0,0 +1,46 @@
1 +"""Connector registry. Every module under `aiatlas.connectors.*` that defines `CONNECTORS = [cls, …]` is auto-registered.
2 +
3 +Add a connector: create `aiatlas/connectors/<group>/<name>.py` with a `BaseConnector` subclass and list it in the module's
4 +`CONNECTORS`. Register its source in `registry/sources.yaml`, then `aia seed` and `aia run <name>`.
5 +"""
6 +from __future__ import annotations
7 +
8 +import importlib
9 +import logging
10 +import pkgutil
11 +from functools import lru_cache
12 +
13 +from aiatlas.sdk.connector import BaseConnector
14 +
15 +log = logging.getLogger(__name__)
16 +
17 +
18 +@lru_cache
19 +def registry() -> dict[str, type[BaseConnector]]:
20 + import aiatlas.connectors as pkg
21 +
22 + found: dict[str, type[BaseConnector]] = {}
23 + for mod in pkgutil.walk_packages(pkg.__path__, prefix="aiatlas.connectors."):
24 + try:
25 + module = importlib.import_module(mod.name)
26 + except Exception as exc: # noqa: BLE001
27 + log.error("cannot import connector module", extra={"module": mod.name, "error": str(exc)})
28 + continue
29 + for cls in getattr(module, "CONNECTORS", []):
30 + if not cls.name:
31 + raise RuntimeError(f"{cls} has no name")
32 + if cls.name in found and found[cls.name] is not cls:
33 + raise RuntimeError(f"duplicate connector name {cls.name}")
34 + found[cls.name] = cls
35 + return dict(sorted(found.items()))
36 +
37 +
38 +def get(name: str, config: dict | None = None) -> BaseConnector:
39 + try:
40 + cls = registry()[name]
41 + except KeyError:
42 + raise KeyError(f"unknown connector {name!r}; known: {', '.join(registry())}") from None
43 + return cls(config)
44 +
45 +
46 +__all__ = ["registry", "get"]
added src/aiatlas/connectors/labs/__init__.py +2 −0
@@ -0,0 +1,2 @@
1 +"""Official AI lab connectors (tier 1): OpenAI, Anthropic, Google DeepMind / Gemini API, Meta AI, Microsoft Research, NVIDIA, Apple ML,
2 +Mistral, Qwen, DeepSeek, Cohere, xAI. Each connector reads official pages/feeds directly and emits models, pricing, announcements."""
added src/aiatlas/connectors/labs/_common.py +153 −0
@@ -0,0 +1,153 @@
1 +"""Shared helpers for lab connectors: announcement events from feeds/listings, key/value tables, model-name normalisation."""
2 +from __future__ import annotations
3 +
4 +import re
5 +from datetime import datetime
6 +from typing import Any
7 +
8 +from aiatlas.sdk.extract.dates import parse_datetime
9 +from aiatlas.sdk.extract.feeds import FeedItem
10 +from aiatlas.sdk.facts import EntityRef, Facts, Target
11 +
12 +RELEASE_WORDS = re.compile(r"\b(introducing|announcing|launch(?:ing|es|ed)?|releas(?:e|es|ing|ed)|now available|new model|preview|deprecat|pricing|price)\b", re.I)
13 +MODEL_WORDS = re.compile(r"\b(model|gpt|claude|gemini|llama|mistral|qwen|deepseek|grok|command|phi|nemotron|gemma|sonnet|opus|haiku|o\d|codex|sora|veo|imagen|whisper|"
14 + r"embedding|reasoning|agent)\w*", re.I)
15 +
16 +
17 +def announcement_events(facts: Facts, org: EntityRef, items: list[FeedItem], *, source_name: str, follow: bool = True, max_follow: int = 30,
18 + needs_llm: bool = True, importance_default: int = 1) -> int:
19 + """One ANNOUNCEMENT event per feed item (deduped by URL) and, optionally, a follow-up fetch of the article for LLM extraction."""
20 + n = 0
21 + for i, it in enumerate(items):
22 + if not it.url or not it.title:
23 + continue
24 + text = f"{it.title} {it.summary or ''}"
25 + is_release = bool(RELEASE_WORDS.search(text) and MODEL_WORDS.search(text))
26 + importance = 2 if is_release else importance_default
27 + facts.event("ANNOUNCEMENT", "release" if is_release else "company", f"{org.name}: {it.title}", entity=org, importance=importance,
28 + effective_at=it.published_at, dedupe_key=f"ANNOUNCEMENT:{it.url}", source_url=it.url,
29 + meta={"source": source_name, "categories": it.categories[:5], "summary": (it.summary or "")[:300], "is_release": is_release})
30 + if follow and i < max_follow:
31 + facts.follow(it.url, doc_type="news", needs_llm=needs_llm and is_release, priority=1 if is_release else 3,
32 + meta={"llm_task": "release_announcement", "published_at": it.published_at.isoformat() if it.published_at else None, "title": it.title})
33 + n += 1
34 + return n
35 +
36 +
37 +def kv_tables(tables: list[dict[str, Any]]) -> dict[str, str]:
38 + """Merge 2-column key/value tables into one dict (lower-cased keys)."""
39 + out: dict[str, str] = {}
40 + for t in tables:
41 + rows = t.get("rows") or []
42 + headers = t.get("headers") or []
43 + if headers and len(headers) == 2 and rows:
44 + for r in rows:
45 + if len(r) >= 2 and r[0]:
46 + out.setdefault(r[0].strip().lower(), r[1].strip())
47 + elif rows and all(len(r) == 2 for r in rows):
48 + for r in rows:
49 + if r[0]:
50 + out.setdefault(r[0].strip().lower(), r[1].strip())
51 + return out
52 +
53 +
54 +def transpose_feature_table(table: dict[str, Any]) -> dict[str, dict[str, str]]:
55 + """Feature-comparison table (first column = feature, other columns = models) → {model: {feature: value}}."""
56 + headers = table.get("headers") or []
57 + if len(headers) < 2:
58 + return {}
59 + models = [clean_cell(h) for h in headers[1:]]
60 + out: dict[str, dict[str, str]] = {m: {} for m in models if m}
61 + for row in table.get("rows") or []:
62 + if not row:
63 + continue
64 + feature = clean_cell(row[0]).lower()
65 + for m, val in zip(models, row[1:], strict=False):
66 + if m:
67 + out[m][feature] = clean_cell(val)
68 + return out
69 +
70 +
71 +_LINK = re.compile(r"\[([^\]]*)\]\([^)]*\)")
72 +_CODE = re.compile(r"`([^`]*)`")
73 +
74 +
75 +def clean_cell(s: str) -> str:
76 + s = _LINK.sub(r"\1", s or "")
77 + s = _CODE.sub(r"\1", s)
78 + s = re.sub(r"\*\*|__", "", s)
79 + s = re.sub(r"<[^>]+>", " ", s)
80 + return re.sub(r"\s+", " ", s).strip()
81 +
82 +
83 +def link_in_cell(s: str) -> str | None:
84 + m = re.search(r"\]\((https?://[^)\s]+)\)", s or "")
85 + return m.group(1) if m else None
86 +
87 +
88 +def parse_retirement(text: str) -> tuple[str | None, bool]:
89 + """'Not sooner than September 1, 2027' → ('2027-09-01', True=tentative)."""
90 + if not text or text.strip().lower() in ("n/a", "—", "-", ""):
91 + return None, False
92 + tentative = "not sooner" in text.lower() or "tentative" in text.lower()
93 + m = re.search(r"([A-Z][a-z]+ \d{1,2}, \d{4}|\d{4}-\d{2}-\d{2})", text)
94 + if not m:
95 + return None, tentative
96 + dt = parse_datetime(m.group(1))
97 + return (dt.date().isoformat() if dt else None), tentative
98 +
99 +
100 +def money(cell: str) -> float | None:
101 + """'$10 / MTok', '$0.25 / MTok1' (footnote), '$12.50 per 1M tokens' → 10.0 …"""
102 + if not cell:
103 + return None
104 + m = re.search(r"\$\s*(\d+(?:\.\d+)?)", cell.replace(",", ""))
105 + if not m:
106 + return None
107 + val = float(m.group(1))
108 + low = cell.lower()
109 + if re.search(r"/\s*1?k\b|per\s*1?k\b|1,000 tokens", low):
110 + return val * 1000
111 + return val
112 +
113 +
114 +def tokens(cell: str) -> int | None:
115 + from aiatlas.sdk.extract.numbers import parse_context_length
116 +
117 + return parse_context_length(cell or "")
118 +
119 +
120 +def month_year(cell: str) -> str | None:
121 + """'Jun 2026' → '2026-06'; 'Reliable knowledge cutoff' cells."""
122 + if not cell:
123 + return None
124 + dt = parse_datetime(cell.strip())
125 + if dt and re.search(r"[A-Za-z]{3,9}\.? \d{4}", cell):
126 + return f"{dt.year:04d}-{dt.month:02d}"
127 + if re.fullmatch(r"\d{4}-\d{2}(-\d{2})?", cell.strip()):
128 + return cell.strip()
129 + return None
130 +
131 +
132 +def model_ref(facts: Facts, name: str, org: EntityRef, *, api_id: str | None = None, provider_key: str | None = None, family: str | None = None,
133 + aliases: list[str] | None = None) -> EntityRef:
134 + ids: dict[str, str] = {}
135 + if api_id and provider_key:
136 + ids[f"{provider_key}_model_id"] = api_id
137 + ref = facts.entity("model", name, identifiers=ids, organization=org, aliases=aliases or [])
138 + facts.relate(org, "develops", ref)
139 + if family:
140 + facts.claim(ref, "family", family)
141 + return ref
142 +
143 +
144 +def first_target_with(targets: list[Target], key: str) -> Target | None:
145 + return next((t for t in targets if t.key == key), None)
146 +
147 +
148 +def iso_date(dt: datetime | None) -> str | None:
149 + return dt.date().isoformat() if dt else None
150 +
151 +
152 +__all__ = ["announcement_events", "kv_tables", "transpose_feature_table", "clean_cell", "link_in_cell", "parse_retirement", "money", "tokens", "month_year",
153 + "model_ref", "first_target_with", "iso_date", "RELEASE_WORDS", "MODEL_WORDS"]
added src/aiatlas/connectors/labs/anthropic.py +312 −0
@@ -0,0 +1,312 @@
1 +"""Anthropic — official docs (served as Markdown by the docs platform) + newsroom listing.
2 +
3 +Sources (tier 1):
4 + * models overview → comparison table transposed into one model per column: API ids, context, max output, cutoffs, retirement
5 + * pricing → per-model price table → PriceObs for the Anthropic API provider (+ status hints such as "retired")
6 + * model deprecations → status table keyed by API model name → status / deprecation / retirement claims
7 + * model pages → per-model spec tables (discovered from the overview)
8 + * newsroom → ANNOUNCEMENT events, release articles queued for LLM extraction
9 +"""
10 +from __future__ import annotations
11 +
12 +import re
13 +from datetime import UTC, datetime
14 +
15 +from aiatlas.registry import org_ref, provider_ref
16 +from aiatlas.sdk.connector import BaseConnector, Parsed, RunContext
17 +from aiatlas.sdk.extract.dates import parse_datetime
18 +from aiatlas.sdk.extract.feeds import FeedItem
19 +from aiatlas.sdk.facts import Facts, Target
20 +from aiatlas.sdk.fetch import FetchResult
21 +
22 +from ._common import announcement_events, clean_cell, kv_tables, link_in_cell, model_ref, money, month_year, parse_retirement, tokens, transpose_feature_table
23 +
24 +DOCS = "https://docs.claude.com/en/docs/about-claude"
25 +NEWS = "https://www.anthropic.com/news"
26 +PROVIDER_KEY = "anthropic"
27 +
28 +CLAUDE_NAME = re.compile(r"^(Claude [A-Za-z]+(?: [0-9.]+)?(?: [A-Za-z]+)?)")
29 +
30 +
31 +class AnthropicConnector(BaseConnector):
32 + name = "anthropic"
33 + label = "Anthropic — models, pricing, deprecations, news"
34 + description = "Official Claude docs (models overview, pricing, deprecations, model pages) and the Anthropic newsroom."
35 + source_key = "docs.claude.com"
36 + version = "1"
37 + parser_version = "1"
38 + interval_seconds = 3600
39 + min_interval_seconds = 1800
40 + rate_per_min = 15
41 + tier = 1
42 + priority = 0
43 + expected_min_records = 4
44 + concurrency = 2
45 +
46 + async def discover(self, ctx: RunContext) -> list[Target]:
47 + return [
48 + Target(url=f"{DOCS}/models/overview.md", doc_type="model_docs", key="models", min_bytes=2000),
49 + Target(url=f"{DOCS}/pricing.md", doc_type="pricing", key="pricing", min_bytes=2000),
50 + Target(url=f"{DOCS}/model-deprecations.md", doc_type="model_docs", key="deprecations", min_bytes=1000),
51 + Target(url=NEWS, doc_type="listing", key="news", min_bytes=5000),
52 + ]
53 +
54 + async def extract(self, ctx: RunContext, target: Target, res: FetchResult, parsed: Parsed) -> Facts:
55 + facts = Facts()
56 + org = org_ref("anthropic")
57 + facts.entities.append(org)
58 + key = target.key or target.meta.get("kind")
59 + if key == "models" and parsed.markdown:
60 + self._models_overview(facts, org, parsed)
61 + elif key == "pricing" and parsed.markdown:
62 + self._pricing(facts, org, parsed)
63 + elif key == "deprecations" and parsed.markdown:
64 + self._deprecations(facts, org, parsed)
65 + elif key == "news" and parsed.html:
66 + self._news(facts, org, parsed, res)
67 + elif target.doc_type == "model_page" and parsed.markdown:
68 + self._model_page(facts, org, target, parsed)
69 + return facts
70 +
71 + # ------------------------------------------------------------------------------------------ models overview
72 + def _models_overview(self, facts: Facts, org, parsed: Parsed) -> None: # type: ignore[no-untyped-def]
73 + md = parsed.markdown
74 + assert md
75 + facts.document_title = md.front_matter.get("title") or "Models overview"
76 + table = next((t for t in md.tables if t["headers"] and clean_cell(t["headers"][0]).lower() == "feature"), None)
77 + if not table:
78 + return
79 + raw_headers = table["headers"]
80 + per_model = transpose_feature_table(table)
81 + for i, (model_name, feats) in enumerate(per_model.items()):
82 + api_id = feats.get("claude api id") or feats.get("anthropic api id")
83 + alias = feats.get("claude api alias") or feats.get("anthropic api alias")
84 + aliases = [a for a in (api_id, alias) if a]
85 + ref = model_ref(facts, model_name, org, api_id=api_id, provider_key=PROVIDER_KEY, family="Claude", aliases=aliases + _name_variants(model_name))
86 + facts.claim(ref, "openness", "proprietary")
87 + facts.claim(ref, "status", "active")
88 + facts.claim(ref, "description", feats.get("description"))
89 + facts.claim(ref, "api_model_id", api_id)
90 + facts.claim(ref, "api_alias", alias)
91 + facts.claim(ref, "context_length", tokens(feats.get("context window", "")), unit="tokens")
92 + facts.claim(ref, "max_output_tokens", tokens(feats.get("max output", "")), unit="tokens")
93 + facts.claim(ref, "knowledge_cutoff", month_year(feats.get("reliable knowledge cutoff", "")))
94 + facts.claim(ref, "training_data_cutoff", month_year(feats.get("training data cutoff", "")))
95 + facts.claim(ref, "latency_tier", feats.get("comparative latency"))
96 + facts.claim(ref, "thinking", feats.get("thinking") or feats.get("extended thinking"))
97 + facts.claim(ref, "default_effort", feats.get("default effort"))
98 + facts.claim(ref, "modalities", ["text", "image"])
99 + facts.claim(ref, "modalities_input", ["text", "image"])
100 + facts.claim(ref, "modalities_output", ["text"])
101 + facts.claim(ref, "tool_calling", True)
102 + facts.claim(ref, "vision", True)
103 + retire, tentative = parse_retirement(feats.get("retirement", ""))
104 + if retire:
105 + facts.claim(ref, "retirement_date", retire)
106 + facts.claim(ref, "retirement_tentative", tentative)
107 + for platform, scheme in (("amazon bedrock id", "bedrock_model_id"), ("google cloud id", "vertex_model_id"), ("microsoft foundry id", "foundry_model_id"),
108 + ("claude platform on aws id", "claude_aws_model_id")):
109 + v = feats.get(platform)
110 + if v and v not in ("—", "-"):
111 + facts.claim(ref, scheme, v)
112 + page_url = link_in_cell(feats.get("model page", "")) or (link_in_cell(raw_headers[i + 1]) if i + 1 < len(raw_headers) else None)
113 + if not page_url:
114 + # header cells are plain names; the "Model page" row holds the links in the raw table
115 + for row in parsed.markdown.tables[0]["rows"] if parsed.markdown else []:
116 + pass
117 + if page_url:
118 + if not page_url.endswith(".md"):
119 + page_url = page_url.rstrip("/") + ".md"
120 + facts.follow(page_url, doc_type="model_page", entity=ref, key=f"model:{api_id or model_name}", meta={"model": model_name, "api_id": api_id}, min_bytes=500)
121 + facts.document_entity = org
122 + # raw table rows keep the links: recover "Model page" links precisely
123 + for t in md.tables:
124 + if t["headers"] and clean_cell(t["headers"][0]).lower() == "feature":
125 + for row in t["rows"]:
126 + if row and clean_cell(row[0]).lower() == "model page":
127 + for name, cell in zip([clean_cell(h) for h in t["headers"][1:]], row[1:], strict=False):
128 + url = link_in_cell(cell)
129 + if url and not any(f.url.startswith(url.rstrip("/")) for f in facts.targets):
130 + ref = next((e for e in facts.entities if e.entity_type == "model" and e.name == name), None)
131 + facts.follow(url.rstrip("/") + ".md", doc_type="model_page", entity=ref, key=f"model:{name}", meta={"model": name}, min_bytes=500)
132 +
133 + # ------------------------------------------------------------------------------------------ model page
134 + def _model_page(self, facts: Facts, org, target: Target, parsed: Parsed) -> None: # type: ignore[no-untyped-def]
135 + md = parsed.markdown
136 + assert md
137 + name = target.meta.get("model") or md.front_matter.get("title") or ""
138 + if not name:
139 + return
140 + ref = target.entity or model_ref(facts, name, org, api_id=target.meta.get("api_id"), provider_key=PROVIDER_KEY, family="Claude")
141 + if ref not in facts.entities:
142 + facts.entities.append(ref)
143 + kv = kv_tables(md.tables)
144 + facts.claim(ref, "official_url", md.front_matter.get("url"))
145 + facts.claim(ref, "description", md.front_matter.get("description"))
146 + for k, prop in (("context window", "context_length"), ("max output", "max_output_tokens")):
147 + if kv.get(k):
148 + facts.claim(ref, prop, tokens(kv[k]), unit="tokens")
149 + for k, prop in (("reliable knowledge cutoff", "knowledge_cutoff"), ("training data cutoff", "training_data_cutoff")):
150 + if kv.get(k):
151 + facts.claim(ref, prop, month_year(kv[k]))
152 + if kv.get("release date") or kv.get("released"):
153 + dt = parse_datetime(kv.get("release date") or kv.get("released"))
154 + if dt:
155 + facts.claim(ref, "release_date", dt.date().isoformat())
156 + facts.document_entity = ref
157 + facts.document_title = md.front_matter.get("title")
158 +
159 + # ------------------------------------------------------------------------------------------ pricing
160 + def _pricing(self, facts: Facts, org, parsed: Parsed) -> None: # type: ignore[no-untyped-def]
161 + md = parsed.markdown
162 + assert md
163 + facts.document_title = md.front_matter.get("title") or "Pricing"
164 + provider = provider_ref(PROVIDER_KEY)
165 + facts.entities.append(provider)
166 + table = next((t for t in md.tables if t["headers"] and clean_cell(t["headers"][0]).lower() == "model" and any("output" in clean_cell(h).lower() for h in t["headers"])), None)
167 + if not table:
168 + return
169 + headers = [clean_cell(h).lower() for h in table["headers"]]
170 +
171 + def col(*needles: str) -> int | None:
172 + for i, h in enumerate(headers):
173 + if all(n in h for n in needles):
174 + return i
175 + return None
176 +
177 + c_in, c_out = col("input"), col("output")
178 + c_w5, c_w1, c_hit = col("5m", "cache"), col("1h", "cache"), col("cache hit")
179 + for row in table["rows"]:
180 + if not row or c_in is None or c_out is None:
181 + continue
182 + raw_name = row[0]
183 + name_clean = clean_cell(raw_name)
184 + m = CLAUDE_NAME.match(name_clean)
185 + model_name = m.group(1).strip() if m else name_clean.split("(")[0].strip()
186 + note = name_clean[len(model_name):].strip(" ()")
187 + status = None
188 + low = note.lower()
189 + if "retired" in low:
190 + status = "retired"
191 + elif "deprecated" in low:
192 + status = "deprecated"
193 + elif "limited availability" in low:
194 + status = "limited-availability"
195 + ref = model_ref(facts, model_name, org, family="Claude", aliases=_name_variants(model_name))
196 + facts.claim(ref, "openness", "proprietary")
197 + if status:
198 + facts.claim(ref, "status", status)
199 + facts.claim(ref, "availability_note", note)
200 + facts.price(model=ref, provider=provider, input_per_mtok=money(row[c_in]), output_per_mtok=money(row[c_out]),
201 + cached_input_per_mtok=money(row[c_hit]) if c_hit is not None and c_hit < len(row) else None,
202 + cache_write_per_mtok=money(row[c_w5]) if c_w5 is not None and c_w5 < len(row) else None,
203 + features={"cache_write_1h_per_mtok": money(row[c_w1]) if c_w1 is not None and c_w1 < len(row) else None},
204 + meta={"from": "pricing page", "note": note or None})
205 + # batch discount, if stated as a multiplier/percent
206 + for t in md.tables:
207 + hs = [clean_cell(h).lower() for h in t["headers"]]
208 + if hs and "cache operation" in hs[0]:
209 + facts.claim(provider, "prompt_caching", {clean_cell(r[0]): clean_cell(r[1]) for r in t["rows"] if len(r) >= 2})
210 + facts.document_entity = provider
211 +
212 + # ------------------------------------------------------------------------------------------ deprecations
213 + def _deprecations(self, facts: Facts, org, parsed: Parsed) -> None: # type: ignore[no-untyped-def]
214 + md = parsed.markdown
215 + assert md
216 + facts.document_title = md.front_matter.get("title") or "Model deprecations"
217 + table = next((t for t in md.tables if t["headers"] and "api model name" in clean_cell(t["headers"][0]).lower()), None)
218 + if not table:
219 + return
220 + headers = [clean_cell(h).lower() for h in table["headers"]]
221 + i_state = next((i for i, h in enumerate(headers) if "state" in h or "status" in h), 1)
222 + i_dep = next((i for i, h in enumerate(headers) if "deprecated" in h), 2)
223 + i_ret = next((i for i, h in enumerate(headers) if "retirement" in h), 3)
224 + for row in table["rows"]:
225 + if len(row) <= max(i_state, i_dep, i_ret):
226 + continue
227 + api_id = clean_cell(row[0])
228 + if not api_id.startswith("claude"):
229 + continue
230 + display = _display_name(api_id)
231 + ref = model_ref(facts, display, org, api_id=api_id, provider_key=PROVIDER_KEY, family="Claude", aliases=[api_id] + _name_variants(display))
232 + state = clean_cell(row[i_state]).lower()
233 + facts.claim(ref, "status", {"active": "active", "retired": "retired", "deprecated": "deprecated"}.get(state, state))
234 + dep = clean_cell(row[i_dep])
235 + if dep and dep.upper() != "N/A":
236 + d = parse_datetime(dep)
237 + if d:
238 + facts.claim(ref, "deprecation_date", d.date().isoformat())
239 + ret, tentative = parse_retirement(clean_cell(row[i_ret]))
240 + if ret:
241 + facts.claim(ref, "retirement_date", ret)
242 + facts.claim(ref, "retirement_tentative", tentative)
243 + facts.document_entity = org
244 +
245 + # ------------------------------------------------------------------------------------------ news
246 + def _news(self, facts: Facts, org, parsed: Parsed, res: FetchResult) -> None: # type: ignore[no-untyped-def]
247 + html = parsed.html
248 + assert html
249 + items: list[FeedItem] = []
250 + seen: set[str] = set()
251 + for node in html.css("a[href^='/news/']"):
252 + href = node.attributes.get("href") or ""
253 + if href in seen or href.count("/") != 2:
254 + continue
255 + text = re.sub(r"\s+", " ", node.text(separator=" | ", strip=True))
256 + parts = [p.strip() for p in text.split("|") if p.strip()]
257 + if len(parts) < 2:
258 + continue
259 + date = None
260 + category = None
261 + title = None
262 + summary = None
263 + for p in parts:
264 + if date is None and re.fullmatch(r"[A-Z][a-z]{2} \d{1,2}, \d{4}", p):
265 + date = parse_datetime(p)
266 + elif category is None and p in ("Announcements", "Product", "Policy", "Research", "Interpretability", "Alignment", "Societal Impacts", "Economic Research", "Education"):
267 + category = p
268 + elif title is None:
269 + title = p
270 + elif summary is None:
271 + summary = p
272 + if not title:
273 + continue
274 + seen.add(href)
275 + items.append(FeedItem(id=href, url=f"https://www.anthropic.com{href}", title=title[:300], summary=summary, published_at=date, updated_at=None,
276 + categories=[category] if category else []))
277 + announcement_events(facts, org, items, source_name="anthropic.com/news", follow=True, max_follow=25)
278 + facts.document_title = "Anthropic newsroom"
279 + facts.document_entity = org
280 +
281 +
282 +def _name_variants(name: str) -> list[str]:
283 + """Anthropic has used both 'Claude 3.5 Haiku' and 'Claude Haiku 3.5' — register both orders as aliases."""
284 + m = re.fullmatch(r"Claude (\d[\d.]*) ([A-Za-z]+)", name)
285 + if m:
286 + return [f"Claude {m.group(2)} {m.group(1)}"]
287 + m = re.fullmatch(r"Claude ([A-Za-z]+) (\d[\d.]*)", name)
288 + if m:
289 + return [f"Claude {m.group(2)} {m.group(1)}"]
290 + return []
291 +
292 +
293 +def _display_name(api_id: str) -> str:
294 + """claude-opus-4-5-20251101 → Claude Opus 4.5 ; claude-3-7-sonnet-20250219 → Claude 3.7 Sonnet ; claude-fable-5-1 → Claude Fable 5.1"""
295 + parts = api_id.split("-")
296 + parts = [p for p in parts if not re.fullmatch(r"\d{8}", p)]
297 + words: list[str] = []
298 + nums: list[str] = []
299 + for p in parts:
300 + if p.isdigit():
301 + nums.append(p)
302 + else:
303 + if nums:
304 + words.append(".".join(nums))
305 + nums = []
306 + words.append(p.capitalize())
307 + if nums:
308 + words.append(".".join(nums))
309 + return " ".join(words)
310 +
311 +
312 +CONNECTORS = [AnthropicConnector]
added src/aiatlas/db/__init__.py +75 −0
@@ -0,0 +1,75 @@
1 +"""Database access: SQLAlchemy Core (async, asyncpg) with plain SQL. One engine per process."""
2 +from __future__ import annotations
3 +
4 +import json
5 +from collections.abc import AsyncIterator, Mapping, Sequence
6 +from contextlib import asynccontextmanager
7 +from typing import Any
8 +
9 +from sqlalchemy import text
10 +from sqlalchemy.ext.asyncio import AsyncConnection, AsyncEngine, create_async_engine
11 +
12 +from aiatlas.config import settings
13 +
14 +_engine: AsyncEngine | None = None
15 +
16 +
17 +def engine() -> AsyncEngine:
18 + global _engine
19 + if _engine is None:
20 + _engine = create_async_engine(settings.database_url, pool_size=8, max_overflow=8, pool_pre_ping=True, pool_recycle=1800,
21 + connect_args={"server_settings": {"application_name": "aiatlas", "jit": "off"}})
22 + return _engine
23 +
24 +
25 +async def dispose() -> None:
26 + global _engine
27 + if _engine is not None:
28 + await _engine.dispose()
29 + _engine = None
30 +
31 +
32 +@asynccontextmanager
33 +async def connection() -> AsyncIterator[AsyncConnection]:
34 + async with engine().connect() as conn:
35 + yield conn
36 +
37 +
38 +@asynccontextmanager
39 +async def transaction() -> AsyncIterator[AsyncConnection]:
40 + async with engine().begin() as conn:
41 + yield conn
42 +
43 +
44 +def jsonb(value: Any) -> str:
45 + """Serialise a Python value for a `cast(:x as jsonb)` parameter."""
46 + return json.dumps(value, default=str, ensure_ascii=False)
47 +
48 +
49 +async def execute(conn: AsyncConnection, sql: str, /, **params: Any) -> None:
50 + await conn.execute(text(sql), params)
51 +
52 +
53 +async def fetch_all(conn: AsyncConnection, sql: str, /, **params: Any) -> list[dict[str, Any]]:
54 + result = await conn.execute(text(sql), params)
55 + return [dict(r._mapping) for r in result]
56 +
57 +
58 +async def fetch_one(conn: AsyncConnection, sql: str, /, **params: Any) -> dict[str, Any] | None:
59 + result = await conn.execute(text(sql), params)
60 + row = result.first()
61 + return dict(row._mapping) if row is not None else None
62 +
63 +
64 +async def fetch_val(conn: AsyncConnection, sql: str, /, **params: Any) -> Any:
65 + result = await conn.execute(text(sql), params)
66 + row = result.first()
67 + return row[0] if row is not None else None
68 +
69 +
70 +async def execute_many(conn: AsyncConnection, sql: str, rows: Sequence[Mapping[str, Any]]) -> None:
71 + if rows:
72 + await conn.execute(text(sql), list(rows))
73 +
74 +
75 +__all__ = ["engine", "dispose", "connection", "transaction", "execute", "fetch_all", "fetch_one", "fetch_val", "execute_many", "jsonb"]
added src/aiatlas/ids.py +93 −0
@@ -0,0 +1,93 @@
1 +"""Stable internal identifiers: prefixed ULIDs (`model_01J…`). URLs and names change; ids never do."""
2 +from __future__ import annotations
3 +
4 +import re
5 +
6 +from slugify import slugify as _slugify
7 +from ulid import ULID
8 +
9 +PREFIXES: dict[str, str] = {
10 + "model": "model",
11 + "company": "company",
12 + "organization": "org",
13 + "researcher": "person",
14 + "paper": "paper",
15 + "dataset": "dataset",
16 + "benchmark": "bench",
17 + "provider": "provider",
18 + "framework": "framework",
19 + "library": "lib",
20 + "repository": "repo",
21 + "tool": "tool",
22 + "agent": "agent",
23 + "application": "app",
24 + "hardware": "hw",
25 + "runtime": "runtime",
26 + "quantization": "quant",
27 + "license": "license",
28 + "conference": "conf",
29 + "university": "univ",
30 + "lab": "lab",
31 + "product": "product",
32 + "release": "release",
33 + "regulation": "reg",
34 + "incident": "incident",
35 + "country": "country",
36 + "mcp_server": "mcp",
37 + "robot": "robot",
38 + "data_center": "dc",
39 + "job": "job",
40 + "course": "course",
41 + "standard": "std",
42 + "funding_round": "funding",
43 + "acquisition": "acq",
44 + # infrastructure records
45 + "source": "src",
46 + "document": "doc",
47 + "snapshot": "snap",
48 + "claim": "claim",
49 + "relation": "rel",
50 + "change_event": "evt",
51 + "connector_run": "run",
52 + "queue_job": "qj",
53 + "llm_job": "llm",
54 + "review": "rev",
55 + "price": "price",
56 + "result": "res",
57 + "api_key": "key",
58 +}
59 +
60 +ENTITY_TYPES: tuple[str, ...] = tuple(k for k in PREFIXES if k not in {
61 + "source", "document", "snapshot", "claim", "relation", "change_event", "connector_run", "queue_job", "llm_job",
62 + "review", "price", "result", "api_key"})
63 +
64 +
65 +def new_id(kind: str) -> str:
66 + prefix = PREFIXES.get(kind)
67 + if prefix is None:
68 + raise ValueError(f"unknown id kind {kind!r}")
69 + return f"{prefix}_{ULID()}"
70 +
71 +
72 +def kind_of(entity_id: str) -> str | None:
73 + prefix = entity_id.split("_", 1)[0]
74 + for kind, p in PREFIXES.items():
75 + if p == prefix:
76 + return kind
77 + return None
78 +
79 +
80 +_slug_clean = re.compile(r"[^a-z0-9.+-]+")
81 +
82 +
83 +def slugify(text: str, *, max_length: int = 96) -> str:
84 + """URL slug that keeps dots and plus signs (model names like `qwen3-8b`, `gpt-4.1`, `c++`)."""
85 + s = _slugify(text, lowercase=True, regex_pattern=r"[^a-z0-9.+-]+", replacements=[("/", "-"), ("_", "-"), ("@", "-at-")])
86 + s = _slug_clean.sub("-", s).strip("-.")
87 + return s[:max_length].rstrip("-.") or "item"
88 +
89 +
90 +def normalize_alias(text: str) -> str:
91 + """Deterministic alias key: lowercase, ASCII, punctuation collapsed. Used for entity resolution — never for display."""
92 + s = _slugify(text, lowercase=True, regex_pattern=r"[^a-z0-9]+")
93 + return s.replace("-", "")
added src/aiatlas/logging.py +56 −0
@@ -0,0 +1,56 @@
1 +"""Structured logging (JSON in production, human-readable in development)."""
2 +from __future__ import annotations
3 +
4 +import json
5 +import logging
6 +import sys
7 +from datetime import UTC, datetime
8 +
9 +from aiatlas.config import settings
10 +
11 +_RESERVED = {"name", "msg", "args", "levelname", "levelno", "pathname", "filename", "module", "exc_info", "exc_text", "stack_info",
12 + "lineno", "funcName", "created", "msecs", "relativeCreated", "thread", "threadName", "processName", "process",
13 + "message", "taskName"}
14 +
15 +
16 +class JsonFormatter(logging.Formatter):
17 + def __init__(self, service: str):
18 + super().__init__()
19 + self.service = service
20 +
21 + def format(self, record: logging.LogRecord) -> str:
22 + payload = {
23 + "ts": datetime.now(UTC).isoformat(timespec="milliseconds"),
24 + "level": record.levelname,
25 + "logger": record.name,
26 + "service": self.service,
27 + "msg": record.getMessage(),
28 + }
29 + for key, value in record.__dict__.items():
30 + if key not in _RESERVED and not key.startswith("_"):
31 + payload[key] = value
32 + if record.exc_info:
33 + payload["exc"] = self.formatException(record.exc_info)
34 + return json.dumps(payload, default=str)
35 +
36 +
37 +class PlainFormatter(logging.Formatter):
38 + def format(self, record: logging.LogRecord) -> str:
39 + extras = {k: v for k, v in record.__dict__.items() if k not in _RESERVED and not k.startswith("_")}
40 + base = f"{datetime.now().strftime('%H:%M:%S')} {record.levelname:<7} {record.name}: {record.getMessage()}"
41 + if extras:
42 + base += " " + " ".join(f"{k}={v}" for k, v in extras.items())
43 + if record.exc_info:
44 + base += "\n" + self.formatException(record.exc_info)
45 + return base
46 +
47 +
48 +def setup_logging(level: int = logging.INFO, service: str = "aiatlas") -> None:
49 + root = logging.getLogger()
50 + root.handlers.clear()
51 + handler = logging.StreamHandler(sys.stderr)
52 + handler.setFormatter(JsonFormatter(service) if settings.log_json else PlainFormatter())
53 + root.addHandler(handler)
54 + root.setLevel(level)
55 + for noisy in ("httpx", "httpcore", "apscheduler", "asyncio", "urllib3"):
56 + logging.getLogger(noisy).setLevel(logging.WARNING)
added src/aiatlas/registry/__init__.py +103 −0
@@ -0,0 +1,103 @@
1 +"""Curated registries (YAML under /registry) and their loaders."""
2 +from __future__ import annotations
3 +
4 +from functools import lru_cache
5 +from pathlib import Path
6 +from typing import Any
7 +
8 +import yaml
9 +
10 +REGISTRY_DIR = Path(__file__).resolve().parents[3] / "registry"
11 +
12 +
13 +@lru_cache
14 +def load(name: str) -> list[dict[str, Any]]:
15 + """`registry/<name>.yaml` merged with fragment files `registry/<name>.d/*.yaml` (same top-level key). Later fragments may not
16 + redefine a key — duplicates are an error."""
17 + paths = [REGISTRY_DIR / f"{name}.yaml", *sorted((REGISTRY_DIR / f"{name}.d").glob("*.yaml"))]
18 + items: list[dict[str, Any]] = []
19 + for path in paths:
20 + if not path.exists():
21 + continue
22 + with path.open("r", encoding="utf-8") as fh:
23 + data = yaml.safe_load(fh) or {}
24 + items.extend(data.get(name) or [])
25 + keys = [i["key"] for i in items]
26 + dupes = {k for k in keys if keys.count(k) > 1}
27 + if dupes:
28 + raise ValueError(f"duplicate keys in {name}.yaml: {sorted(dupes)}")
29 + return items
30 +
31 +
32 +@lru_cache
33 +def organizations() -> dict[str, dict[str, Any]]:
34 + return {o["key"]: o for o in load("organizations")}
35 +
36 +
37 +@lru_cache
38 +def providers() -> dict[str, dict[str, Any]]:
39 + return {p["key"]: p for p in load("providers")}
40 +
41 +
42 +@lru_cache
43 +def org_by_hf(hf_org: str) -> dict[str, Any] | None:
44 + for o in organizations().values():
45 + if o.get("hf_org", "").lower() == hf_org.lower():
46 + return o
47 + return None
48 +
49 +
50 +@lru_cache
51 +def org_by_github(gh_org: str) -> dict[str, Any] | None:
52 + for o in organizations().values():
53 + if o.get("github_org", "").lower() == gh_org.lower():
54 + return o
55 + return None
56 +
57 +
58 +@lru_cache
59 +def org_by_domain(domain: str) -> dict[str, Any] | None:
60 + d = domain.lower()
61 + d = d[4:] if d.startswith("www.") else d
62 + for o in organizations().values():
63 + for od in o.get("domains", []):
64 + if d == od or d.endswith("." + od):
65 + return o
66 + return None
67 +
68 +
69 +def org_ref(key: str): # type: ignore[no-untyped-def]
70 + """EntityRef for a registry organization (identifiers make resolution deterministic)."""
71 + from aiatlas.sdk.facts import EntityRef
72 +
73 + o = organizations()[key]
74 + ids: dict[str, str] = {"registry_org": key}
75 + if o.get("domains"):
76 + ids["domain"] = o["domains"][0]
77 + if o.get("hf_org"):
78 + ids["hf_org"] = o["hf_org"]
79 + if o.get("github_org"):
80 + ids["github_org"] = o["github_org"]
81 + return EntityRef(entity_type=o.get("type", "company") if o.get("type") in ("company", "lab", "organization", "university") else "company",
82 + name=o["name"], identifiers=ids, aliases=list(o.get("aliases", [])), slug_hint=key)
83 +
84 +
85 +def provider_ref(key: str): # type: ignore[no-untyped-def]
86 + from aiatlas.sdk.facts import EntityRef
87 +
88 + p = providers()[key]
89 + ids = {"registry_provider": key}
90 + if p.get("openrouter_slug"):
91 + ids["openrouter_provider"] = p["openrouter_slug"]
92 + org = org_ref(p["organization"]) if p.get("organization") in organizations() else None
93 + return EntityRef(entity_type="provider", name=p["name"], identifiers=ids, aliases=list(p.get("aliases", [])), slug_hint=key, organization=org)
94 +
95 +
96 +def provider_by_openrouter(slug: str) -> str | None:
97 + for k, p in providers().items():
98 + if p.get("openrouter_slug") == slug:
99 + return k
100 + return None
101 +
102 +
103 +__all__ = ["load", "organizations", "providers", "org_by_hf", "org_by_github", "org_by_domain", "org_ref", "provider_ref", "provider_by_openrouter", "REGISTRY_DIR"]
added src/aiatlas/registry/seed.py +168 −0
@@ -0,0 +1,168 @@
1 +"""`aia seed` — idempotent: sources, connectors (from code), curated organizations / providers / benchmarks / hardware as entities
2 +with claims attributed to the curated registry source (tier 2, each entry's own `source_url`)."""
3 +from __future__ import annotations
4 +
5 +import logging
6 +from typing import Any
7 +
8 +from sqlalchemy.ext.asyncio import AsyncConnection
9 +
10 +from aiatlas.connectors import registry as connector_registry
11 +from aiatlas.db import execute, fetch_one, jsonb
12 +from aiatlas.ids import new_id
13 +from aiatlas.registry import load, org_ref, organizations, provider_ref
14 +from aiatlas.sdk.facts import EntityRef, Facts
15 +from aiatlas.sdk.writer import FactWriter
16 +
17 +log = logging.getLogger(__name__)
18 +REGISTRY_SOURCE_KEY = "ai-atlas.registry"
19 +
20 +
21 +async def seed(conn: AsyncConnection) -> dict[str, Any]:
22 + out: dict[str, Any] = {}
23 + out["sources"] = await _seed_sources(conn)
24 + out["connectors"] = await _seed_connectors(conn)
25 + reg_source = await fetch_one(conn, "select id, tier from sources where key = :k", k=REGISTRY_SOURCE_KEY)
26 + assert reg_source
27 + out["organizations"] = await _seed_organizations(conn, reg_source["id"])
28 + out["providers"] = await _seed_providers(conn, reg_source["id"])
29 + out["benchmarks"] = await _seed_benchmarks(conn, reg_source["id"])
30 + out["hardware"] = await _seed_hardware(conn, reg_source["id"])
31 + out["domains"] = await _seed_domains(conn)
32 + return out
33 +
34 +
35 +async def _seed_sources(conn: AsyncConnection) -> int:
36 + n = 0
37 + for s in load("sources"):
38 + org = organizations().get(s.get("organization", ""))
39 + org_id = None
40 + if org:
41 + row = await fetch_one(conn, "select entity_id from entity_identifiers where scheme = 'registry_org' and value = :v", v=org["key"])
42 + org_id = row["entity_id"] if row else None
43 + await execute(conn, """insert into sources (id, key, name, domain, organization_id, tier, kind, category, base_url, rate_limit_per_min, crawl_interval_s, enabled, priority, notes, meta)
44 + values (:id, :key, :name, :domain, :org, :tier, :kind, :cat, :base, :rate, :interval, :enabled, :prio, :notes, cast(:meta as jsonb))
45 + on conflict (key) do update set name = excluded.name, domain = excluded.domain, organization_id = coalesce(excluded.organization_id, sources.organization_id),
46 + tier = excluded.tier, kind = excluded.kind, category = excluded.category, base_url = excluded.base_url, rate_limit_per_min = excluded.rate_limit_per_min,
47 + crawl_interval_s = excluded.crawl_interval_s, priority = excluded.priority, notes = excluded.notes, updated_at = now()""",
48 + id=new_id("source"), key=s["key"], name=s["name"], domain=s["domain"], org=org_id, tier=s.get("tier", 2), kind=s.get("kind", "website"),
49 + cat=s.get("category", "lab"), base=s.get("base_url"), rate=s.get("rate_limit_per_min", 30), interval=s.get("crawl_interval_s", 86400),
50 + enabled=s.get("enabled", True), prio=s.get("priority", 2), notes=s.get("notes"), meta=jsonb({k: v for k, v in s.items() if k not in ("key",)}))
51 + n += 1
52 + return n
53 +
54 +
55 +async def _seed_connectors(conn: AsyncConnection) -> int:
56 + n = 0
57 + for name, cls in connector_registry().items():
58 + src = await fetch_one(conn, "select id from sources where key = :k", k=cls.source_key) if cls.source_key else None
59 + if cls.source_key and not src:
60 + log.warning("connector source missing in registry/sources.yaml", extra={"connector": name, "source_key": cls.source_key})
61 + await execute(conn, """insert into connectors (name, source_id, label, description, enabled, priority, interval_seconds, min_interval_seconds, max_interval_seconds,
62 + parser_version, rate_limit_per_min, expected_min_records, next_run_at, meta)
63 + values (:name, :src, :label, :desc, :enabled, :prio, :interval, :mini, :maxi, :pv, :rate, :emr, now(), cast(:meta as jsonb))
64 + on conflict (name) do update set source_id = coalesce(excluded.source_id, connectors.source_id), label = excluded.label, description = excluded.description,
65 + priority = excluded.priority, min_interval_seconds = excluded.min_interval_seconds, max_interval_seconds = excluded.max_interval_seconds,
66 + parser_version = excluded.parser_version, rate_limit_per_min = excluded.rate_limit_per_min, expected_min_records = excluded.expected_min_records,
67 + meta = connectors.meta || excluded.meta, updated_at = now()""",
68 + name=name, src=src["id"] if src else None, label=cls.label or name, desc=cls.description or None,
69 + enabled=bool(getattr(cls, "enabled_by_default", True)), prio=cls.priority, interval=cls.interval_seconds, mini=cls.min_interval_seconds,
70 + maxi=cls.max_interval_seconds, pv=cls.parser_version, rate=cls.rate_per_min, emr=cls.expected_min_records,
71 + meta=jsonb({"version": cls.version, "tier": cls.tier, "needs_llm": cls.needs_llm, "module": cls.__module__}))
72 + n += 1
73 + return n
74 +
75 +
76 +def _writer(conn: AsyncConnection, source_id: str, url: str | None) -> FactWriter:
77 + return FactWriter(conn, source_id=source_id, snapshot_id=None, source_url=url, tier=2, connector_name="registry", extractor="curated", extractor_version="1")
78 +
79 +
80 +async def _seed_organizations(conn: AsyncConnection, source_id: str) -> int:
81 + n = 0
82 + # parents first so `parent` relations resolve
83 + items = sorted(load("organizations"), key=lambda o: 0 if not o.get("parent") else 1)
84 + for o in items:
85 + facts = Facts()
86 + ref = org_ref(o["key"])
87 + facts.entities.append(ref)
88 + for prop in ("country", "headquarters", "founded", "website", "legal_name"):
89 + if o.get(prop):
90 + facts.claim(ref, prop, o[prop], source_url=o.get("source_url"))
91 + if o.get("domains"):
92 + facts.claim(ref, "domains", o["domains"], source_url=o.get("source_url"))
93 + if o.get("hf_org"):
94 + facts.claim(ref, "hf_org", o["hf_org"], source_url=f"https://huggingface.co/{o['hf_org']}")
95 + if o.get("github_org"):
96 + facts.claim(ref, "github_org", o["github_org"], source_url=f"https://github.com/{o['github_org']}")
97 + facts.claim(ref, "org_kind", o.get("type", "company"), source_url=o.get("source_url"))
98 + if o.get("parent") and o["parent"] in organizations():
99 + facts.relate(org_ref(o["parent"]), "owns", ref, source_url=o.get("source_url"))
100 + w = _writer(conn, source_id, o.get("source_url"))
101 + await w.write(facts)
102 + n += 1
103 + return n
104 +
105 +
106 +async def _seed_providers(conn: AsyncConnection, source_id: str) -> int:
107 + n = 0
108 + for p in load("providers"):
109 + facts = Facts()
110 + ref = provider_ref(p["key"])
111 + facts.entities.append(ref)
112 + for prop in ("website", "pricing_url", "docs_url"):
113 + if p.get(prop):
114 + facts.claim(ref, prop, p[prop], source_url=p.get("website"))
115 + if p.get("organization") in organizations():
116 + facts.relate(org_ref(p["organization"]), "operates", ref, source_url=p.get("website"))
117 + await _writer(conn, source_id, p.get("website")).write(facts)
118 + n += 1
119 + return n
120 +
121 +
122 +async def _seed_benchmarks(conn: AsyncConnection, source_id: str) -> int:
123 + n = 0
124 + for b in load("benchmarks"):
125 + facts = Facts()
126 + ref = EntityRef(entity_type="benchmark", name=b["name"], identifiers={"registry_benchmark": b["key"]}, aliases=list(b.get("aliases", [])), slug_hint=b["key"])
127 + facts.entities.append(ref)
128 + for prop in ("category", "task", "metric", "unit", "creator", "website", "paper", "known_limitations", "methodology"):
129 + if b.get(prop) not in (None, ""):
130 + facts.claim(ref, prop, b[prop], source_url=b.get("source_url"))
131 + await _writer(conn, source_id, b.get("source_url")).write(facts)
132 + n += 1
133 + return n
134 +
135 +
136 +async def _seed_hardware(conn: AsyncConnection, source_id: str) -> int:
137 + n = 0
138 + for h in load("hardware"):
139 + facts = Facts()
140 + org = org_ref(h["manufacturer"]) if h.get("manufacturer") in organizations() else None
141 + ref = EntityRef(entity_type="hardware", name=h["name"], identifiers={"registry_hardware": h["key"]}, aliases=list(h.get("aliases", [])), slug_hint=h["key"], organization=org)
142 + facts.entities.append(ref)
143 + for prop in ("kind", "architecture", "release_date", "memory_gb", "memory_type", "memory_bandwidth_gbs", "tdp_watts", "runtimes", "form_factor", "price_usd"):
144 + if h.get(prop) not in (None, ""):
145 + facts.claim(ref, prop, h[prop], source_url=h.get("source_url"))
146 + facts.claim(ref, "manufacturer", organizations()[h["manufacturer"]]["name"] if org else h.get("manufacturer"), source_url=h.get("source_url"))
147 + facts.claim(ref, "spec_url", h.get("source_url"), source_url=h.get("source_url"))
148 + if org:
149 + facts.relate(org, "manufactures", ref, source_url=h.get("source_url"))
150 + await _writer(conn, source_id, h.get("source_url")).write(facts)
151 + n += 1
152 + return n
153 +
154 +
155 +async def _seed_domains(conn: AsyncConnection) -> int:
156 + n = 0
157 + for o in load("organizations"):
158 + row = await fetch_one(conn, "select entity_id from entity_identifiers where scheme = 'registry_org' and value = :v", v=o["key"])
159 + if not row:
160 + continue
161 + for d in o.get("domains", []):
162 + await execute(conn, """insert into domains (domain, organization_id, trust_tier, category) values (:d, :o, 1, :c)
163 + on conflict (domain) do update set organization_id = excluded.organization_id""", d=d, o=row["entity_id"], c=o.get("type", "company"))
164 + n += 1
165 + return n
166 +
167 +
168 +__all__ = ["seed"]
added src/aiatlas/schemas/__init__.py +17 −0
@@ -0,0 +1,17 @@
1 +"""Extraction schemas (pydantic) — the contract between documents and the knowledge graph. Used by the LLM factory and by
2 +deterministic extractors alike; every field is optional because absence of evidence must stay absence."""
3 +from aiatlas.schemas.extraction import (
4 + TASKS,
5 + BenchmarkResultExtraction,
6 + CompanyPassport,
7 + DocumentClassification,
8 + HardwareSpec,
9 + ModelPassport,
10 + PaperPassport,
11 + PricingExtraction,
12 + ReleaseAnnouncement,
13 + schema_for,
14 +)
15 +
16 +__all__ = ["TASKS", "BenchmarkResultExtraction", "CompanyPassport", "DocumentClassification", "HardwareSpec", "ModelPassport", "PaperPassport",
17 + "PricingExtraction", "ReleaseAnnouncement", "schema_for"]
added src/aiatlas/schemas/extraction.py +174 −0
@@ -0,0 +1,174 @@
1 +from __future__ import annotations
2 +
3 +from pydantic import BaseModel, Field
4 +
5 +OPENNESS = ("open-weights", "open-source", "proprietary", "restricted", "unknown")
6 +MODALITIES = ("text", "image", "audio", "video", "code", "embedding", "3d", "multimodal")
7 +
8 +
9 +class DocumentClassification(BaseModel):
10 + doc_class: str = Field(description="one of: model_release, model_update, pricing, research_paper, company_news, product_launch, "
11 + "framework_release, dataset_release, benchmark, hardware, regulation, incident, funding, acquisition, other")
12 + is_primary_source: bool | None = None
13 + mentioned_models: list[str] = Field(default_factory=list)
14 + mentioned_companies: list[str] = Field(default_factory=list)
15 + language: str | None = None
16 + relevance: float = Field(default=0.5, ge=0, le=1, description="relevance to the AI ecosystem")
17 +
18 +
19 +class ModelPassport(BaseModel):
20 + name: str | None = None
21 + developer: str | None = Field(default=None, description="organization that developed the model")
22 + family: str | None = None
23 + version: str | None = None
24 + release_date: str | None = Field(default=None, description="ISO date if stated (YYYY-MM-DD, YYYY-MM or YYYY)")
25 + status: str | None = Field(default=None, description="available | preview | deprecated | retired | announced")
26 + openness: str | None = Field(default=None, description=" | ".join(OPENNESS))
27 + license: str | None = None
28 + architecture: str | None = Field(default=None, description="e.g. transformer decoder, MoE, diffusion, state-space")
29 + parameter_count: int | None = Field(default=None, description="total parameters, as an integer (e.g. 70000000000)")
30 + active_parameter_count: int | None = None
31 + is_moe: bool | None = None
32 + modalities_input: list[str] = Field(default_factory=list)
33 + modalities_output: list[str] = Field(default_factory=list)
34 + context_length: int | None = Field(default=None, description="tokens")
35 + max_output_tokens: int | None = None
36 + knowledge_cutoff: str | None = None
37 + languages: list[str] = Field(default_factory=list)
38 + tool_calling: bool | None = None
39 + structured_output: bool | None = None
40 + reasoning: bool | None = None
41 + vision: bool | None = None
42 + audio: bool | None = None
43 + fine_tuning_available: bool | None = None
44 + tokenizer: str | None = None
45 + training_data_notes: str | None = None
46 + predecessor: str | None = None
47 + base_model: str | None = None
48 + quantizations: list[str] = Field(default_factory=list)
49 + paper_url: str | None = None
50 + model_card_url: str | None = None
51 + repository_url: str | None = None
52 + official_page_url: str | None = None
53 + hardware_requirements: str | None = None
54 + safety_notes: str | None = None
55 + evidence: list[str] = Field(default_factory=list, description="short quotes supporting the most important fields")
56 +
57 +
58 +class PriceLine(BaseModel):
59 + model: str
60 + provider_model_id: str | None = None
61 + input_per_mtok: float | None = Field(default=None, description="USD per 1M input tokens")
62 + output_per_mtok: float | None = None
63 + cached_input_per_mtok: float | None = None
64 + cache_write_per_mtok: float | None = None
65 + batch_input_per_mtok: float | None = None
66 + batch_output_per_mtok: float | None = None
67 + per_image: float | None = None
68 + context_length: int | None = None
69 + max_output_tokens: int | None = None
70 + notes: str | None = None
71 +
72 +
73 +class PricingExtraction(BaseModel):
74 + provider: str | None = None
75 + currency: str = "USD"
76 + effective_date: str | None = None
77 + prices: list[PriceLine] = Field(default_factory=list)
78 +
79 +
80 +class CompanyPassport(BaseModel):
81 + name: str | None = None
82 + legal_name: str | None = None
83 + country: str | None = Field(default=None, description="ISO 3166-1 alpha-2 if determinable")
84 + headquarters: str | None = None
85 + founded: str | None = None
86 + founders: list[str] = Field(default_factory=list)
87 + leadership: list[str] = Field(default_factory=list)
88 + website: str | None = None
89 + description: str | None = None
90 + products: list[str] = Field(default_factory=list)
91 + models: list[str] = Field(default_factory=list)
92 + investors: list[str] = Field(default_factory=list)
93 + parent_company: str | None = None
94 + subsidiaries: list[str] = Field(default_factory=list)
95 + employee_count: int | None = None
96 + funding_total_usd: float | None = None
97 +
98 +
99 +class PaperPassport(BaseModel):
100 + title: str | None = None
101 + authors: list[str] = Field(default_factory=list)
102 + affiliations: list[str] = Field(default_factory=list)
103 + date: str | None = None
104 + field: str | None = None
105 + summary: str | None = Field(default=None, description="2-3 sentence factual summary")
106 + methods: list[str] = Field(default_factory=list)
107 + models: list[str] = Field(default_factory=list, description="models introduced or evaluated")
108 + datasets: list[str] = Field(default_factory=list)
109 + benchmarks: list[str] = Field(default_factory=list)
110 + key_claims: list[str] = Field(default_factory=list)
111 + results: list[str] = Field(default_factory=list)
112 + limitations: list[str] = Field(default_factory=list)
113 + code_url: str | None = None
114 +
115 +
116 +class BenchmarkRow(BaseModel):
117 + model: str
118 + score: float
119 + metric: str | None = None
120 + config: str | None = None
121 +
122 +
123 +class BenchmarkResultExtraction(BaseModel):
124 + benchmark: str | None = None
125 + metric: str | None = None
126 + higher_is_better: bool | None = True
127 + evaluated_at: str | None = None
128 + rows: list[BenchmarkRow] = Field(default_factory=list)
129 +
130 +
131 +class HardwareSpec(BaseModel):
132 + name: str | None = None
133 + manufacturer: str | None = None
134 + kind: str | None = Field(default=None, description="gpu | cpu | npu | tpu | asic | soc | accelerator | system")
135 + architecture: str | None = None
136 + release_date: str | None = None
137 + memory_gb: float | None = None
138 + memory_type: str | None = None
139 + memory_bandwidth_gbs: float | None = None
140 + compute_fp16_tflops: float | None = None
141 + compute_fp8_tflops: float | None = None
142 + compute_int8_tops: float | None = None
143 + tdp_watts: float | None = None
144 + form_factor: str | None = None
145 + price_usd: float | None = None
146 + interconnect: str | None = None
147 +
148 +
149 +class ReleaseAnnouncement(BaseModel):
150 + kind: str | None = Field(default=None, description="new_model | model_update | pricing_change | deprecation | new_product | framework_release | research | other")
151 + title: str | None = None
152 + date: str | None = None
153 + organization: str | None = None
154 + models: list[str] = Field(default_factory=list)
155 + summary: str | None = None
156 + facts: list[str] = Field(default_factory=list, description="atomic factual statements (one per item)")
157 + model_passport: ModelPassport | None = None
158 + pricing: PricingExtraction | None = None
159 +
160 +
161 +TASKS: dict[str, tuple[type[BaseModel], str]] = {
162 + "classify": (DocumentClassification, "small"),
163 + "model_passport": (ModelPassport, "medium"),
164 + "pricing": (PricingExtraction, "medium"),
165 + "company_passport": (CompanyPassport, "medium"),
166 + "paper_passport": (PaperPassport, "medium"),
167 + "benchmark_results": (BenchmarkResultExtraction, "medium"),
168 + "hardware_spec": (HardwareSpec, "medium"),
169 + "release_announcement": (ReleaseAnnouncement, "medium"),
170 +}
171 +
172 +
173 +def schema_for(task: str) -> tuple[type[BaseModel], str]:
174 + return TASKS[task]
added src/aiatlas/sdk/__init__.py +7 −0
@@ -0,0 +1,7 @@
1 +"""Connector SDK — every connector shares this infrastructure: fetch transport, raw archive, extraction, facts, change detection."""
2 +from aiatlas.sdk.connector import BaseConnector, ConnectorError, RunContext, Target
3 +from aiatlas.sdk.facts import Claim, EntityRef, Event, Facts, PriceObs, Relation, ResultObs
4 +from aiatlas.sdk.fetch import BlockedError, FetchError, FetchResult, Fetcher, NotModified
5 +
6 +__all__ = ["BaseConnector", "ConnectorError", "RunContext", "Target", "Claim", "EntityRef", "Event", "Facts", "PriceObs",
7 + "Relation", "ResultObs", "BlockedError", "FetchError", "FetchResult", "Fetcher", "NotModified"]
added src/aiatlas/sdk/archive.py +74 −0
@@ -0,0 +1,74 @@
1 +"""Raw source archive — content-addressed, gzip-compressed, deduplicated. Historical snapshots are never discarded.
2 +
3 +Layout (under AIA_DATA_DIR):
4 + raw/<sha256[0:2]>/<sha256[2:4]>/<sha256>.gz original bytes (HTML, JSON, XML, PDF…)
5 + text/<sha256[0:2]>/<sha256[2:4]>/<sha256>.txt.gz cleaned text
6 +"""
7 +from __future__ import annotations
8 +
9 +import gzip
10 +import hashlib
11 +from pathlib import Path
12 +
13 +from aiatlas.config import settings
14 +
15 +
16 +def _path(root: Path, digest: str, suffix: str) -> Path:
17 + return root / digest[:2] / digest[2:4] / f"{digest}{suffix}"
18 +
19 +
20 +def store_raw(content: bytes, *, sha256: str | None = None) -> str:
21 + """Write bytes once (dedupe by hash); return the path relative to raw_dir."""
22 + digest = sha256 or hashlib.sha256(content).hexdigest()
23 + path = _path(settings.raw_dir, digest, ".gz")
24 + if not path.exists():
25 + path.parent.mkdir(parents=True, exist_ok=True)
26 + tmp = path.with_suffix(".gz.tmp")
27 + with gzip.open(tmp, "wb", compresslevel=6) as fh:
28 + fh.write(content)
29 + tmp.replace(path)
30 + return str(path.relative_to(settings.raw_dir))
31 +
32 +
33 +def store_text(text: str) -> tuple[str, str]:
34 + """Write cleaned text; return (relative path, sha256 of the text)."""
35 + data = text.encode("utf-8")
36 + digest = hashlib.sha256(data).hexdigest()
37 + path = _path(settings.text_dir, digest, ".txt.gz")
38 + if not path.exists():
39 + path.parent.mkdir(parents=True, exist_ok=True)
40 + tmp = path.with_suffix(".gz.tmp")
41 + with gzip.open(tmp, "wb", compresslevel=6) as fh:
42 + fh.write(data)
43 + tmp.replace(path)
44 + return str(path.relative_to(settings.text_dir)), digest
45 +
46 +
47 +def load_raw(rel_path: str) -> bytes:
48 + with gzip.open(settings.raw_dir / rel_path, "rb") as fh:
49 + return fh.read()
50 +
51 +
52 +def load_text(rel_path: str) -> str:
53 + with gzip.open(settings.text_dir / rel_path, "rb") as fh:
54 + return fh.read().decode("utf-8")
55 +
56 +
57 +def archive_size() -> dict[str, int]:
58 + out: dict[str, int] = {}
59 + for name, root in (("raw", settings.raw_dir), ("text", settings.text_dir)):
60 + total = 0
61 + count = 0
62 + if root.exists():
63 + for p in root.rglob("*.gz"):
64 + try:
65 + total += p.stat().st_size
66 + count += 1
67 + except OSError:
68 + pass
69 + out[f"{name}_bytes"] = total
70 + out[f"{name}_files"] = count
71 + return out
72 +
73 +
74 +__all__ = ["store_raw", "store_text", "load_raw", "load_text", "archive_size"]
added src/aiatlas/sdk/connector.py +483 −0
@@ -0,0 +1,483 @@
1 +"""BaseConnector — the lifecycle every connector shares:
2 +
3 + discover() → fetch() → parse() → extract() → diff/write → schedule_next()
4 +
5 +Subclasses usually implement `discover()` (seed URLs / feeds / sitemaps) and `extract()` (structured facts from a parsed document).
6 +`run()` does all bookkeeping: connector_runs, documents, snapshots (raw archive), content-hash change detection, structural diffs,
7 +DOCUMENT_CHANGED events, breakage detection (record count collapse ≠ deletion), circuit breaker and adaptive scheduling.
8 +"""
9 +from __future__ import annotations
10 +
11 +import asyncio
12 +import json
13 +import logging
14 +import time
15 +from dataclasses import dataclass, field
16 +from datetime import UTC, datetime, timedelta
17 +from typing import Any
18 +
19 +from aiatlas.config import settings
20 +from aiatlas.db import execute, fetch_one, jsonb, transaction
21 +from aiatlas.ids import new_id
22 +from aiatlas.sdk import archive
23 +from aiatlas.sdk.extract.feeds import FeedItem, parse_feed
24 +from aiatlas.sdk.extract.html import HtmlDoc, parse_html
25 +from aiatlas.sdk.extract.markdown import MarkdownDoc, parse_markdown
26 +from aiatlas.sdk.facts import Facts, Target
27 +from aiatlas.sdk.fetch import BlockedError, FetchError, Fetcher, FetchResult, NotModified, canonicalize_url, file_result
28 +from aiatlas.sdk.writer import FactWriter
29 +
30 +log = logging.getLogger(__name__)
31 +
32 +CIRCUIT_FAILURES = 3
33 +CIRCUIT_COOLDOWN_S = 1800
34 +
35 +
36 +class ConnectorError(Exception):
37 + pass
38 +
39 +
40 +@dataclass
41 +class Parsed:
42 + kind: str # html|markdown|feed|json|pdf|text|xml
43 + html: HtmlDoc | None = None
44 + markdown: MarkdownDoc | None = None
45 + feed_meta: dict[str, Any] | None = None
46 + feed_items: list[FeedItem] = field(default_factory=list)
47 + json: Any = None
48 + text: str = ""
49 +
50 + def structured(self) -> dict[str, Any] | None:
51 + if self.html:
52 + return self.html.structured()
53 + if self.markdown:
54 + return {"front_matter": _jsonable(self.markdown.front_matter), "headings": self.markdown.headings[:200], "tables": self.markdown.tables[:40],
55 + "link_count": len(self.markdown.links), "text_length": len(self.markdown.text)}
56 + if self.kind == "feed":
57 + return {"feed": self.feed_meta, "items": [{"id": i.id, "url": i.url, "title": i.title, "published_at": i.published_at.isoformat() if i.published_at else None}
58 + for i in self.feed_items[:200]]}
59 + if self.kind == "json":
60 + return {"json_keys": list(self.json)[:100] if isinstance(self.json, dict) else None,
61 + "json_length": len(self.json) if isinstance(self.json, (list, dict)) else None}
62 + return {"text_length": len(self.text)} if self.text else None
63 +
64 +
65 +@dataclass
66 +class RunStats:
67 + docs_discovered: int = 0
68 + docs_fetched: int = 0
69 + docs_changed: int = 0
70 + docs_unchanged: int = 0
71 + docs_failed: int = 0
72 + entities_created: int = 0
73 + entities_updated: int = 0
74 + claims_written: int = 0
75 + relations_written: int = 0
76 + events_emitted: int = 0
77 + records: int = 0 # connector-defined "records" for breakage detection (models, papers, prices…)
78 + meta: dict[str, Any] = field(default_factory=dict)
79 +
80 +
81 +@dataclass
82 +class RunContext:
83 + run_id: str
84 + connector: BaseConnector
85 + fetcher: Fetcher
86 + started_at: datetime
87 + force: bool = False
88 + reprocess: bool = False # re-extract from stored snapshots without fetching
89 + file_overrides: dict[str, str] = field(default_factory=dict) # target.key or url → local path
90 + max_targets: int = 2000
91 + stats: RunStats = field(default_factory=RunStats)
92 + seen_urls: set[str] = field(default_factory=set)
93 + log: logging.LoggerAdapter[logging.Logger] = field(init=False)
94 +
95 + def __post_init__(self) -> None:
96 + self.log = logging.LoggerAdapter(logging.getLogger(f"connector.{self.connector.name}"), {"connector": self.connector.name, "run_id": self.run_id})
97 +
98 +
99 +class BaseConnector:
100 + # ------------------------------------------------------------------------------------------ identity & policy
101 + name: str = ""
102 + label: str = ""
103 + description: str = ""
104 + source_key: str = "" # sources.key (seeded from registry/sources.yaml)
105 + version: str = "1" # connector version
106 + parser_version: str = "1" # bump when extraction improves → `aia reprocess <connector>` replays snapshots
107 + interval_seconds: int = 3600
108 + min_interval_seconds: int = 900
109 + max_interval_seconds: int = 7 * 86400
110 + rate_per_min: int = 30
111 + respect_robots: bool = True
112 + expected_min_records: int = 0
113 + priority: int = 2
114 + tier: int = 1
115 + concurrency: int = 3
116 + default_doc_type: str = "page"
117 + needs_llm: bool = False # queue documents for LLM extraction after deterministic extraction
118 +
119 + def __init__(self, config: dict[str, Any] | None = None):
120 + self.config = config or {}
121 + self.source_id: str | None = None
122 +
123 + # ------------------------------------------------------------------------------------------ to implement
124 + async def discover(self, ctx: RunContext) -> list[Target]:
125 + """Return the targets for this run (seed pages, feeds, sitemaps, org pages…)."""
126 + seeds = self.config.get("seeds") or getattr(self, "seeds", [])
127 + return [Target(url=s) if isinstance(s, str) else Target(**s) for s in seeds]
128 +
129 + async def extract(self, ctx: RunContext, target: Target, res: FetchResult, parsed: Parsed) -> Facts:
130 + """Turn a parsed document into facts. Deterministic only; LLM extraction is queued separately."""
131 + return Facts()
132 +
133 + def parse(self, target: Target, res: FetchResult) -> Parsed:
134 + """Default parser by content type; connectors may override for special formats."""
135 + if res.is_pdf:
136 + return Parsed(kind="pdf", text=_pdf_text(res.content))
137 + if target.doc_type == "feed" or (res.is_xml and b"<rss" in res.content[:2000] or b"<feed" in res.content[:2000]):
138 + meta, items = parse_feed(res.content)
139 + if items or meta.get("title"):
140 + return Parsed(kind="feed", feed_meta=meta, feed_items=items)
141 + if res.is_json:
142 + try:
143 + return Parsed(kind="json", json=res.json())
144 + except Exception: # noqa: BLE001
145 + pass
146 + if res.is_html:
147 + doc = parse_html(res.content, res.final_url or res.url)
148 + return Parsed(kind="html", html=doc, text=doc.text)
149 + text = res.text
150 + if target.doc_type in ("model_card", "readme", "markdown") or "markdown" in res.content_type or res.url.endswith((".md", ".mdx")):
151 + md = parse_markdown(text)
152 + return Parsed(kind="markdown", markdown=md, text=md.text)
153 + if res.is_xml:
154 + return Parsed(kind="xml", text=text)
155 + return Parsed(kind="text", text=text)
156 +
157 + async def healthcheck(self) -> bool:
158 + return True
159 +
160 + # ------------------------------------------------------------------------------------------ orchestration
161 + async def run(self, *, force: bool = False, reprocess: bool = False, file_overrides: dict[str, str] | None = None,
162 + max_targets: int | None = None, only_urls: list[str] | None = None) -> RunContext:
163 + started = datetime.now(UTC)
164 + run_id = new_id("connector_run")
165 + async with Fetcher(rate_per_min=self.rate_per_min, robots=self.respect_robots) as fetcher:
166 + ctx = RunContext(run_id=run_id, connector=self, fetcher=fetcher, started_at=started, force=force, reprocess=reprocess,
167 + file_overrides=file_overrides or {}, max_targets=max_targets or int(self.config.get("max_targets", 2000)))
168 + async with transaction() as conn:
169 + state = await fetch_one(conn, "select source_id, enabled, circuit_open_until from connectors where name = :n", n=self.name)
170 + if state is None:
171 + raise ConnectorError(f"connector {self.name!r} not registered (run `aia seed`)")
172 + self.source_id = state["source_id"]
173 + if not state["enabled"] and not force:
174 + ctx.log.info("connector disabled, skipping")
175 + await self._record(conn, ctx, "skipped", error="disabled")
176 + return ctx
177 + if state["circuit_open_until"] and state["circuit_open_until"] > started and not force:
178 + ctx.log.warning("circuit open, skipping", extra={"until": state["circuit_open_until"].isoformat()})
179 + await self._record(conn, ctx, "skipped", error="circuit open")
180 + return ctx
181 + await execute(conn, "insert into connector_runs (id, connector_name, started_at, status) values (:id, :c, :t, 'running')", id=run_id, c=self.name, t=started)
182 + await execute(conn, "update connectors set last_attempt_at = :t, health = case when health = 'unknown' then 'degraded' else health end where name = :n",
183 + t=started, n=self.name)
184 + t0 = time.perf_counter()
185 + try:
186 + targets = await self.discover(ctx)
187 + if only_urls:
188 + wanted = {canonicalize_url(u) for u in only_urls}
189 + targets = [t for t in targets if canonicalize_url(t.url) in wanted] or [Target(url=u) for u in only_urls]
190 + ctx.stats.docs_discovered = len(targets)
191 + await self._process_all(ctx, targets)
192 + status = self._final_status(ctx)
193 + async with transaction() as conn:
194 + await self._record(conn, ctx, status)
195 + changed = ctx.stats.docs_changed > 0
196 + await execute(conn, """update connectors set consecutive_failures = 0, circuit_open_until = null, last_success_at = now(),
197 + last_change_at = case when cast(:changed as boolean) then now() else last_change_at end,
198 + consecutive_unchanged = case when cast(:changed as boolean) then 0 else consecutive_unchanged + 1 end,
199 + interval_seconds = cast(:interval as integer), next_run_at = now() + make_interval(secs => cast(:interval as double precision)),
200 + last_duration_ms = :d, health = :health, updated_at = now() where name = :n""",
201 + changed=changed, interval=await self._next_interval(conn, changed), d=int((time.perf_counter() - t0) * 1000),
202 + health="degraded" if status == "suspect" else "ok", n=self.name)
203 + if status == "suspect":
204 + await execute(conn, """insert into review_queue (id, kind, entity_ids, payload, reason, dedupe_key)
205 + values (:id, 'parser_breakage', '{}', cast(:p as jsonb), :r, :d) on conflict (dedupe_key) do nothing""",
206 + id=new_id("review"), p=jsonb({"connector": self.name, "run_id": run_id, "records": ctx.stats.records, "expected_min": self.expected_min_records}),
207 + r=f"{self.name}: {ctx.stats.records} records < expected {self.expected_min_records} — connector failure suspected, nothing deleted",
208 + d=f"parser_breakage:{self.name}:{started.date()}")
209 + ctx.log.info("run finished", extra={"status": status, **{k: v for k, v in ctx.stats.__dict__.items() if k != "meta"},
210 + "ms": int((time.perf_counter() - t0) * 1000)})
211 + except Exception as exc: # noqa: BLE001
212 + ctx.log.exception("run failed", extra={"error": str(exc)})
213 + async with transaction() as conn:
214 + await self._record(conn, ctx, "failed", error=f"{exc.__class__.__name__}: {exc}"[:2000])
215 + await execute(conn, "insert into connector_errors (connector_name, run_id, error_type, message) values (:n, :r, :t, :m)",
216 + n=self.name, r=run_id, t=exc.__class__.__name__, m=str(exc)[:4000])
217 + row = await fetch_one(conn, """update connectors set consecutive_failures = consecutive_failures + 1, last_duration_ms = :d, health = 'failing',
218 + next_run_at = now() + make_interval(secs => least(interval_seconds, 3600)), updated_at = now()
219 + where name = :n returning consecutive_failures""", d=int((time.perf_counter() - t0) * 1000), n=self.name)
220 + if row and row["consecutive_failures"] >= CIRCUIT_FAILURES:
221 + until = datetime.now(UTC) + timedelta(seconds=CIRCUIT_COOLDOWN_S)
222 + await execute(conn, "update connectors set circuit_open_until = :u where name = :n", u=until, n=self.name)
223 + ctx.log.error("circuit opened", extra={"until": until.isoformat()})
224 + raise
225 + return ctx
226 +
227 + def _final_status(self, ctx: RunContext) -> str:
228 + s = ctx.stats
229 + if self.expected_min_records and s.records < self.expected_min_records and not ctx.reprocess:
230 + return "suspect"
231 + if s.docs_fetched and s.docs_failed == s.docs_fetched and s.docs_fetched > 0:
232 + return "failed" if s.docs_changed == 0 else "success"
233 + return "unchanged" if s.docs_changed == 0 else "success"
234 +
235 + async def _next_interval(self, conn: Any, changed: bool) -> int:
236 + row = await fetch_one(conn, "select interval_seconds, consecutive_unchanged, min_interval_seconds, max_interval_seconds from connectors where name = :n", n=self.name)
237 + if not row:
238 + return self.interval_seconds
239 + cur = row["interval_seconds"] or self.interval_seconds
240 + lo, hi = row["min_interval_seconds"] or self.min_interval_seconds, row["max_interval_seconds"] or self.max_interval_seconds
241 + if changed:
242 + return max(lo, int(cur * 0.7))
243 + if row["consecutive_unchanged"] >= 3:
244 + return min(hi, int(cur * 1.5))
245 + return cur
246 +
247 + async def _process_all(self, ctx: RunContext, targets: list[Target]) -> None:
248 + queue: asyncio.Queue[Target] = asyncio.Queue()
249 + for t in targets:
250 + queue.put_nowait(t)
251 + processed = 0
252 + sem = asyncio.Semaphore(max(1, self.concurrency))
253 + pending: set[asyncio.Task[None]] = set()
254 +
255 + async def worker(target: Target) -> None:
256 + nonlocal processed
257 + async with sem:
258 + followups = await self._process_target(ctx, target)
259 + for f in followups:
260 + cu = canonicalize_url(f.url)
261 + if cu not in ctx.seen_urls and processed + queue.qsize() < ctx.max_targets:
262 + queue.put_nowait(f)
263 +
264 + while not queue.empty() or pending:
265 + while not queue.empty() and processed < ctx.max_targets:
266 + target = queue.get_nowait()
267 + cu = canonicalize_url(target.url)
268 + if cu in ctx.seen_urls:
269 + continue
270 + ctx.seen_urls.add(cu)
271 + processed += 1
272 + task = asyncio.create_task(worker(target))
273 + pending.add(task)
274 + task.add_done_callback(pending.discard)
275 + if pending:
276 + await asyncio.wait(pending, return_when=asyncio.FIRST_COMPLETED)
277 + elif queue.empty():
278 + break
279 +
280 + async def _process_target(self, ctx: RunContext, target: Target) -> list[Target]:
281 + url = canonicalize_url(target.url)
282 + doc_type = target.doc_type or self.default_doc_type
283 + async with transaction() as conn:
284 + doc = await fetch_one(conn, "select * from documents where url = :u", u=url)
285 + if doc is None:
286 + doc_id = new_id("document")
287 + await execute(conn, """insert into documents (id, source_id, connector_name, url, doc_type, priority, meta) values (:id, :s, :c, :u, :t, :p, cast(:m as jsonb))
288 + on conflict (url) do nothing""", id=doc_id, s=self.source_id, c=self.name, u=url, t=doc_type, p=target.priority, m=jsonb(target.meta))
289 + doc = await fetch_one(conn, "select * from documents where url = :u", u=url)
290 + assert doc
291 + # ---- reprocess mode: replay latest snapshot without network
292 + if ctx.reprocess:
293 + async with transaction() as conn:
294 + snap = await fetch_one(conn, "select * from snapshots where document_id = :d and changed order by observed_at desc limit 1", d=doc["id"])
295 + if not snap or not snap["raw_path"]:
296 + return []
297 + res = FetchResult(url=url, final_url=snap["final_url"] or url, status=snap["http_status"] or 200, headers=snap["headers"] or {},
298 + content=archive.load_raw(snap["raw_path"]), content_type=snap["content_type"] or "", fetched_at=snap["observed_at"], duration_ms=0,
299 + transport="file")
300 + return await self._extract_and_write(ctx, target, doc, snap["id"], res, first_time=False)
301 + # ---- fetch
302 + override = ctx.file_overrides.get(target.key or "") or ctx.file_overrides.get(url) or ctx.file_overrides.get(target.url)
303 + try:
304 + if override:
305 + res = file_result(override, url=url, content_type=target.meta.get("content_type", "text/html"))
306 + else:
307 + res = await ctx.fetcher.get(url, etag=doc["etag"] if not ctx.force else None, last_modified=doc["last_modified"] if not ctx.force else None,
308 + min_bytes=target.min_bytes, escalate=target.escalate, accept=target.accept, rate_per_min=target.rate_per_min)
309 + except NotModified:
310 + ctx.stats.docs_fetched += 1
311 + ctx.stats.docs_unchanged += 1
312 + async with transaction() as conn:
313 + await execute(conn, "update documents set last_fetched_at = now(), fetch_count = fetch_count + 1, last_status = 304, fail_count = 0 where id = :id", id=doc["id"])
314 + return []
315 + except BlockedError as exc:
316 + ctx.stats.docs_fetched += 1
317 + ctx.stats.docs_failed += 1
318 + ctx.log.warning("blocked", extra={"url": url, "error": str(exc)})
319 + async with transaction() as conn:
320 + await execute(conn, "update documents set last_fetched_at = now(), fetch_count = fetch_count + 1, fail_count = fail_count + 1, last_status = :s, status = 'blocked' where id = :id",
321 + s=exc.status, id=doc["id"])
322 + await execute(conn, "insert into connector_errors (connector_name, run_id, url, error_type, message) values (:n, :r, :u, 'blocked', :m)",
323 + n=self.name, r=ctx.run_id, u=url, m=str(exc)[:2000])
324 + await execute(conn, """insert into review_queue (id, kind, entity_ids, payload, reason, dedupe_key) values (:id, 'blocked_source', '{}', cast(:p as jsonb), :r, :d)
325 + on conflict (dedupe_key) do nothing""", id=new_id("review"), p=jsonb({"url": url, "connector": self.name, "status": exc.status}),
326 + r=f"{self.name}: access denied for {url}", d=f"blocked:{url}")
327 + return []
328 + except FetchError as exc:
329 + ctx.stats.docs_fetched += 1
330 + ctx.stats.docs_failed += 1
331 + ctx.log.warning("fetch failed", extra={"url": url, "error": str(exc)})
332 + async with transaction() as conn:
333 + gone = exc.status in (404, 410)
334 + await execute(conn, """update documents set last_fetched_at = now(), fetch_count = fetch_count + 1, fail_count = fail_count + 1, last_status = :s,
335 + status = case when :gone and fail_count >= 2 then 'gone' else status end where id = :id""", s=exc.status, gone=gone, id=doc["id"])
336 + await execute(conn, "insert into connector_errors (connector_name, run_id, url, error_type, message) values (:n, :r, :u, :t, :m)",
337 + n=self.name, r=ctx.run_id, u=url, t=exc.__class__.__name__, m=str(exc)[:2000])
338 + return []
339 + ctx.stats.docs_fetched += 1
340 + changed = res.sha256 != doc["content_hash"]
341 + first_time = doc["content_hash"] is None
342 + if not changed and not ctx.force:
343 + ctx.stats.docs_unchanged += 1
344 + async with transaction() as conn:
345 + await execute(conn, """update documents set last_fetched_at = now(), fetch_count = fetch_count + 1, last_status = :s, fail_count = 0,
346 + etag = coalesce(:etag, etag), last_modified = coalesce(:lm, last_modified) where id = :id""",
347 + s=res.status, etag=res.headers.get("etag"), lm=res.headers.get("last-modified"), id=doc["id"])
348 + return []
349 + # ---- changed (or forced): archive + snapshot + extract
350 + parsed = self.parse(target, res)
351 + raw_path = archive.store_raw(res.content, sha256=res.sha256)
352 + text_path, text_hash = archive.store_text(parsed.text) if parsed.text else (None, None)
353 + structured = parsed.structured()
354 + snapshot_id = new_id("snapshot")
355 + async with transaction() as conn:
356 + prev = await fetch_one(conn, "select structured, text_hash from snapshots where document_id = :d and changed order by observed_at desc limit 1", d=doc["id"])
357 + diff = _structural_diff(prev["structured"] if prev else None, structured) if prev else None
358 + semantic_change = not prev or prev["text_hash"] != text_hash or bool(diff)
359 + await execute(conn, """insert into snapshots (id, document_id, run_id, url, final_url, observed_at, http_status, headers, content_type, content_hash, byte_size,
360 + raw_path, text_path, text_hash, structured, parser_version, connector_version, transport, changed, diff, processing_status)
361 + values (:id, :d, :run, :u, :fu, :o, :st, cast(:h as jsonb), :ct, :hash, :size, :rp, :tp, :th, cast(:s as jsonb), :pv, :cv, :tr, :changed, cast(:diff as jsonb), 'stored')""",
362 + id=snapshot_id, d=doc["id"], run=ctx.run_id, u=url, fu=res.final_url, o=res.fetched_at, st=res.status,
363 + h=jsonb({k: v for k, v in res.headers.items() if k in ("etag", "last-modified", "content-type", "content-length", "server", "cache-control", "date")}),
364 + ct=res.content_type[:200], hash=res.sha256, size=len(res.content), rp=raw_path, tp=text_path, th=text_hash, s=jsonb(structured) if structured else None,
365 + pv=self.parser_version, cv=self.version, tr=res.transport, changed=changed, diff=jsonb(diff) if diff else None)
366 + title = (parsed.html.title if parsed.html else None) or (parsed.feed_meta or {}).get("title") if parsed.kind == "feed" else (parsed.html.title if parsed.html else None)
367 + await execute(conn, """update documents set last_fetched_at = now(), last_changed_at = case when :changed then now() else last_changed_at end,
368 + fetch_count = fetch_count + 1, change_count = change_count + case when :changed and not :first then 1 else 0 end, last_status = :s, fail_count = 0,
369 + content_hash = :hash, etag = :etag, last_modified = :lm, canonical_url = coalesce(:canon, canonical_url), title = coalesce(:title, title),
370 + status = 'active', needs_llm = :llm, doc_type = :dt where id = :id""",
371 + changed=changed, first=first_time, s=res.status, hash=res.sha256, etag=res.headers.get("etag"), lm=res.headers.get("last-modified"),
372 + canon=(parsed.html.canonical if parsed.html else None), title=(title or None), llm=bool(target.needs_llm or self.needs_llm), dt=doc_type, id=doc["id"])
373 + if changed and not first_time and semantic_change and doc_type not in ("feed", "sitemap", "listing"):
374 + await execute(conn, """insert into change_events (id, entity_id, event_type, category, summary, importance, observed_at, source_id, snapshot_id, source_url,
375 + connector_name, dedupe_key, meta) values (:id, :e, 'DOCUMENT_CHANGED', 'source', :s, 0, now(), :src, :snap, :u, :c, :d, cast(:m as jsonb))
376 + on conflict (dedupe_key) do nothing""",
377 + id=new_id("change_event"), e=doc["entity_id"], s=f"{title or url} changed", src=self.source_id, snap=snapshot_id, u=url, c=self.name,
378 + d=f"DOCUMENT_CHANGED:{snapshot_id}", m=jsonb({"doc_type": doc_type, "diff_keys": list(diff)[:20] if diff else []}))
379 + if changed:
380 + ctx.stats.docs_changed += 1
381 + return await self._extract_and_write(ctx, target, doc, snapshot_id, res, first_time=first_time, parsed=parsed)
382 +
383 + async def _extract_and_write(self, ctx: RunContext, target: Target, doc: dict[str, Any], snapshot_id: str, res: FetchResult, *,
384 + first_time: bool, parsed: Parsed | None = None) -> list[Target]:
385 + parsed = parsed or self.parse(target, res)
386 + try:
387 + facts = await self.extract(ctx, target, res, parsed)
388 + except Exception as exc: # noqa: BLE001
389 + ctx.log.exception("extract failed", extra={"url": res.url})
390 + async with transaction() as conn:
391 + await execute(conn, "insert into connector_errors (connector_name, run_id, url, error_type, message) values (:n, :r, :u, :t, :m)",
392 + n=self.name, r=ctx.run_id, u=res.url, t=f"extract:{exc.__class__.__name__}", m=str(exc)[:2000])
393 + await execute(conn, "update snapshots set processing_status = 'failed' where id = :id", id=snapshot_id)
394 + return []
395 + if facts is None:
396 + return []
397 + async with transaction() as conn:
398 + writer = FactWriter(conn, source_id=self.source_id, snapshot_id=snapshot_id, source_url=res.final_url or res.url, tier=self.tier,
399 + connector_name=self.name, extractor="deterministic", extractor_version=self.parser_version, observed_at=res.fetched_at)
400 + ws = await writer.write(facts)
401 + main = facts.document_entity or target.entity
402 + if main and main.id is None:
403 + await writer.resolver.resolve(main)
404 + if main and main.id:
405 + await execute(conn, "update documents set entity_id = coalesce(entity_id, :e), title = coalesce(:t, title) where id = :id", e=main.id, t=facts.document_title, id=doc["id"])
406 + await execute(conn, "update snapshots set processing_status = :st where id = :id",
407 + st="llm_pending" if (target.needs_llm or self.needs_llm or facts.llm_hint) else "extracted", id=snapshot_id)
408 + if target.needs_llm or self.needs_llm or facts.llm_hint:
409 + from aiatlas.services.jobs import enqueue
410 +
411 + await enqueue(conn, "llm_extract", {"snapshot_id": snapshot_id, "task": facts.llm_hint or target.meta.get("llm_task") or "auto",
412 + "entity_id": main.id if main else None, "connector": self.name}, priority=4,
413 + dedupe_key=f"llm_extract:{snapshot_id}")
414 + s = ctx.stats
415 + s.entities_created += ws.entities_created
416 + s.entities_updated += ws.entities_updated
417 + s.claims_written += ws.claims
418 + s.relations_written += ws.relations
419 + s.events_emitted += ws.events
420 + s.records += len(facts.entities) + len(facts.prices) + len(facts.results)
421 + return facts.targets
422 +
423 + async def _record(self, conn: Any, ctx: RunContext, status: str, *, error: str | None = None) -> None:
424 + s = ctx.stats
425 + await execute(conn, """insert into connector_runs (id, connector_name, started_at, finished_at, status, duration_ms, docs_discovered, docs_fetched, docs_changed,
426 + docs_unchanged, docs_failed, entities_created, entities_updated, claims_written, relations_written, events_emitted, error, meta)
427 + values (:id, :c, :started, now(), :status, :dur, :dd, :df, :dc, :du, :dfail, :ec, :eu, :cw, :rw, :ee, :err, cast(:meta as jsonb))
428 + on conflict (id) do update set finished_at = now(), status = excluded.status, duration_ms = excluded.duration_ms,
429 + docs_discovered = excluded.docs_discovered, docs_fetched = excluded.docs_fetched, docs_changed = excluded.docs_changed,
430 + docs_unchanged = excluded.docs_unchanged, docs_failed = excluded.docs_failed, entities_created = excluded.entities_created,
431 + entities_updated = excluded.entities_updated, claims_written = excluded.claims_written, relations_written = excluded.relations_written,
432 + events_emitted = excluded.events_emitted, error = excluded.error, meta = excluded.meta""",
433 + id=ctx.run_id, c=self.name, started=ctx.started_at, status=status, dur=int((datetime.now(UTC) - ctx.started_at).total_seconds() * 1000),
434 + dd=s.docs_discovered, df=s.docs_fetched, dc=s.docs_changed, du=s.docs_unchanged, dfail=s.docs_failed, ec=s.entities_created, eu=s.entities_updated,
435 + cw=s.claims_written, rw=s.relations_written, ee=s.events_emitted, err=error, meta=jsonb({**s.meta, "records": s.records}))
436 +
437 +
438 +def _structural_diff(prev: dict[str, Any] | None, cur: dict[str, Any] | None) -> dict[str, Any] | None:
439 + if not prev or not cur:
440 + return None
441 + diff: dict[str, Any] = {}
442 + for key in ("title", "description", "headings", "tables", "json_ld", "front_matter", "published_at", "modified_at", "items"):
443 + a, b = prev.get(key), cur.get(key)
444 + if a != b:
445 + if isinstance(a, list) and isinstance(b, list):
446 + sa = {json.dumps(x, sort_keys=True, default=str) for x in a}
447 + sb = {json.dumps(x, sort_keys=True, default=str) for x in b}
448 + added = [json.loads(x) for x in list(sb - sa)[:50]]
449 + removed = [json.loads(x) for x in list(sa - sb)[:50]]
450 + if added or removed:
451 + diff[key] = {"added": added, "removed": removed}
452 + else:
453 + diff[key] = {"old": a, "new": b}
454 + return diff or None
455 +
456 +
457 +def _pdf_text(content: bytes) -> str:
458 + try:
459 + import io
460 +
461 + from pypdf import PdfReader
462 +
463 + reader = PdfReader(io.BytesIO(content))
464 + parts = []
465 + for page in reader.pages[:60]:
466 + try:
467 + parts.append(page.extract_text() or "")
468 + except Exception: # noqa: BLE001
469 + continue
470 + return "\n\n".join(parts).strip()
471 + except Exception: # noqa: BLE001
472 + return ""
473 +
474 +
475 +def _jsonable(obj: Any) -> Any:
476 + try:
477 + json.dumps(obj)
478 + return obj
479 + except (TypeError, ValueError):
480 + return json.loads(json.dumps(obj, default=str))
481 +
482 +
483 +__all__ = ["BaseConnector", "ConnectorError", "RunContext", "RunStats", "Parsed", "Target"]
added src/aiatlas/sdk/extract/__init__.py +12 −0
@@ -0,0 +1,12 @@
1 +"""Deterministic extraction (Stage 1): DOM, metadata, JSON-LD, embedded JSON, feeds, sitemaps, markdown, tables, numbers, dates.
2 +Always run before any LLM."""
3 +from aiatlas.sdk.extract.dates import parse_date, parse_datetime
4 +from aiatlas.sdk.extract.feeds import FeedItem, parse_feed
5 +from aiatlas.sdk.extract.html import HtmlDoc, parse_html
6 +from aiatlas.sdk.extract.markdown import MarkdownDoc, parse_front_matter, parse_markdown
7 +from aiatlas.sdk.extract.numbers import parse_context_length, parse_money_per_mtok, parse_param_count, parse_percent, parse_tokens
8 +from aiatlas.sdk.extract.sitemap import parse_sitemap
9 +
10 +__all__ = ["parse_date", "parse_datetime", "FeedItem", "parse_feed", "HtmlDoc", "parse_html", "MarkdownDoc", "parse_front_matter",
11 + "parse_markdown", "parse_context_length", "parse_money_per_mtok", "parse_param_count", "parse_percent", "parse_tokens",
12 + "parse_sitemap"]
added src/aiatlas/sdk/extract/dates.py +71 −0
@@ -0,0 +1,71 @@
1 +"""Dates in the wild → aware datetimes (UTC). Partial dates ('March 2025', '2024') keep a precision marker."""
2 +from __future__ import annotations
3 +
4 +import re
5 +from datetime import UTC, date, datetime
6 +
7 +from dateutil import parser as duparser
8 +
9 +_MONTHS = "january|february|march|april|may|june|july|august|september|october|november|december|jan|feb|mar|apr|jun|jul|aug|sep|sept|oct|nov|dec"
10 +_MONTH_YEAR = re.compile(rf"\b({_MONTHS})\.?\s+(\d{{4}})\b", re.I)
11 +_YEAR = re.compile(r"\b(19[89]\d|20[0-4]\d)\b")
12 +
13 +
14 +def parse_datetime(value: str | datetime | date | None, *, default_tz=UTC) -> datetime | None:
15 + if value is None:
16 + return None
17 + if isinstance(value, datetime):
18 + return value if value.tzinfo else value.replace(tzinfo=default_tz)
19 + if isinstance(value, date):
20 + return datetime(value.year, value.month, value.day, tzinfo=default_tz)
21 + s = str(value).strip()
22 + if not s:
23 + return None
24 + if re.fullmatch(r"\d{10}(\.\d+)?", s):
25 + return datetime.fromtimestamp(float(s), tz=UTC)
26 + if re.fullmatch(r"\d{13}", s):
27 + return datetime.fromtimestamp(int(s) / 1000, tz=UTC)
28 + try:
29 + dt = duparser.parse(s, fuzzy=False)
30 + return dt if dt.tzinfo else dt.replace(tzinfo=default_tz)
31 + except (ValueError, OverflowError, TypeError):
32 + pass
33 + return None
34 +
35 +
36 +def parse_date(value: str | None) -> tuple[date | None, str]:
37 + """Return (date, precision) where precision ∈ {'day','month','year','none'}. Fuzzy text allowed."""
38 + if not value:
39 + return None, "none"
40 + s = str(value).strip()
41 + dt = parse_datetime(s)
42 + if dt and re.search(r"\d{1,2}", s) and not _MONTH_YEAR.fullmatch(s) and not _YEAR.fullmatch(s):
43 + return dt.date(), "day"
44 + m = _MONTH_YEAR.search(s)
45 + if m:
46 + try:
47 + d = duparser.parse(f"1 {m.group(1)} {m.group(2)}")
48 + return d.date(), "month"
49 + except ValueError:
50 + pass
51 + m = _YEAR.search(s)
52 + if m:
53 + return date(int(m.group(1)), 1, 1), "year"
54 + try:
55 + d = duparser.parse(s, fuzzy=True, default=datetime(1900, 1, 1))
56 + if d.year > 1900:
57 + return d.date(), "day"
58 + except (ValueError, OverflowError):
59 + pass
60 + return None, "none"
61 +
62 +
63 +def iso(dt: datetime | date | None) -> str | None:
64 + if dt is None:
65 + return None
66 + if isinstance(dt, datetime):
67 + return dt.astimezone(UTC).isoformat(timespec="seconds")
68 + return dt.isoformat()
69 +
70 +
71 +__all__ = ["parse_datetime", "parse_date", "iso"]
added src/aiatlas/sdk/extract/feeds.py +76 −0
@@ -0,0 +1,76 @@
1 +"""RSS / Atom feeds (feedparser) → normalized items."""
2 +from __future__ import annotations
3 +
4 +from dataclasses import dataclass, field
5 +from datetime import UTC, datetime
6 +from typing import Any
7 +
8 +import feedparser
9 +
10 +from aiatlas.sdk.extract.html import clean_text
11 +
12 +
13 +@dataclass
14 +class FeedItem:
15 + id: str
16 + url: str
17 + title: str
18 + summary: str | None
19 + published_at: datetime | None
20 + updated_at: datetime | None
21 + authors: list[str] = field(default_factory=list)
22 + categories: list[str] = field(default_factory=list)
23 + content_html: str | None = None
24 + raw: dict[str, Any] = field(default_factory=dict, repr=False)
25 +
26 +
27 +def _dt(struct: Any) -> datetime | None:
28 + if not struct:
29 + return None
30 + try:
31 + return datetime(*struct[:6], tzinfo=UTC)
32 + except Exception: # noqa: BLE001
33 + return None
34 +
35 +
36 +def parse_feed(content: bytes | str) -> tuple[dict[str, Any], list[FeedItem]]:
37 + parsed = feedparser.parse(content)
38 + feed_meta = {"title": parsed.feed.get("title"), "link": parsed.feed.get("link"), "updated": parsed.feed.get("updated"),
39 + "subtitle": parsed.feed.get("subtitle"), "bozo": bool(parsed.get("bozo"))}
40 + items: list[FeedItem] = []
41 + for e in parsed.entries:
42 + url = e.get("link") or ""
43 + if not url:
44 + for link in e.get("links", []):
45 + if link.get("rel") in (None, "alternate") and link.get("href"):
46 + url = link["href"]
47 + break
48 + content_html = None
49 + if e.get("content"):
50 + content_html = e["content"][0].get("value")
51 + summary = e.get("summary") or e.get("description")
52 + items.append(FeedItem(
53 + id=e.get("id") or e.get("guid") or url,
54 + url=url,
55 + title=clean_text(e.get("title") or "")[:500],
56 + summary=clean_text(_strip_tags(summary))[:4000] if summary else None,
57 + published_at=_dt(e.get("published_parsed")) or _dt(e.get("created_parsed")),
58 + updated_at=_dt(e.get("updated_parsed")),
59 + authors=[a.get("name") for a in e.get("authors", []) if a.get("name")] or ([e["author"]] if e.get("author") else []),
60 + categories=[t.get("term") for t in e.get("tags", []) if t.get("term")],
61 + content_html=content_html,
62 + raw={k: v for k, v in e.items() if isinstance(v, (str, int, float))},
63 + ))
64 + return feed_meta, items
65 +
66 +
67 +def _strip_tags(s: str) -> str:
68 + from selectolax.parser import HTMLParser
69 +
70 + try:
71 + return HTMLParser(s).text(separator=" ")
72 + except Exception: # noqa: BLE001
73 + return s
74 +
75 +
76 +__all__ = ["FeedItem", "parse_feed"]
added src/aiatlas/sdk/extract/html.py +236 −0
@@ -0,0 +1,236 @@
1 +"""HTML parsing with selectolax: title, meta, canonical, Open Graph, JSON-LD, embedded JSON (Next.js/Nuxt/data-props),
2 +headings, tables, links, cleaned text."""
3 +from __future__ import annotations
4 +
5 +import html as htmlmod
6 +import json
7 +import re
8 +from dataclasses import dataclass, field
9 +from typing import Any
10 +from urllib.parse import urljoin
11 +
12 +from selectolax.parser import HTMLParser, Node
13 +
14 +_WS = re.compile(r"[ \t\r\f\v]+")
15 +_NL = re.compile(r"\n{3,}")
16 +_SKIP_TAGS = {"script", "style", "noscript", "svg", "template", "iframe", "canvas", "nav", "footer", "form", "button"}
17 +
18 +
19 +@dataclass
20 +class HtmlDoc:
21 + url: str
22 + title: str | None = None
23 + canonical: str | None = None
24 + description: str | None = None
25 + lang: str | None = None
26 + meta: dict[str, str] = field(default_factory=dict)
27 + og: dict[str, str] = field(default_factory=dict)
28 + json_ld: list[Any] = field(default_factory=list)
29 + embedded_json: dict[str, Any] = field(default_factory=dict) # id/key -> parsed JSON
30 + headings: list[tuple[int, str]] = field(default_factory=list)
31 + tables: list[dict[str, Any]] = field(default_factory=list) # {"headers": [...], "rows": [[...]], "caption": str}
32 + links: list[tuple[str, str]] = field(default_factory=list) # (absolute href, anchor text)
33 + text: str = ""
34 + published_at: str | None = None
35 + modified_at: str | None = None
36 + tree: HTMLParser | None = field(default=None, repr=False)
37 +
38 + def structured(self) -> dict[str, Any]:
39 + """JSON-serialisable summary stored in `snapshots.structured`."""
40 + return {
41 + "title": self.title, "canonical": self.canonical, "description": self.description, "lang": self.lang,
42 + "meta": {k: v for k, v in self.meta.items() if len(v) < 500}, "og": self.og,
43 + "json_ld": self.json_ld[:20], "embedded_json_keys": list(self.embedded_json)[:50],
44 + "headings": self.headings[:200], "tables": self.tables[:40], "published_at": self.published_at, "modified_at": self.modified_at,
45 + "link_count": len(self.links), "text_length": len(self.text),
46 + }
47 +
48 + def css(self, selector: str) -> list[Node]:
49 + return self.tree.css(selector) if self.tree else []
50 +
51 + def css_first(self, selector: str) -> Node | None:
52 + return self.tree.css_first(selector) if self.tree else None
53 +
54 + def links_matching(self, pattern: str | re.Pattern[str]) -> list[tuple[str, str]]:
55 + rx = re.compile(pattern) if isinstance(pattern, str) else pattern
56 + seen: set[str] = set()
57 + out: list[tuple[str, str]] = []
58 + for href, text in self.links:
59 + if href not in seen and rx.search(href):
60 + seen.add(href)
61 + out.append((href, text))
62 + return out
63 +
64 +
65 +def clean_text(s: str) -> str:
66 + s = htmlmod.unescape(s)
67 + s = _WS.sub(" ", s)
68 + s = "\n".join(line.strip() for line in s.split("\n"))
69 + return _NL.sub("\n\n", s).strip()
70 +
71 +
72 +def node_text(node: Node, *, separator: str = " ") -> str:
73 + return clean_text(node.text(separator=separator, strip=True))
74 +
75 +
76 +def parse_html(content: str | bytes, url: str = "", *, keep_tree: bool = True, max_links: int = 5000) -> HtmlDoc:
77 + tree = HTMLParser(content)
78 + doc = HtmlDoc(url=url, tree=tree if keep_tree else None)
79 + if (html_node := tree.css_first("html")) is not None:
80 + doc.lang = html_node.attributes.get("lang")
81 + if (t := tree.css_first("title")) is not None:
82 + doc.title = clean_text(t.text()) or None
83 +
84 + for m in tree.css("meta"):
85 + a = m.attributes
86 + key = a.get("property") or a.get("name") or a.get("itemprop")
87 + val = a.get("content")
88 + if not key or val is None:
89 + continue
90 + key = key.strip().lower()
91 + val = val.strip()
92 + if key.startswith(("og:", "twitter:", "article:")):
93 + doc.og[key] = val
94 + else:
95 + doc.meta.setdefault(key, val)
96 + doc.description = doc.meta.get("description") or doc.og.get("og:description")
97 + if not doc.title:
98 + doc.title = doc.og.get("og:title")
99 + doc.published_at = (doc.og.get("article:published_time") or doc.meta.get("date") or doc.meta.get("pubdate")
100 + or doc.meta.get("publish_date") or doc.meta.get("datepublished") or doc.meta.get("dc.date.issued"))
101 + doc.modified_at = doc.og.get("article:modified_time") or doc.meta.get("last-modified") or doc.meta.get("datemodified")
102 +
103 + for link in tree.css("link[rel]"):
104 + rel = (link.attributes.get("rel") or "").lower()
105 + href = link.attributes.get("href")
106 + if "canonical" in rel and href:
107 + doc.canonical = urljoin(url, href)
108 +
109 + for s in tree.css("script"):
110 + stype = (s.attributes.get("type") or "").lower()
111 + sid = s.attributes.get("id") or ""
112 + raw = s.text() or ""
113 + if not raw.strip():
114 + continue
115 + if "ld+json" in stype:
116 + parsed = _loads_lenient(raw)
117 + if parsed is not None:
118 + if isinstance(parsed, list):
119 + doc.json_ld.extend(parsed)
120 + else:
121 + doc.json_ld.append(parsed)
122 + elif stype in ("application/json", "text/json") or sid in ("__NEXT_DATA__", "__NUXT_DATA__", "__remixContext"):
123 + parsed = _loads_lenient(raw)
124 + if parsed is not None:
125 + doc.embedded_json[sid or f"json_{len(doc.embedded_json)}"] = parsed
126 + # Hugging Face / Svelte style `data-props` attributes and generic data-* JSON blobs
127 + for n in tree.css("[data-props]"):
128 + raw = n.attributes.get("data-props") or ""
129 + parsed = _loads_lenient(raw)
130 + if parsed is not None:
131 + key = f"data-props:{n.attributes.get('data-target') or len(doc.embedded_json)}"
132 + doc.embedded_json.setdefault(key, parsed)
133 +
134 + for level in range(1, 5):
135 + for h in tree.css(f"h{level}"):
136 + txt = node_text(h)
137 + if txt:
138 + doc.headings.append((level, txt[:300]))
139 +
140 + for table in tree.css("table")[:60]:
141 + parsed_table = _parse_table(table)
142 + if parsed_table["rows"]:
143 + doc.tables.append(parsed_table)
144 +
145 + seen: set[str] = set()
146 + for a in tree.css("a[href]"):
147 + href = a.attributes.get("href") or ""
148 + if not href or href.startswith(("#", "javascript:", "mailto:", "tel:")):
149 + continue
150 + absolute = urljoin(url, href.strip())
151 + if absolute in seen:
152 + continue
153 + seen.add(absolute)
154 + doc.links.append((absolute, node_text(a)[:200]))
155 + if len(doc.links) >= max_links:
156 + break
157 +
158 + doc.text = extract_text(tree)
159 + return doc
160 +
161 +
162 +def extract_text(tree: HTMLParser) -> str:
163 + body = tree.body or tree.root
164 + if body is None:
165 + return ""
166 + for tag in _SKIP_TAGS:
167 + for n in body.css(tag):
168 + n.decompose()
169 + for n in body.css("[aria-hidden='true'], .sr-only, [hidden]"):
170 + n.decompose()
171 + parts: list[str] = []
172 + block_tags = {"p", "div", "section", "article", "li", "h1", "h2", "h3", "h4", "h5", "h6", "tr", "br", "pre", "blockquote", "td", "th", "dd", "dt"}
173 + for node in body.traverse(include_text=True):
174 + if node.tag == "-text":
175 + t = node.text(deep=False)
176 + if t and t.strip():
177 + parts.append(t)
178 + elif node.tag in block_tags:
179 + parts.append("\n")
180 + return clean_text("".join(parts))
181 +
182 +
183 +def _parse_table(table: Node) -> dict[str, Any]:
184 + headers: list[str] = []
185 + rows: list[list[str]] = []
186 + caption_node = table.css_first("caption")
187 + caption = node_text(caption_node) if caption_node else None
188 + for tr in table.css("tr"):
189 + cells = tr.css("th, td")
190 + if not cells:
191 + continue
192 + values = [node_text(c)[:500] for c in cells]
193 + if not headers and all(c.tag == "th" for c in cells):
194 + headers = values
195 + else:
196 + rows.append(values)
197 + if len(rows) > 500:
198 + break
199 + return {"caption": caption, "headers": headers, "rows": rows}
200 +
201 +
202 +def _loads_lenient(raw: str) -> Any | None:
203 + raw = raw.strip()
204 + if not raw:
205 + return None
206 + try:
207 + return json.loads(raw)
208 + except json.JSONDecodeError:
209 + pass
210 + try:
211 + return json.loads(htmlmod.unescape(raw))
212 + except json.JSONDecodeError:
213 + return None
214 +
215 +
216 +def find_in_json(obj: Any, key: str, *, max_hits: int = 50) -> list[Any]:
217 + """Depth-first search of every value under `key` inside a nested JSON structure."""
218 + hits: list[Any] = []
219 +
220 + def walk(o: Any) -> None:
221 + if len(hits) >= max_hits:
222 + return
223 + if isinstance(o, dict):
224 + for k, v in o.items():
225 + if k == key:
226 + hits.append(v)
227 + walk(v)
228 + elif isinstance(o, list):
229 + for v in o:
230 + walk(v)
231 +
232 + walk(obj)
233 + return hits
234 +
235 +
236 +__all__ = ["HtmlDoc", "parse_html", "clean_text", "node_text", "extract_text", "find_in_json"]
added src/aiatlas/sdk/extract/markdown.py +103 −0
@@ -0,0 +1,103 @@
1 +"""Markdown documents (model cards, docs served as .md, READMEs): YAML front matter, headings, tables, links, plain text."""
2 +from __future__ import annotations
3 +
4 +import re
5 +from dataclasses import dataclass, field
6 +from typing import Any
7 +
8 +import yaml
9 +
10 +_FM = re.compile(r"\A---[ \t]*\r?\n(.*?)\r?\n---[ \t]*\r?\n", re.S)
11 +_HEADING = re.compile(r"^(#{1,6})\s+(.*?)\s*#*\s*$", re.M)
12 +_LINK = re.compile(r"\[([^\]]*)\]\((https?://[^)\s]+)\)")
13 +_TABLE_ROW = re.compile(r"^\s*\|(.+)\|\s*$")
14 +_SEP_ROW = re.compile(r"^\s*\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)*\|?\s*$")
15 +
16 +
17 +@dataclass
18 +class MarkdownDoc:
19 + front_matter: dict[str, Any] = field(default_factory=dict)
20 + body: str = ""
21 + headings: list[tuple[int, str]] = field(default_factory=list)
22 + tables: list[dict[str, Any]] = field(default_factory=list)
23 + links: list[tuple[str, str]] = field(default_factory=list)
24 + text: str = ""
25 +
26 + def section(self, title_pattern: str) -> str:
27 + """Body text of the first heading matching `title_pattern` (case-insensitive) up to the next heading of same/higher level."""
28 + rx = re.compile(title_pattern, re.I)
29 + lines = self.body.split("\n")
30 + start = None
31 + level = 0
32 + for i, line in enumerate(lines):
33 + m = _HEADING.match(line)
34 + if m and start is None and rx.search(m.group(2)):
35 + start = i + 1
36 + level = len(m.group(1))
37 + continue
38 + if start is not None and m and len(m.group(1)) <= level:
39 + return "\n".join(lines[start:i]).strip()
40 + return "\n".join(lines[start:]).strip() if start is not None else ""
41 +
42 +
43 +def parse_front_matter(text: str) -> tuple[dict[str, Any], str]:
44 + m = _FM.match(text)
45 + if not m:
46 + return {}, text
47 + try:
48 + data = yaml.safe_load(m.group(1)) or {}
49 + if not isinstance(data, dict):
50 + data = {"_value": data}
51 + except yaml.YAMLError:
52 + data = {}
53 + return data, text[m.end():]
54 +
55 +
56 +def parse_markdown(text: str) -> MarkdownDoc:
57 + fm, body = parse_front_matter(text)
58 + doc = MarkdownDoc(front_matter=fm, body=body)
59 + doc.headings = [(len(m.group(1)), m.group(2).strip()) for m in _HEADING.finditer(body)]
60 + doc.links = [(m.group(2), m.group(1)) for m in _LINK.finditer(body)]
61 + doc.tables = _tables(body)
62 + doc.text = _to_text(body)
63 + return doc
64 +
65 +
66 +def _tables(body: str) -> list[dict[str, Any]]:
67 + out: list[dict[str, Any]] = []
68 + lines = body.split("\n")
69 + i = 0
70 + while i < len(lines):
71 + if _TABLE_ROW.match(lines[i]) and i + 1 < len(lines) and _SEP_ROW.match(lines[i + 1]):
72 + headers = _cells(lines[i])
73 + rows: list[list[str]] = []
74 + i += 2
75 + while i < len(lines) and _TABLE_ROW.match(lines[i]):
76 + rows.append(_cells(lines[i]))
77 + i += 1
78 + out.append({"caption": None, "headers": headers, "rows": rows})
79 + else:
80 + i += 1
81 + return out
82 +
83 +
84 +def _cells(line: str) -> list[str]:
85 + inner = line.strip()
86 + if inner.startswith("|"):
87 + inner = inner[1:]
88 + if inner.endswith("|"):
89 + inner = inner[:-1]
90 + return [re.sub(r"\*\*|`", "", c).strip() for c in inner.split("|")]
91 +
92 +
93 +def _to_text(body: str) -> str:
94 + s = re.sub(r"```.*?```", " ", body, flags=re.S)
95 + s = re.sub(r"!\[[^\]]*\]\([^)]*\)", " ", s)
96 + s = re.sub(r"\[([^\]]*)\]\([^)]*\)", r"\1", s)
97 + s = re.sub(r"<[^>]+>", " ", s)
98 + s = re.sub(r"^[#>*\-|\s]+", "", s, flags=re.M)
99 + s = re.sub(r"[ \t]+", " ", s)
100 + return re.sub(r"\n{3,}", "\n\n", s).strip()
101 +
102 +
103 +__all__ = ["MarkdownDoc", "parse_front_matter", "parse_markdown"]
added src/aiatlas/sdk/extract/numbers.py +106 −0
@@ -0,0 +1,106 @@
1 +"""Numbers as they appear in AI documentation: `70B`, `1.5T`, `128K context`, `$3.00 / 1M tokens`, `72.4%`."""
2 +from __future__ import annotations
3 +
4 +import re
5 +
6 +_MULT = {"k": 1e3, "m": 1e6, "b": 1e9, "t": 1e12, "g": 1e9}
7 +
8 +_PARAMS = re.compile(r"(?<![\w.])(\d+(?:[.,]\d+)?)\s*([kKmMbBtT])\b(?:\s*(?:params?|parameters?))?", re.I)
9 +_PARAMS_WORD = re.compile(r"(\d+(?:[.,]\d+)?)\s*(billion|million|trillion)\s*(?:params?|parameters?)", re.I)
10 +_CONTEXT = re.compile(r"(\d+(?:[.,]\d+)?)\s*([kKmM])?\s*(?:tokens?|token|ctx|context)?", re.I)
11 +_MONEY = re.compile(r"(?:US)?\$\s*(\d+(?:[.,]\d+)?)\s*(?:/|per)\s*(?:1\s*)?([mMkK])\s*(?:tok(?:ens?)?)?", re.I)
12 +_MONEY_SIMPLE = re.compile(r"(?:US)?\$\s*(\d+(?:\.\d+)?)")
13 +_PCT = re.compile(r"(-?\d+(?:\.\d+)?)\s*%")
14 +
15 +
16 +def _num(s: str) -> float:
17 + return float(s.replace(",", "."))
18 +
19 +
20 +def parse_param_count(text: str) -> int | None:
21 + """'Qwen3-235B-A22B' → 235e9 ; '7.6 billion parameters' → 7.6e9. Returns total parameters (not active)."""
22 + m = _PARAMS_WORD.search(text)
23 + if m:
24 + return int(_num(m.group(1)) * {"million": 1e6, "billion": 1e9, "trillion": 1e12}[m.group(2).lower()])
25 + best: int | None = None
26 + for m in _PARAMS.finditer(text):
27 + val = _num(m.group(1)) * _MULT[m.group(2).lower()]
28 + if 1e6 <= val <= 5e13 and (best is None or val > best):
29 + best = int(val)
30 + return best
31 +
32 +
33 +def parse_active_params(text: str) -> int | None:
34 + """'235B-A22B' / '30B-A3B' → active parameters of an MoE model."""
35 + m = re.search(r"-A(\d+(?:\.\d+)?)([bBmM])\b", text)
36 + if not m:
37 + m = re.search(r"(\d+(?:\.\d+)?)\s*([bB])\s*active", text, re.I)
38 + if not m:
39 + return None
40 + return int(_num(m.group(1)) * _MULT[m.group(2).lower()])
41 +
42 +
43 +def parse_context_length(text: str) -> int | None:
44 + """'128K' → 128000 ; '1M' → 1000000 ; '200,000 tokens' → 200000 ; '32768' → 32768."""
45 + t = text.strip().replace("tokens", "").replace("token", "")
46 + m = re.search(r"(\d{1,3}(?:,\d{3})+|\d+(?:\.\d+)?)\s*([kKmM])?\b", t)
47 + if not m:
48 + return None
49 + raw = m.group(1)
50 + if "," in raw and not m.group(2):
51 + val = float(raw.replace(",", ""))
52 + else:
53 + val = float(raw.replace(",", "."))
54 + if m.group(2):
55 + unit = m.group(2).lower()
56 + val *= 1024 if (unit == "k" and val in (8, 16, 32, 64, 128, 256, 512)) and "1024" in text else _MULT[unit]
57 + if val < 256 or val > 1e8:
58 + return None
59 + return int(val)
60 +
61 +
62 +def parse_tokens(text: str) -> int | None:
63 + return parse_context_length(text)
64 +
65 +
66 +def parse_money_per_mtok(text: str) -> float | None:
67 + """'$3.00 / 1M tokens' → 3.0 ; '$0.15/M' → 0.15 ; '$2 per 1K tokens' → 2000.0 (normalised to per million)."""
68 + m = _MONEY.search(text)
69 + if m:
70 + val = _num(m.group(1))
71 + unit = m.group(2).lower()
72 + return val * 1000 if unit == "k" else val
73 + m = _MONEY_SIMPLE.search(text)
74 + if m and "token" in text.lower():
75 + return float(m.group(1))
76 + return None
77 +
78 +
79 +def parse_money(text: str) -> float | None:
80 + m = _MONEY_SIMPLE.search(text.replace(",", ""))
81 + return float(m.group(1)) if m else None
82 +
83 +
84 +def parse_percent(text: str) -> float | None:
85 + m = _PCT.search(text)
86 + if m:
87 + return float(m.group(1))
88 + m = re.search(r"(?<![\d.])(\d{1,3}(?:\.\d+)?)(?![\d.%])", text)
89 + if m:
90 + v = float(m.group(1))
91 + return v if 0 <= v <= 100 else None
92 + return None
93 +
94 +
95 +def parse_int(text: str) -> int | None:
96 + m = re.search(r"-?\d[\d,]*", text)
97 + if not m:
98 + return None
99 + try:
100 + return int(m.group(0).replace(",", ""))
101 + except ValueError:
102 + return None
103 +
104 +
105 +__all__ = ["parse_param_count", "parse_active_params", "parse_context_length", "parse_tokens", "parse_money_per_mtok", "parse_money",
106 + "parse_percent", "parse_int"]
added src/aiatlas/sdk/extract/sitemap.py +42 −0
@@ -0,0 +1,42 @@
1 +"""XML sitemaps and sitemap indexes."""
2 +from __future__ import annotations
3 +
4 +import re
5 +from dataclasses import dataclass
6 +from xml.etree import ElementTree as ET
7 +
8 +_NS = re.compile(r"\{[^}]+\}")
9 +
10 +
11 +@dataclass
12 +class SitemapEntry:
13 + loc: str
14 + lastmod: str | None = None
15 + is_index: bool = False
16 +
17 +
18 +def parse_sitemap(content: bytes | str) -> list[SitemapEntry]:
19 + if isinstance(content, str):
20 + content = content.encode()
21 + try:
22 + root = ET.fromstring(content)
23 + except ET.ParseError:
24 + return []
25 + tag = _NS.sub("", root.tag).lower()
26 + is_index = tag == "sitemapindex"
27 + out: list[SitemapEntry] = []
28 + for node in root:
29 + loc = None
30 + lastmod = None
31 + for child in node:
32 + name = _NS.sub("", child.tag).lower()
33 + if name == "loc" and child.text:
34 + loc = child.text.strip()
35 + elif name == "lastmod" and child.text:
36 + lastmod = child.text.strip()
37 + if loc:
38 + out.append(SitemapEntry(loc=loc, lastmod=lastmod, is_index=is_index))
39 + return out
40 +
41 +
42 +__all__ = ["SitemapEntry", "parse_sitemap"]
added src/aiatlas/sdk/facts.py +222 −0
@@ -0,0 +1,222 @@
1 +"""What a connector produces: entity references, temporal claims, relations, events, prices, benchmark results.
2 +Connectors never touch the database — they return `Facts`; the writer resolves, versions and records them."""
3 +from __future__ import annotations
4 +
5 +from dataclasses import dataclass, field
6 +from datetime import datetime
7 +from typing import Any
8 +
9 +CONFIDENCE = ("verified", "high", "medium", "low", "conflicted")
10 +
11 +
12 +@dataclass
13 +class EntityRef:
14 + entity_type: str
15 + name: str
16 + identifiers: dict[str, str] = field(default_factory=dict) # scheme -> value (hf_repo, github_repo, arxiv, doi, domain, pypi, provider_model_id…)
17 + aliases: list[str] = field(default_factory=list)
18 + slug_hint: str | None = None
19 + organization: EntityRef | None = None # developer / publisher / owner
20 + description: str | None = None
21 + status: str | None = None
22 + attributes: dict[str, Any] = field(default_factory=dict) # convenience: each item becomes a Claim
23 + first_seen_hint: datetime | None = None # e.g. release date, to backdate `first_seen_at` for historical backfill
24 + id: str | None = field(default=None, compare=False)
25 +
26 + def key(self) -> str:
27 + if self.identifiers:
28 + scheme, value = sorted(self.identifiers.items())[0]
29 + return f"{self.entity_type}:{scheme}={value}"
30 + return f"{self.entity_type}:name={self.name.strip().lower()}"
31 +
32 +
33 +@dataclass
34 +class Claim:
35 + entity: EntityRef
36 + property: str
37 + value: Any
38 + unit: str | None = None
39 + confidence: str | None = None # default from source tier
40 + observed_at: datetime | None = None
41 + effective_at: datetime | None = None
42 + source_url: str | None = None
43 +
44 +
45 +@dataclass
46 +class Relation:
47 + subject: EntityRef
48 + predicate: str
49 + object: EntityRef
50 + attributes: dict[str, Any] = field(default_factory=dict)
51 + confidence: str | None = None
52 + source_url: str | None = None
53 +
54 +
55 +@dataclass
56 +class Event:
57 + event_type: str
58 + category: str
59 + summary: str
60 + entity: EntityRef | None = None
61 + old_value: Any = None
62 + new_value: Any = None
63 + importance: int = 2
64 + effective_at: datetime | None = None
65 + dedupe_key: str | None = None
66 + source_url: str | None = None
67 + meta: dict[str, Any] = field(default_factory=dict)
68 +
69 +
70 +@dataclass
71 +class PriceObs:
72 + model: EntityRef
73 + provider: EntityRef
74 + provider_model_id: str | None = None
75 + input_per_mtok: float | None = None
76 + output_per_mtok: float | None = None
77 + cached_input_per_mtok: float | None = None
78 + cache_write_per_mtok: float | None = None
79 + batch_input_per_mtok: float | None = None
80 + batch_output_per_mtok: float | None = None
81 + per_image: float | None = None
82 + per_request: float | None = None
83 + currency: str = "USD"
84 + context_length: int | None = None
85 + max_output_tokens: int | None = None
86 + features: dict[str, Any] = field(default_factory=dict)
87 + source_url: str | None = None
88 + meta: dict[str, Any] = field(default_factory=dict)
89 +
90 + def price_tuple(self) -> tuple[Any, ...]:
91 + return (self.input_per_mtok, self.output_per_mtok, self.cached_input_per_mtok, self.cache_write_per_mtok,
92 + self.batch_input_per_mtok, self.batch_output_per_mtok, self.per_image, self.per_request, self.currency)
93 +
94 +
95 +@dataclass
96 +class ResultObs:
97 + model: EntityRef
98 + benchmark: EntityRef
99 + score: float
100 + metric: str | None = None
101 + unit: str | None = "%"
102 + higher_is_better: bool = True
103 + config: dict[str, Any] = field(default_factory=dict)
104 + evaluated_at: datetime | None = None
105 + source_url: str | None = None
106 + confidence: str | None = None
107 +
108 +
109 +@dataclass
110 +class Target:
111 + """Something to fetch. Connectors return targets from `discover()` and may add more from `extract()`."""
112 + url: str
113 + doc_type: str = "page"
114 + entity: EntityRef | None = None
115 + meta: dict[str, Any] = field(default_factory=dict)
116 + accept: str | None = None
117 + min_bytes: int = 64
118 + escalate: bool = False
119 + needs_llm: bool = False
120 + priority: int = 2
121 + key: str | None = None # short handle for --file overrides / fixtures
122 + rate_per_min: int | None = None
123 +
124 +
125 +@dataclass
126 +class Facts:
127 + entities: list[EntityRef] = field(default_factory=list)
128 + claims: list[Claim] = field(default_factory=list)
129 + relations: list[Relation] = field(default_factory=list)
130 + events: list[Event] = field(default_factory=list)
131 + prices: list[PriceObs] = field(default_factory=list)
132 + results: list[ResultObs] = field(default_factory=list)
133 + targets: list[Target] = field(default_factory=list) # follow-up fetches discovered while extracting
134 + document_title: str | None = None
135 + document_entity: EntityRef | None = None # main entity described by the document
136 + llm_hint: str | None = None # ask the LLM factory for a specific extraction task
137 +
138 + # ---------------------------------------------------------------------------------------------- builders
139 + def entity(self, entity_type: str, name: str, **kw: Any) -> EntityRef:
140 + ref = EntityRef(entity_type=entity_type, name=name.strip(), **kw)
141 + self.entities.append(ref)
142 + return ref
143 +
144 + def claim(self, entity: EntityRef, property: str, value: Any, **kw: Any) -> Claim | None:
145 + if value is None or value == "" or value == [] or value == {}:
146 + return None
147 + c = Claim(entity=entity, property=property, value=value, **kw)
148 + self.claims.append(c)
149 + return c
150 +
151 + def relate(self, subject: EntityRef, predicate: str, obj: EntityRef, **kw: Any) -> Relation:
152 + r = Relation(subject=subject, predicate=predicate, object=obj, **kw)
153 + self.relations.append(r)
154 + return r
155 +
156 + def event(self, event_type: str, category: str, summary: str, **kw: Any) -> Event:
157 + e = Event(event_type=event_type, category=category, summary=summary[:500], **kw)
158 + self.events.append(e)
159 + return e
160 +
161 + def price(self, **kw: Any) -> PriceObs:
162 + p = PriceObs(**kw)
163 + self.prices.append(p)
164 + return p
165 +
166 + def result(self, **kw: Any) -> ResultObs:
167 + r = ResultObs(**kw)
168 + self.results.append(r)
169 + return r
170 +
171 + def follow(self, url: str, **kw: Any) -> Target:
172 + t = Target(url=url, **kw)
173 + self.targets.append(t)
174 + return t
175 +
176 + def extend(self, other: Facts) -> None:
177 + self.entities += other.entities
178 + self.claims += other.claims
179 + self.relations += other.relations
180 + self.events += other.events
181 + self.prices += other.prices
182 + self.results += other.results
183 + self.targets += other.targets
184 +
185 + def is_empty(self) -> bool:
186 + return not (self.entities or self.claims or self.relations or self.events or self.prices or self.results)
187 +
188 +
189 +# Property → change-event mapping (material properties emit events; noisy metrics never do).
190 +MATERIAL_PROPERTIES: dict[str, tuple[str, int]] = {
191 + "context_length": ("CONTEXT_CHANGED", 2),
192 + "max_output_tokens": ("MAX_OUTPUT_CHANGED", 1),
193 + "status": ("STATUS_CHANGED", 2),
194 + "license": ("LICENSE_CHANGED", 2),
195 + "parameter_count": ("PARAMETERS_CHANGED", 1),
196 + "active_parameter_count": ("PARAMETERS_CHANGED", 1),
197 + "weights_availability": ("OPENNESS_CHANGED", 3),
198 + "openness": ("OPENNESS_CHANGED", 3),
199 + "release_date": ("RELEASE_DATE_CHANGED", 1),
200 + "knowledge_cutoff": ("KNOWLEDGE_CUTOFF_CHANGED", 1),
201 + "latest_version": ("VERSION_RELEASED", 2),
202 + "deprecation_date": ("DEPRECATION_ANNOUNCED", 3),
203 + "retirement_date": ("RETIREMENT_ANNOUNCED", 3),
204 + "modalities": ("CAPABILITIES_CHANGED", 2),
205 + "capabilities": ("CAPABILITIES_CHANGED", 1),
206 + "rate_limit": ("RATE_LIMIT_CHANGED", 1),
207 + "memory_gb": ("SPEC_CHANGED", 1),
208 + "price_usd": ("PRICE_CHANGED", 2),
209 +}
210 +
211 +NOISY_PREFIXES = ("metric.", "stats.", "counts.")
212 +
213 +EVENT_CATEGORY_BY_TYPE: dict[str, str] = {
214 + "model": "model", "company": "company", "organization": "company", "lab": "company", "university": "company",
215 + "paper": "paper", "dataset": "dataset", "benchmark": "benchmark", "provider": "provider", "framework": "framework",
216 + "library": "framework", "repository": "repository", "tool": "tool", "agent": "tool", "hardware": "hardware",
217 + "runtime": "framework", "quantization": "model", "regulation": "regulation", "incident": "incident", "release": "release",
218 + "mcp_server": "tool", "researcher": "company", "license": "model", "product": "tool", "robot": "hardware",
219 +}
220 +
221 +__all__ = ["EntityRef", "Claim", "Relation", "Event", "PriceObs", "ResultObs", "Target", "Facts", "MATERIAL_PROPERTIES",
222 + "NOISY_PREFIXES", "EVENT_CATEGORY_BY_TYPE", "CONFIDENCE"]
added src/aiatlas/sdk/fetch.py +329 −0
@@ -0,0 +1,329 @@
1 +"""Fetch transport: DIRECT MODE first (httpx, conditional requests, per-domain rate limits, robots.txt, backoff), optional
2 +ESCALATED MODE (headless browser → Scrapfly → Firecrawl) that is never required and never automatic unless the connector asks.
3 +
4 + direct → retry → [browser] → [scrapfly] → [firecrawl] → BlockedError (→ review queue by the caller)
5 +"""
6 +from __future__ import annotations
7 +
8 +import asyncio
9 +import hashlib
10 +import logging
11 +import time
12 +from dataclasses import dataclass, field
13 +from datetime import UTC, datetime
14 +from urllib.parse import urlparse, urlunparse
15 +from urllib.robotparser import RobotFileParser
16 +
17 +import httpx
18 +
19 +from aiatlas.config import settings
20 +
21 +log = logging.getLogger(__name__)
22 +
23 +TRANSIENT_STATUS = {408, 425, 429, 500, 502, 503, 504}
24 +BLOCK_STATUS = {401, 403, 451, 999}
25 +
26 +
27 +class FetchError(Exception):
28 + def __init__(self, message: str, *, status: int | None = None, url: str = ""):
29 + super().__init__(message)
30 + self.status = status
31 + self.url = url
32 +
33 +
34 +class BlockedError(FetchError):
35 + """Access denied by the origin after every allowed transport (never bypass: park in the review queue)."""
36 +
37 +
38 +class NotModified(Exception):
39 + """HTTP 304 — content unchanged since our stored validators."""
40 +
41 +
42 +@dataclass
43 +class FetchResult:
44 + url: str
45 + final_url: str
46 + status: int
47 + headers: dict[str, str]
48 + content: bytes
49 + content_type: str
50 + fetched_at: datetime
51 + duration_ms: int
52 + transport: str = "direct"
53 + from_cache: bool = False
54 + sha256: str = field(init=False)
55 +
56 + def __post_init__(self) -> None:
57 + self.sha256 = hashlib.sha256(self.content).hexdigest()
58 +
59 + @property
60 + def text(self) -> str:
61 + enc = "utf-8"
62 + ct = self.content_type.lower()
63 + if "charset=" in ct:
64 + enc = ct.split("charset=", 1)[1].split(";")[0].strip().strip('"') or "utf-8"
65 + try:
66 + return self.content.decode(enc, errors="replace")
67 + except LookupError:
68 + return self.content.decode("utf-8", errors="replace")
69 +
70 + @property
71 + def is_html(self) -> bool:
72 + return "html" in self.content_type or self.content[:256].lstrip().lower().startswith((b"<!doctype html", b"<html"))
73 +
74 + @property
75 + def is_json(self) -> bool:
76 + return "json" in self.content_type or self.content[:1] in (b"{", b"[")
77 +
78 + @property
79 + def is_xml(self) -> bool:
80 + return "xml" in self.content_type or self.content[:5] == b"<?xml"
81 +
82 + @property
83 + def is_pdf(self) -> bool:
84 + return "pdf" in self.content_type or self.content[:4] == b"%PDF"
85 +
86 + def json(self): # type: ignore[no-untyped-def]
87 + import orjson
88 +
89 + return orjson.loads(self.content)
90 +
91 +
92 +def canonicalize_url(url: str) -> str:
93 + """Stable URL key: lowercase scheme/host, no fragment, no tracking params, no trailing slash duplication."""
94 + p = urlparse(url.strip())
95 + query = "&".join(sorted(q for q in p.query.split("&") if q and not q.lower().startswith(
96 + ("utm_", "ref=", "ref_", "fbclid", "gclid", "mc_cid", "mc_eid", "_hs", "igshid", "source="))))
97 + path = p.path or "/"
98 + if len(path) > 1 and path.endswith("/") and not path.endswith("//"):
99 + path = path.rstrip("/") or "/"
100 + return urlunparse((p.scheme.lower() or "https", p.netloc.lower(), path, "", query, ""))
101 +
102 +
103 +def domain_of(url: str) -> str:
104 + host = urlparse(url).netloc.lower()
105 + return host[4:] if host.startswith("www.") else host
106 +
107 +
108 +class _RateLimiter:
109 + """Per-domain minimum spacing between requests (token bucket, in-process). Cluster-wide fairness comes from Redis locks
110 + at the connector level (one connector run at a time)."""
111 +
112 + def __init__(self) -> None:
113 + self._next: dict[str, float] = {}
114 + self._locks: dict[str, asyncio.Lock] = {}
115 +
116 + async def wait(self, domain: str, per_min: int) -> None:
117 + lock = self._locks.setdefault(domain, asyncio.Lock())
118 + async with lock:
119 + spacing = 60.0 / max(1, per_min)
120 + now = time.monotonic()
121 + ready = self._next.get(domain, 0.0)
122 + if ready > now:
123 + await asyncio.sleep(ready - now)
124 + now = time.monotonic()
125 + self._next[domain] = now + spacing
126 +
127 +
128 +class _Robots:
129 + def __init__(self) -> None:
130 + self._cache: dict[str, tuple[float, RobotFileParser | None]] = {}
131 +
132 + async def allowed(self, client: httpx.AsyncClient, url: str) -> bool:
133 + if not settings.respect_robots:
134 + return True
135 + p = urlparse(url)
136 + key = f"{p.scheme}://{p.netloc}"
137 + cached = self._cache.get(key)
138 + if cached is None or cached[0] < time.monotonic():
139 + rp: RobotFileParser | None = RobotFileParser()
140 + try:
141 + r = await client.get(f"{key}/robots.txt", timeout=15, follow_redirects=True)
142 + if r.status_code == 200 and len(r.content) < 512 * 1024:
143 + rp.parse(r.text.splitlines()) # type: ignore[union-attr]
144 + else:
145 + rp = None # no robots or error → allowed
146 + except Exception: # noqa: BLE001
147 + rp = None
148 + self._cache[key] = (time.monotonic() + 6 * 3600, rp)
149 + cached = self._cache[key]
150 + rp = cached[1]
151 + if rp is None:
152 + return True
153 + try:
154 + return rp.can_fetch(settings.user_agent.split("/")[0], url) or rp.can_fetch("*", url)
155 + except Exception: # noqa: BLE001
156 + return True
157 +
158 +
159 +class Fetcher:
160 + """One Fetcher per connector run. Direct mode by default; `escalate=True` enables the optional chain."""
161 +
162 + def __init__(self, *, rate_per_min: int | None = None, robots: bool = True, timeout_s: float | None = None,
163 + headers: dict[str, str] | None = None, http2: bool = True):
164 + self.rate_per_min = rate_per_min or settings.default_rate_per_min
165 + self.robots = robots
166 + self.timeout_s = timeout_s or settings.http_timeout_s
167 + self.headers = {"User-Agent": settings.user_agent, "Accept": "text/html,application/xhtml+xml,application/xml,application/json,text/*;q=0.9,*/*;q=0.8",
168 + "Accept-Language": "en-US,en;q=0.8", **(headers or {})}
169 + self._client: httpx.AsyncClient | None = None
170 + self._http2 = http2
171 +
172 + async def __aenter__(self) -> Fetcher:
173 + self._client = httpx.AsyncClient(headers=self.headers, timeout=httpx.Timeout(self.timeout_s, connect=20), follow_redirects=True,
174 + http2=self._http2, limits=httpx.Limits(max_connections=16, max_keepalive_connections=8))
175 + return self
176 +
177 + async def __aexit__(self, *exc: object) -> None:
178 + if self._client:
179 + await self._client.aclose()
180 + self._client = None
181 +
182 + @property
183 + def client(self) -> httpx.AsyncClient:
184 + if self._client is None:
185 + raise RuntimeError("use `async with Fetcher() as f`")
186 + return self._client
187 +
188 + async def get(self, url: str, *, etag: str | None = None, last_modified: str | None = None, min_bytes: int = 1,
189 + escalate: bool = False, retries: int = 2, accept: str | None = None, rate_per_min: int | None = None) -> FetchResult:
190 + """Direct fetch with conditional headers. Raises NotModified (304), FetchError, BlockedError."""
191 + client = self.client
192 + domain = domain_of(url)
193 + if self.robots and not await _robots.allowed(client, url):
194 + raise BlockedError(f"robots.txt disallows {url}", status=None, url=url)
195 + headers: dict[str, str] = {}
196 + if etag:
197 + headers["If-None-Match"] = etag
198 + if last_modified:
199 + headers["If-Modified-Since"] = last_modified
200 + if accept:
201 + headers["Accept"] = accept
202 + last_exc: Exception | None = None
203 + for attempt in range(retries + 1):
204 + await _limiter.wait(domain, rate_per_min or self.rate_per_min)
205 + t0 = time.perf_counter()
206 + try:
207 + async with client.stream("GET", url, headers=headers) as r:
208 + if r.status_code == 304:
209 + raise NotModified()
210 + if r.status_code in TRANSIENT_STATUS and attempt < retries:
211 + retry_after = r.headers.get("retry-after")
212 + delay = min(60.0, float(retry_after)) if retry_after and retry_after.isdigit() else 2.0 * (2 ** attempt)
213 + log.info("transient status, backing off", extra={"url": url, "status": r.status_code, "delay": delay})
214 + await asyncio.sleep(delay)
215 + continue
216 + if r.status_code in BLOCK_STATUS:
217 + if escalate:
218 + return await self._escalate(url, reason=f"http {r.status_code}")
219 + raise BlockedError(f"http {r.status_code} for {url}", status=r.status_code, url=url)
220 + if r.status_code >= 400:
221 + raise FetchError(f"http {r.status_code} for {url}", status=r.status_code, url=url)
222 + chunks: list[bytes] = []
223 + size = 0
224 + async for chunk in r.aiter_bytes():
225 + size += len(chunk)
226 + if size > settings.max_body_bytes:
227 + raise FetchError(f"body exceeds {settings.max_body_bytes} bytes", status=r.status_code, url=url)
228 + chunks.append(chunk)
229 + content = b"".join(chunks)
230 + if len(content) < min_bytes:
231 + raise FetchError(f"suspiciously short body ({len(content)} bytes) for {url}", status=r.status_code, url=url)
232 + res = FetchResult(url=url, final_url=str(r.url), status=r.status_code, headers={k.lower(): v for k, v in r.headers.items()},
233 + content=content, content_type=r.headers.get("content-type", "").lower(), fetched_at=datetime.now(UTC),
234 + duration_ms=int((time.perf_counter() - t0) * 1000), transport="direct")
235 + if escalate and res.is_html and _looks_like_challenge(content):
236 + return await self._escalate(url, reason="anti-bot challenge page")
237 + return res
238 + except NotModified:
239 + raise
240 + except (BlockedError, FetchError):
241 + raise
242 + except (httpx.TimeoutException, httpx.TransportError) as exc:
243 + last_exc = exc
244 + if attempt < retries:
245 + await asyncio.sleep(1.5 * (2 ** attempt))
246 + continue
247 + raise FetchError(f"{exc.__class__.__name__}: {exc}", url=url) from exc
248 + raise FetchError(f"fetch failed: {last_exc}", url=url)
249 +
250 + # ---------------------------------------------------------------------------------------------- escalation (optional)
251 + async def _escalate(self, url: str, *, reason: str) -> FetchResult:
252 + log.warning("escalating fetch", extra={"url": url, "reason": reason})
253 + if settings.browser_enabled:
254 + try:
255 + return await self._browser(url)
256 + except Exception as exc: # noqa: BLE001
257 + log.info("browser transport failed", extra={"url": url, "error": str(exc)})
258 + if settings.scrapfly_api_key:
259 + try:
260 + return await self._scrapfly(url)
261 + except Exception as exc: # noqa: BLE001
262 + log.info("scrapfly transport failed", extra={"url": url, "error": str(exc)})
263 + if settings.firecrawl_api_key:
264 + try:
265 + return await self._firecrawl(url)
266 + except Exception as exc: # noqa: BLE001
267 + log.info("firecrawl transport failed", extra={"url": url, "error": str(exc)})
268 + raise BlockedError(f"blocked after escalation ({reason}): {url}", url=url)
269 +
270 + async def _browser(self, url: str) -> FetchResult:
271 + from playwright.async_api import async_playwright # optional dependency
272 +
273 + t0 = time.perf_counter()
274 + async with async_playwright() as p:
275 + browser = await p.chromium.launch(headless=True)
276 + try:
277 + page = await browser.new_page(user_agent=settings.user_agent)
278 + resp = await page.goto(url, wait_until="networkidle", timeout=int(self.timeout_s * 1000))
279 + html = await page.content()
280 + status = resp.status if resp else 200
281 + finally:
282 + await browser.close()
283 + return FetchResult(url=url, final_url=url, status=status, headers={}, content=html.encode(), content_type="text/html; charset=utf-8",
284 + fetched_at=datetime.now(UTC), duration_ms=int((time.perf_counter() - t0) * 1000), transport="browser")
285 +
286 + async def _scrapfly(self, url: str) -> FetchResult:
287 + t0 = time.perf_counter()
288 + r = await self.client.get("https://api.scrapfly.io/scrape", params={"key": settings.scrapfly_api_key, "url": url, "asp": "true",
289 + "render_js": "true", "country": "us"}, timeout=120)
290 + r.raise_for_status()
291 + data = r.json()["result"]
292 + content = (data.get("content") or "").encode()
293 + return FetchResult(url=url, final_url=data.get("url") or url, status=int(data.get("status_code") or 200), headers={},
294 + content=content, content_type=(data.get("content_type") or "text/html").lower(), fetched_at=datetime.now(UTC),
295 + duration_ms=int((time.perf_counter() - t0) * 1000), transport="scrapfly")
296 +
297 + async def _firecrawl(self, url: str) -> FetchResult:
298 + t0 = time.perf_counter()
299 + r = await self.client.post("https://api.firecrawl.dev/v1/scrape", json={"url": url, "formats": ["rawHtml"]},
300 + headers={"Authorization": f"Bearer {settings.firecrawl_api_key}"}, timeout=120)
301 + r.raise_for_status()
302 + data = r.json().get("data", {})
303 + content = (data.get("rawHtml") or data.get("html") or "").encode()
304 + return FetchResult(url=url, final_url=(data.get("metadata") or {}).get("sourceURL") or url, status=200, headers={}, content=content,
305 + content_type="text/html", fetched_at=datetime.now(UTC), duration_ms=int((time.perf_counter() - t0) * 1000),
306 + transport="firecrawl")
307 +
308 +
309 +def _looks_like_challenge(content: bytes) -> bool:
310 + head = content[:20000].lower()
311 + if len(content) > 60_000:
312 + return False
313 + markers = (b"just a moment", b"cf-chl-", b"challenge-platform", b"attention required", b"verify you are human", b"access denied",
314 + b"captcha", b"perimeterx", b"_px", b"datadome", b"enable javascript and cookies to continue")
315 + return sum(m in head for m in markers) >= 2
316 +
317 +
318 +def file_result(path: str, *, url: str, content_type: str = "application/octet-stream") -> FetchResult:
319 + """Wrap a local file as a FetchResult (fixtures, seed snapshots, `aia run x --file`)."""
320 + with open(path, "rb") as fh:
321 + content = fh.read()
322 + return FetchResult(url=url, final_url=url, status=200, headers={}, content=content, content_type=content_type,
323 + fetched_at=datetime.now(UTC), duration_ms=0, transport="file")
324 +
325 +
326 +_limiter = _RateLimiter()
327 +_robots = _Robots()
328 +
329 +__all__ = ["Fetcher", "FetchResult", "FetchError", "BlockedError", "NotModified", "canonicalize_url", "domain_of", "file_result"]
added src/aiatlas/sdk/resolution.py +169 −0
@@ -0,0 +1,169 @@
1 +"""Entity resolution — deterministic first, never merge blindly.
2 +
3 + 1. identifiers (scheme, value) → exact entity
4 + 2. normalized alias within the same entity type (disambiguated by organization when several match)
5 + 3. slug collision within the same type
6 + 4. otherwise create, and park ambiguous cases in the review queue as merge candidates
7 +"""
8 +from __future__ import annotations
9 +
10 +import logging
11 +from datetime import UTC, datetime
12 +from typing import Any
13 +
14 +from sqlalchemy.ext.asyncio import AsyncConnection
15 +
16 +from aiatlas.db import execute, fetch_all, fetch_one, jsonb
17 +from aiatlas.ids import ENTITY_TYPES, new_id, normalize_alias, slugify
18 +from aiatlas.sdk.facts import EntityRef
19 +
20 +log = logging.getLogger(__name__)
21 +
22 +# Types whose slug should be prefixed by the organization slug to stay unique and readable (models: `qwen-qwen3-8b` is ugly →
23 +# we keep the model name and only prefix on collision).
24 +GENERIC_NAMES = {"model", "models", "api", "pricing", "docs", "blog", "news", "research", "overview"}
25 +
26 +
27 +class Resolver:
28 + def __init__(self, conn: AsyncConnection, *, snapshot_id: str | None = None, source_tier: int = 2):
29 + self.conn = conn
30 + self.snapshot_id = snapshot_id
31 + self.tier = source_tier
32 + self._cache: dict[str, str] = {}
33 + self.created: list[str] = []
34 + self.updated: set[str] = set()
35 +
36 + async def resolve(self, ref: EntityRef, *, create: bool = True) -> str | None:
37 + if ref.id:
38 + return ref.id
39 + if ref.entity_type not in ENTITY_TYPES:
40 + raise ValueError(f"unknown entity type {ref.entity_type!r}")
41 + key = ref.key()
42 + if key in self._cache:
43 + ref.id = self._cache[key]
44 + await self._refresh_links(ref)
45 + return ref.id
46 +
47 + org_id = await self.resolve(ref.organization) if ref.organization else None
48 +
49 + found = await self._by_identifiers(ref)
50 + if found is None:
51 + found = await self._by_alias(ref, org_id)
52 + if found is None:
53 + found = await self._by_slug(ref)
54 + if found is None and not create:
55 + return None
56 + if found is None:
57 + found = await self._create(ref, org_id)
58 + else:
59 + await self._touch(found, ref, org_id)
60 + ref.id = found
61 + self._cache[key] = found
62 + await self._refresh_links(ref)
63 + return found
64 +
65 + # ---------------------------------------------------------------------------------------------- lookups
66 + async def _by_identifiers(self, ref: EntityRef) -> str | None:
67 + for scheme, value in ref.identifiers.items():
68 + row = await fetch_one(self.conn, """select ei.entity_id, e.entity_type, e.merged_into from entity_identifiers ei
69 + join entities e on e.id = ei.entity_id where ei.scheme = :s and ei.value = :v""",
70 + s=scheme, v=str(value))
71 + if row:
72 + if row["entity_type"] != ref.entity_type:
73 + log.warning("identifier type mismatch", extra={"scheme": scheme, "value": value, "have": row["entity_type"], "want": ref.entity_type})
74 + continue
75 + return row["merged_into"] or row["entity_id"]
76 + return None
77 +
78 + async def _by_alias(self, ref: EntityRef, org_id: str | None) -> str | None:
79 + names = [ref.name, *ref.aliases]
80 + norms = {normalize_alias(n) for n in names if n and normalize_alias(n)}
81 + if not norms:
82 + return None
83 + rows = await fetch_all(self.conn, """select distinct e.id, e.organization_id, e.canonical_name, e.merged_into from entity_aliases a
84 + join entities e on e.id = a.entity_id
85 + where a.alias_norm = any(cast(:norms as text[])) and e.entity_type = :t""", norms=list(norms), t=ref.entity_type)
86 + if not rows:
87 + return None
88 + rows = [{**r, "id": r["merged_into"] or r["id"]} for r in rows]
89 + ids = {r["id"] for r in rows}
90 + if len(ids) == 1:
91 + return rows[0]["id"]
92 + if org_id:
93 + same_org = [r for r in rows if r["organization_id"] == org_id]
94 + if len({r["id"] for r in same_org}) == 1:
95 + return same_org[0]["id"]
96 + # ambiguous: do not guess — create and flag
97 + await self._review("merge_candidate", sorted(ids), f"alias '{ref.name}' matches {len(ids)} {ref.entity_type} entities",
98 + {"name": ref.name, "identifiers": ref.identifiers})
99 + return None
100 +
101 + async def _by_slug(self, ref: EntityRef) -> str | None:
102 + slug = ref.slug_hint or slugify(ref.name)
103 + row = await fetch_one(self.conn, "select id, entity_type, organization_id, merged_into from entities where slug = :s", s=slug)
104 + if row and row["entity_type"] == ref.entity_type:
105 + return row["merged_into"] or row["id"]
106 + return None
107 +
108 + # ---------------------------------------------------------------------------------------------- writes
109 + async def _create(self, ref: EntityRef, org_id: str | None) -> str:
110 + eid = new_id(ref.entity_type)
111 + slug = await self._unique_slug(ref, org_id)
112 + first_seen = datetime.now(UTC)
113 + await execute(self.conn, """insert into entities (id, entity_type, canonical_name, slug, description, status, organization_id, first_seen_at, last_seen_at)
114 + values (:id, :t, :n, :slug, :d, :status, :org, :fs, now())""",
115 + id=eid, t=ref.entity_type, n=ref.name.strip()[:300], slug=slug, d=(ref.description or None), status=ref.status or "active",
116 + org=org_id, fs=first_seen)
117 + self.created.append(eid)
118 + return eid
119 +
120 + async def _touch(self, eid: str, ref: EntityRef, org_id: str | None) -> None:
121 + sets = ["last_seen_at = now()"]
122 + params: dict[str, Any] = {"id": eid}
123 + if org_id:
124 + sets.append("organization_id = coalesce(organization_id, :org)")
125 + params["org"] = org_id
126 + if ref.description:
127 + sets.append("description = case when description is null or length(description) < 40 then :d else description end")
128 + params["d"] = ref.description
129 + await execute(self.conn, f"update entities set {', '.join(sets)} where id = :id", **params)
130 + self.updated.add(eid)
131 +
132 + async def _refresh_links(self, ref: EntityRef) -> None:
133 + assert ref.id
134 + for alias in {ref.name, *ref.aliases}:
135 + norm = normalize_alias(alias)
136 + if not norm or len(norm) < 2:
137 + continue
138 + await execute(self.conn, """insert into entity_aliases (entity_id, alias, alias_norm, kind, snapshot_id) values (:e, :a, :n, 'alias', :s)
139 + on conflict (entity_id, alias_norm) do nothing""", e=ref.id, a=alias.strip()[:300], n=norm, s=self.snapshot_id)
140 + for scheme, value in ref.identifiers.items():
141 + await execute(self.conn, """insert into entity_identifiers (entity_id, scheme, value, snapshot_id) values (:e, :s, :v, :snap)
142 + on conflict (scheme, value) do nothing""", e=ref.id, s=scheme, v=str(value)[:500], snap=self.snapshot_id)
143 +
144 + async def _unique_slug(self, ref: EntityRef, org_id: str | None) -> str:
145 + base = ref.slug_hint or slugify(ref.name)
146 + if base in GENERIC_NAMES or len(base) < 2:
147 + base = f"{ref.entity_type}-{base}"
148 + candidates = [base]
149 + if org_id:
150 + org_slug = await fetch_one(self.conn, "select slug from entities where id = :id", id=org_id)
151 + if org_slug and not base.startswith(org_slug["slug"]):
152 + candidates.append(f"{org_slug['slug']}-{base}")
153 + for c in candidates:
154 + if not await fetch_one(self.conn, "select 1 from entities where slug = :s", s=c):
155 + return c
156 + n = 2
157 + while True:
158 + c = f"{base}-{n}"
159 + if not await fetch_one(self.conn, "select 1 from entities where slug = :s", s=c):
160 + return c
161 + n += 1
162 +
163 + async def _review(self, kind: str, entity_ids: list[str], reason: str, payload: dict[str, Any]) -> None:
164 + dedupe = f"{kind}:{':'.join(entity_ids)}:{normalize_alias(reason)[:80]}"
165 + await execute(self.conn, """insert into review_queue (id, kind, entity_ids, payload, reason, dedupe_key) values (:id, :k, :ids, cast(:p as jsonb), :r, :d)
166 + on conflict (dedupe_key) do nothing""", id=new_id("review"), k=kind, ids=entity_ids, p=jsonb(payload), r=reason, d=dedupe)
167 +
168 +
169 +__all__ = ["Resolver"]
added src/aiatlas/sdk/writer.py +357 −0
@@ -0,0 +1,357 @@
1 +"""FactWriter — turns `Facts` into versioned database state.
2 +
3 +Temporal rules (per entity × property):
4 + * no current claim → insert current claim, set attribute, NEW_* event for new entities
5 + * same value → confirm (observed_at bumped), nothing else
6 + * different, source ≥ tier → supersede (valid_to = observed), insert new current, update attribute, CHANGE event for material props
7 + * different, worse source → store as `conflicting`, flag confidence, review-queue item — never overwrite
8 +Prices and benchmark results have their own append-only tables with the same close/open semantics.
9 +"""
10 +from __future__ import annotations
11 +
12 +import hashlib
13 +import json
14 +import logging
15 +from datetime import UTC, datetime
16 +from typing import Any
17 +
18 +from sqlalchemy.ext.asyncio import AsyncConnection
19 +
20 +from aiatlas.db import execute, fetch_one, jsonb
21 +from aiatlas.ids import new_id, normalize_alias
22 +from aiatlas.sdk.facts import EVENT_CATEGORY_BY_TYPE, MATERIAL_PROPERTIES, NOISY_PREFIXES, EntityRef, Facts, PriceObs, ResultObs
23 +from aiatlas.sdk.resolution import Resolver
24 +
25 +log = logging.getLogger(__name__)
26 +
27 +TIER_CONFIDENCE = {1: "high", 2: "medium", 3: "low", 4: "low"}
28 +SOFT_PROPERTIES = {"description", "summary", "tagline", "availability_note", "abstract", "notes", "training_data_notes", "safety_notes", "hardware_requirements"}
29 +NEW_IMPORTANCE = {"model": 3, "company": 2, "provider": 2, "paper": 1, "dataset": 1, "benchmark": 2, "framework": 1, "hardware": 2,
30 + "tool": 1, "repository": 0, "release": 2, "regulation": 2, "incident": 2, "organization": 1, "researcher": 0}
31 +
32 +
33 +def _norm_value(v: Any) -> Any:
34 + if isinstance(v, datetime):
35 + return v.astimezone(UTC).isoformat(timespec="seconds")
36 + if isinstance(v, (set, tuple)):
37 + return sorted(v) if all(isinstance(x, str) for x in v) else list(v)
38 + if isinstance(v, float) and v.is_integer() and abs(v) < 1e15:
39 + return int(v)
40 + return v
41 +
42 +
43 +def _same(a: Any, b: Any) -> bool:
44 + return json.dumps(_norm_value(a), sort_keys=True, default=str) == json.dumps(_norm_value(b), sort_keys=True, default=str)
45 +
46 +
47 +class WriteStats:
48 + def __init__(self) -> None:
49 + self.entities_created = 0
50 + self.entities_updated = 0
51 + self.claims = 0
52 + self.relations = 0
53 + self.events = 0
54 + self.prices = 0
55 + self.results = 0
56 + self.conflicts = 0
57 +
58 + def as_dict(self) -> dict[str, int]:
59 + return dict(self.__dict__)
60 +
61 +
62 +class FactWriter:
63 + def __init__(self, conn: AsyncConnection, *, source_id: str | None, snapshot_id: str | None, source_url: str | None,
64 + tier: int = 2, connector_name: str | None = None, extractor: str = "deterministic", extractor_version: str = "1",
65 + observed_at: datetime | None = None):
66 + self.conn = conn
67 + self.source_id = source_id
68 + self.snapshot_id = snapshot_id
69 + self.source_url = source_url
70 + self.tier = tier
71 + self.connector_name = connector_name
72 + self.extractor = extractor
73 + self.extractor_version = extractor_version
74 + self.observed_at = observed_at or datetime.now(UTC)
75 + self.resolver = Resolver(conn, snapshot_id=snapshot_id, source_tier=tier)
76 + self.stats = WriteStats()
77 +
78 + # ---------------------------------------------------------------------------------------------- entry point
79 + async def write(self, facts: Facts) -> WriteStats:
80 + new_before = len(self.resolver.created)
81 + for ref in facts.entities:
82 + await self.resolver.resolve(ref)
83 + for prop, value in ref.attributes.items():
84 + await self.write_claim(ref, prop, value)
85 + for c in facts.claims:
86 + await self.write_claim(c.entity, c.property, c.value, unit=c.unit, confidence=c.confidence, observed_at=c.observed_at,
87 + effective_at=c.effective_at, source_url=c.source_url)
88 + for r in facts.relations:
89 + await self.write_relation(r.subject, r.predicate, r.object, r.attributes, confidence=r.confidence, source_url=r.source_url)
90 + for p in facts.prices:
91 + await self.write_price(p)
92 + for res in facts.results:
93 + await self.write_result(res)
94 + for e in facts.events:
95 + eid = await self.resolver.resolve(e.entity) if e.entity else None
96 + await self.emit_event(e.event_type, e.category, e.summary, entity_id=eid, old_value=e.old_value, new_value=e.new_value,
97 + importance=e.importance, effective_at=e.effective_at, dedupe_key=e.dedupe_key, source_url=e.source_url, meta=e.meta)
98 + # NEW_* events for every entity created in this write
99 + for eid in self.resolver.created[new_before:]:
100 + await self._new_entity_event(eid)
101 + self.stats.entities_created = len(self.resolver.created)
102 + self.stats.entities_updated = len(self.resolver.updated - set(self.resolver.created))
103 + return self.stats
104 +
105 + # ---------------------------------------------------------------------------------------------- claims
106 + async def write_claim(self, ref: EntityRef, prop: str, value: Any, *, unit: str | None = None, confidence: str | None = None,
107 + observed_at: datetime | None = None, effective_at: datetime | None = None, source_url: str | None = None) -> None:
108 + if value is None or value == "" or value == [] or value == {}:
109 + return
110 + eid = await self.resolver.resolve(ref)
111 + assert eid
112 + value = _norm_value(value)
113 + observed = observed_at or self.observed_at
114 + conf = confidence or TIER_CONFIDENCE.get(self.tier, "medium")
115 + url = source_url or self.source_url
116 + noisy = prop.startswith(NOISY_PREFIXES)
117 + current = await fetch_one(self.conn, """select id, value, tier, source_url, observed_at from claims
118 + where entity_id = :e and property = :p and status = 'current' order by valid_from desc limit 1""",
119 + e=eid, p=prop)
120 + is_new_entity = eid in self.resolver.created
121 + if current is None:
122 + await self._insert_claim(eid, prop, value, unit, conf, "current", observed, effective_at, url)
123 + await self._set_attribute(eid, prop, value, unit, conf, url, observed)
124 + return
125 + if _same(current["value"], value):
126 + await execute(self.conn, "update claims set observed_at = greatest(observed_at, :o) where id = :id", o=observed, id=current["id"])
127 + if noisy:
128 + await self._set_attribute(eid, prop, value, unit, conf, url, observed)
129 + return
130 + same_source = bool(url and current["source_url"] == url)
131 + if prop in SOFT_PROPERTIES and not same_source:
132 + # soft text (descriptions, notes): first statement wins until *its own* source changes; never an event, never a conflict
133 + return
134 + if self.tier <= (current["tier"] or 2) or same_source:
135 + # supersede
136 + await execute(self.conn, "update claims set status = 'superseded', valid_to = :o where id = :id", o=observed, id=current["id"])
137 + await self._insert_claim(eid, prop, value, unit, conf, "current", observed, effective_at, url)
138 + await self._set_attribute(eid, prop, value, unit, conf, url, observed)
139 + if not noisy and not is_new_entity and prop not in SOFT_PROPERTIES:
140 + await self._property_change_event(eid, prop, current["value"], value, observed, effective_at, url)
141 + else:
142 + await self._insert_claim(eid, prop, value, unit, conf, "conflicting", observed, effective_at, url)
143 + await execute(self.conn, "update claims set confidence = 'conflicted' where id = :id", id=current["id"])
144 + await execute(self.conn, """update entities set quality = quality || jsonb_build_object('conflicts', coalesce((quality->>'conflicts')::int, 0) + 1)
145 + where id = :id""", id=eid)
146 + self.stats.conflicts += 1
147 + dedupe = f"conflict:{eid}:{prop}:{hashlib.sha1(json.dumps(value, sort_keys=True, default=str).encode()).hexdigest()[:10]}"
148 + await execute(self.conn, """insert into review_queue (id, kind, entity_ids, payload, reason, dedupe_key)
149 + values (:id, 'conflict', :ids, cast(:p as jsonb), :r, :d) on conflict (dedupe_key) do nothing""",
150 + id=new_id("review"), ids=[eid], p=jsonb({"property": prop, "current": current["value"], "current_source": current["source_url"],
151 + "claimed": value, "claimed_source": url, "tier": self.tier}),
152 + r=f"source disagrees on {prop}", d=dedupe)
153 +
154 + async def _insert_claim(self, eid: str, prop: str, value: Any, unit: str | None, conf: str, status: str, observed: datetime,
155 + effective_at: datetime | None, url: str | None) -> None:
156 + text_val = value if isinstance(value, str) else None
157 + num_val = float(value) if isinstance(value, (int, float)) and not isinstance(value, bool) else None
158 + await execute(self.conn, """insert into claims (id, entity_id, property, value, value_text, value_num, unit, source_id, snapshot_id, source_url, tier,
159 + confidence, status, extractor, extractor_version, observed_at, effective_at, valid_from)
160 + values (:id, :e, :p, cast(:v as jsonb), :vt, :vn, :u, :src, :snap, :url, :tier, :conf, :status, :ex, :exv, :o, :eff, :vf)""",
161 + id=new_id("claim"), e=eid, p=prop, v=jsonb(value), vt=text_val[:2000] if text_val else None, vn=num_val, u=unit, src=self.source_id,
162 + snap=self.snapshot_id, url=url, tier=self.tier, conf=conf, status=status, ex=self.extractor, exv=self.extractor_version,
163 + o=observed, eff=effective_at, vf=effective_at or observed)
164 + self.stats.claims += 1
165 +
166 + async def _set_attribute(self, eid: str, prop: str, value: Any, unit: str | None, conf: str, url: str | None, observed: datetime) -> None:
167 + prov = {"source_id": self.source_id, "snapshot_id": self.snapshot_id, "url": url, "observed_at": observed.isoformat(timespec="seconds"),
168 + "tier": self.tier, "confidence": conf, "extractor": self.extractor}
169 + if unit:
170 + prov["unit"] = unit
171 + await execute(self.conn, """update entities set attributes = attributes || jsonb_build_object(cast(:p as text), cast(:v as jsonb)),
172 + provenance = provenance || jsonb_build_object(cast(:p as text), cast(:prov as jsonb)), last_seen_at = greatest(last_seen_at, :o)
173 + where id = :id""", p=prop, v=jsonb(value), prov=jsonb(prov), o=observed, id=eid)
174 + if prop == "status" and isinstance(value, str):
175 + await execute(self.conn, "update entities set status = :s where id = :id", s=value[:40], id=eid)
176 + if prop == "description" and isinstance(value, str):
177 + await execute(self.conn, "update entities set description = :d where id = :id", d=value[:4000], id=eid)
178 +
179 + async def _property_change_event(self, eid: str, prop: str, old: Any, new: Any, observed: datetime, effective_at: datetime | None,
180 + url: str | None) -> None:
181 + event_type, importance = MATERIAL_PROPERTIES.get(prop, ("PROPERTY_CHANGED", 0))
182 + row = await fetch_one(self.conn, "select canonical_name, entity_type from entities where id = :id", id=eid)
183 + name = row["canonical_name"] if row else eid
184 + category = EVENT_CATEGORY_BY_TYPE.get(row["entity_type"] if row else "", "update")
185 + if prop == "status" and str(new).lower() in ("deprecated", "retired", "discontinued"):
186 + importance = 3
187 + summary = f"{name}: {prop.replace('_', ' ')} changed from {_short(old)} to {_short(new)}"
188 + dedupe = f"{event_type}:{eid}:{prop}:{hashlib.sha1(json.dumps([old, new], sort_keys=True, default=str).encode()).hexdigest()[:12]}"
189 + await self.emit_event(event_type, category, summary, entity_id=eid, old_value=old, new_value=new, importance=importance,
190 + effective_at=effective_at, dedupe_key=dedupe, source_url=url, meta={"property": prop}, observed_at=observed)
191 +
192 + # ---------------------------------------------------------------------------------------------- relations
193 + async def write_relation(self, subject: EntityRef, predicate: str, obj: EntityRef, attributes: dict[str, Any] | None = None, *,
194 + confidence: str | None = None, source_url: str | None = None) -> None:
195 + sid = await self.resolver.resolve(subject)
196 + oid = await self.resolver.resolve(obj)
197 + if not sid or not oid or sid == oid:
198 + return
199 + conf = confidence or TIER_CONFIDENCE.get(self.tier, "medium")
200 + existing = await fetch_one(self.conn, "select id, attributes from relations where subject_id = :s and predicate = :p and object_id = :o and valid_to is null",
201 + s=sid, p=predicate, o=oid)
202 + if existing:
203 + if attributes and not _same(existing["attributes"], {**existing["attributes"], **attributes}):
204 + await execute(self.conn, "update relations set attributes = attributes || cast(:a as jsonb), observed_at = :o where id = :id",
205 + a=jsonb(attributes), o=self.observed_at, id=existing["id"])
206 + else:
207 + await execute(self.conn, "update relations set observed_at = :o where id = :id", o=self.observed_at, id=existing["id"])
208 + return
209 + await execute(self.conn, """insert into relations (id, subject_id, predicate, object_id, attributes, source_id, snapshot_id, source_url, tier, confidence, observed_at, valid_from)
210 + values (:id, :s, :p, :o, cast(:a as jsonb), :src, :snap, :url, :tier, :conf, :obs, :obs)""",
211 + id=new_id("relation"), s=sid, p=predicate, o=oid, a=jsonb(attributes or {}), src=self.source_id, snap=self.snapshot_id,
212 + url=source_url or self.source_url, tier=self.tier, conf=conf, obs=self.observed_at)
213 + self.stats.relations += 1
214 +
215 + # ---------------------------------------------------------------------------------------------- prices
216 + async def write_price(self, p: PriceObs) -> None:
217 + mid = await self.resolver.resolve(p.model)
218 + pid = await self.resolver.resolve(p.provider)
219 + if not mid or not pid:
220 + return
221 + if all(v is None for v in p.price_tuple()[:-1]):
222 + return
223 + url = p.source_url or self.source_url
224 + current = await fetch_one(self.conn, """select * from prices where model_id = :m and provider_id = :p and coalesce(provider_model_id,'') = :pm and valid_to is null""",
225 + m=mid, p=pid, pm=p.provider_model_id or "")
226 + new_tuple = p.price_tuple()
227 + if current:
228 + cur_tuple = (current["input_per_mtok"], current["output_per_mtok"], current["cached_input_per_mtok"], current["cache_write_per_mtok"],
229 + current["batch_input_per_mtok"], current["batch_output_per_mtok"], current["per_image"], current["per_request"], current["currency"])
230 + if _same(cur_tuple, new_tuple) and (p.context_length in (None, current["context_length"])):
231 + await execute(self.conn, "update prices set observed_at = :o where id = :id", o=self.observed_at, id=current["id"])
232 + return
233 + await execute(self.conn, "update prices set valid_to = :o where id = :id", o=self.observed_at, id=current["id"])
234 + await execute(self.conn, """insert into prices (id, model_id, provider_id, provider_model_id, input_per_mtok, output_per_mtok, cached_input_per_mtok, cache_write_per_mtok,
235 + batch_input_per_mtok, batch_output_per_mtok, per_image, per_request, currency, context_length, max_output_tokens, features,
236 + observed_at, valid_from, source_id, snapshot_id, source_url, tier, meta)
237 + values (:id, :m, :p, :pm, :i, :o, :ci, :cw, :bi, :bo, :img, :req, :cur, :ctx, :mo, cast(:f as jsonb), :obs, :obs, :src, :snap, :url, :tier, cast(:meta as jsonb))""",
238 + id=new_id("price"), m=mid, p=pid, pm=p.provider_model_id, i=p.input_per_mtok, o=p.output_per_mtok, ci=p.cached_input_per_mtok,
239 + cw=p.cache_write_per_mtok, bi=p.batch_input_per_mtok, bo=p.batch_output_per_mtok, img=p.per_image, req=p.per_request, cur=p.currency,
240 + ctx=p.context_length, mo=p.max_output_tokens, f=jsonb(p.features), obs=self.observed_at, src=self.source_id, snap=self.snapshot_id,
241 + url=url, tier=self.tier, meta=jsonb(p.meta))
242 + self.stats.prices += 1
243 + model = await fetch_one(self.conn, "select canonical_name from entities where id = :id", id=mid)
244 + provider = await fetch_one(self.conn, "select canonical_name from entities where id = :id", id=pid)
245 + mname = model["canonical_name"] if model else mid
246 + pname = provider["canonical_name"] if provider else pid
247 + if current:
248 + old = {"input_per_mtok": current["input_per_mtok"], "output_per_mtok": current["output_per_mtok"]}
249 + new = {"input_per_mtok": p.input_per_mtok, "output_per_mtok": p.output_per_mtok}
250 + summary = f"{pname} changed pricing for {mname}: {_fmt_price(old)}{_fmt_price(new)}"
251 + dedupe = f"PRICE_CHANGED:{mid}:{pid}:{p.provider_model_id or ''}:{hashlib.sha1(json.dumps([old, new], sort_keys=True, default=str).encode()).hexdigest()[:12]}"
252 + await self.emit_event("PRICE_CHANGED", "price", summary, entity_id=mid, old_value=old, new_value=new, importance=2, dedupe_key=dedupe,
253 + source_url=url, meta={"provider_id": pid, "provider": pname})
254 + else:
255 + new = {"input_per_mtok": p.input_per_mtok, "output_per_mtok": p.output_per_mtok}
256 + summary = f"{pname} lists {mname} at {_fmt_price(new)}"
257 + dedupe = f"PROVIDER_LISTED:{mid}:{pid}:{p.provider_model_id or ''}"
258 + await self.emit_event("PROVIDER_LISTED", "provider", summary, entity_id=mid, new_value=new, importance=1, dedupe_key=dedupe, source_url=url,
259 + meta={"provider_id": pid, "provider": pname})
260 + await self.write_relation(p.model, "available_through", p.provider, {"provider_model_id": p.provider_model_id}, source_url=url)
261 +
262 + # ---------------------------------------------------------------------------------------------- benchmark results
263 + async def write_result(self, r: ResultObs) -> None:
264 + mid = await self.resolver.resolve(r.model)
265 + bid = await self.resolver.resolve(r.benchmark)
266 + if not mid or not bid:
267 + return
268 + url = r.source_url or self.source_url
269 + cfg_hash = hashlib.sha1(json.dumps(r.config, sort_keys=True, default=str).encode()).hexdigest()[:12]
270 + dedupe = f"{mid}:{bid}:{cfg_hash}:{r.metric or ''}"
271 + existing = await fetch_one(self.conn, "select id, score from benchmark_results where dedupe_key = :d", d=dedupe)
272 + conf = r.confidence or TIER_CONFIDENCE.get(self.tier, "medium")
273 + if existing:
274 + if abs((existing["score"] or 0) - r.score) > 1e-9:
275 + await execute(self.conn, "update benchmark_results set valid_to = :o, dedupe_key = dedupe_key || ':' || :suffix where id = :id",
276 + o=self.observed_at, suffix=self.observed_at.strftime("%Y%m%d%H%M%S"), id=existing["id"])
277 + model = await fetch_one(self.conn, "select canonical_name from entities where id = :id", id=mid)
278 + bench = await fetch_one(self.conn, "select canonical_name from entities where id = :id", id=bid)
279 + await self.emit_event("BENCHMARK_UPDATED", "benchmark",
280 + f"{model['canonical_name'] if model else mid} on {bench['canonical_name'] if bench else bid}: {existing['score']:g}{r.score:g}",
281 + entity_id=mid, old_value=existing["score"], new_value=r.score, importance=1,
282 + dedupe_key=f"BENCHMARK_UPDATED:{dedupe}:{r.score:g}", source_url=url, meta={"benchmark_id": bid})
283 + else:
284 + await execute(self.conn, "update benchmark_results set observed_at = :o where id = :id", o=self.observed_at, id=existing["id"])
285 + return
286 + await execute(self.conn, """insert into benchmark_results (id, model_id, benchmark_id, score, metric, unit, higher_is_better, config, evaluated_at, observed_at,
287 + source_id, snapshot_id, source_url, tier, confidence, dedupe_key)
288 + values (:id, :m, :b, :s, :metric, :unit, :hib, cast(:cfg as jsonb), :ev, :obs, :src, :snap, :url, :tier, :conf, :d)""",
289 + id=new_id("result"), m=mid, b=bid, s=r.score, metric=r.metric, unit=r.unit, hib=r.higher_is_better, cfg=jsonb(r.config),
290 + ev=r.evaluated_at, obs=self.observed_at, src=self.source_id, snap=self.snapshot_id, url=url, tier=self.tier, conf=conf, d=dedupe)
291 + self.stats.results += 1
292 + if not existing:
293 + model = await fetch_one(self.conn, "select canonical_name from entities where id = :id", id=mid)
294 + bench = await fetch_one(self.conn, "select canonical_name from entities where id = :id", id=bid)
295 + await self.emit_event("BENCHMARK_RESULT", "benchmark",
296 + f"{model['canonical_name'] if model else mid} scores {r.score:g}{r.unit or ''} on {bench['canonical_name'] if bench else bid}",
297 + entity_id=mid, new_value=r.score, importance=1, dedupe_key=f"BENCHMARK_RESULT:{dedupe}", source_url=url,
298 + meta={"benchmark_id": bid, "metric": r.metric})
299 + await self.write_relation(r.model, "evaluated_on", r.benchmark, source_url=url)
300 +
301 + # ---------------------------------------------------------------------------------------------- events
302 + async def emit_event(self, event_type: str, category: str, summary: str, *, entity_id: str | None = None, old_value: Any = None,
303 + new_value: Any = None, importance: int = 2, effective_at: datetime | None = None, dedupe_key: str | None = None,
304 + source_url: str | None = None, meta: dict[str, Any] | None = None, observed_at: datetime | None = None) -> None:
305 + dedupe = dedupe_key or f"{event_type}:{entity_id or ''}:{normalize_alias(summary)[:120]}"
306 + await execute(self.conn, """insert into change_events (id, entity_id, event_type, category, property, old_value, new_value, summary, importance, observed_at,
307 + effective_at, source_id, snapshot_id, source_url, connector_name, dedupe_key, meta)
308 + values (:id, :e, :t, :c, :p, cast(:o as jsonb), cast(:n as jsonb), :s, :imp, :obs, :eff, :src, :snap, :url, :conn, :d, cast(:meta as jsonb))
309 + on conflict (dedupe_key) do nothing""",
310 + id=new_id("change_event"), e=entity_id, t=event_type, c=category, p=(meta or {}).get("property"), o=jsonb(old_value) if old_value is not None else None,
311 + n=jsonb(new_value) if new_value is not None else None, s=summary[:500], imp=max(0, min(3, importance)), obs=observed_at or self.observed_at,
312 + eff=effective_at, src=self.source_id, snap=self.snapshot_id, url=source_url or self.source_url, conn=self.connector_name, d=dedupe[:400],
313 + meta=jsonb(meta or {}))
314 + self.stats.events += 1
315 +
316 + async def _new_entity_event(self, eid: str) -> None:
317 + row = await fetch_one(self.conn, "select canonical_name, entity_type, attributes, organization_id from entities where id = :id", id=eid)
318 + if not row:
319 + return
320 + etype = row["entity_type"]
321 + if etype in ("researcher", "country", "license", "quantization"):
322 + return
323 + importance = NEW_IMPORTANCE.get(etype, 1)
324 + if self.tier > 2:
325 + importance = max(0, importance - 1)
326 + org = None
327 + if row["organization_id"]:
328 + o = await fetch_one(self.conn, "select canonical_name from entities where id = :id", id=row["organization_id"])
329 + org = o["canonical_name"] if o else None
330 + label = etype.replace("_", " ")
331 + summary = f"New {label}: {row['canonical_name']}" + (f" ({org})" if org else "")
332 + effective = None
333 + rel = row["attributes"].get("release_date") or row["attributes"].get("published_at")
334 + if isinstance(rel, str):
335 + from aiatlas.sdk.extract.dates import parse_datetime
336 +
337 + effective = parse_datetime(rel)
338 + await self.emit_event(f"NEW_{etype.upper()}", EVENT_CATEGORY_BY_TYPE.get(etype, "update"), summary, entity_id=eid, importance=importance,
339 + dedupe_key=f"NEW_{etype.upper()}:{eid}", effective_at=effective)
340 +
341 +
342 +def _short(v: Any) -> str:
343 + s = json.dumps(v, default=str, ensure_ascii=False) if not isinstance(v, str) else v
344 + return s if len(s) <= 60 else s[:57] + "…"
345 +
346 +
347 +def _fmt_price(p: dict[str, Any]) -> str:
348 + i, o = p.get("input_per_mtok"), p.get("output_per_mtok")
349 + parts = []
350 + if i is not None:
351 + parts.append(f"${i:g} in")
352 + if o is not None:
353 + parts.append(f"${o:g} out")
354 + return " / ".join(parts) + " per 1M tokens" if parts else "n/a"
355 +
356 +
357 +__all__ = ["FactWriter", "WriteStats"]
added src/aiatlas/services/__init__.py +1 −0
@@ -0,0 +1 @@
1 +"""Platform services: jobs queue, scheduler, LLM gateway, embeddings, quality, stats, search, backups."""
added src/aiatlas/services/backup.py +39 −0
@@ -0,0 +1,39 @@
1 +"""Database backups (pg_dump custom format, gzip-compressed by pg_dump) into AIA_DATA_DIR/backups. Off-node copies: scripts/backup-offnode.sh.
2 +The dataset is worth more than the code — keep 30 dailies."""
3 +from __future__ import annotations
4 +
5 +import os
6 +import shutil
7 +import subprocess
8 +from datetime import UTC, datetime
9 +from pathlib import Path
10 +from urllib.parse import urlparse
11 +
12 +from aiatlas.config import settings
13 +
14 +
15 +def _pg_dump() -> str:
16 + for candidate in ("/opt/homebrew/opt/postgresql@17/bin/pg_dump", "/opt/homebrew/bin/pg_dump", "/usr/local/bin/pg_dump", "pg_dump"):
17 + if shutil.which(candidate) or os.path.exists(candidate):
18 + return candidate
19 + raise RuntimeError("pg_dump not found")
20 +
21 +
22 +def backup_database(keep: int = 30) -> Path:
23 + settings.ensure_dirs()
24 + url = urlparse(settings.sync_database_url)
25 + stamp = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
26 + out = settings.backups_dir / f"aiatlas-{stamp}.dump"
27 + env = dict(os.environ)
28 + if url.password:
29 + env["PGPASSWORD"] = url.password
30 + cmd = [_pg_dump(), "-Fc", "-Z", "6", "-f", str(out), "-h", url.hostname or "127.0.0.1", "-p", str(url.port or 5432), "-U", url.username or "aiatlas",
31 + (url.path or "/aiatlas").lstrip("/")]
32 + subprocess.run(cmd, check=True, env=env, timeout=3600)
33 + dumps = sorted(settings.backups_dir.glob("aiatlas-*.dump"))
34 + for old in dumps[:-keep]:
35 + old.unlink(missing_ok=True)
36 + return out
37 +
38 +
39 +__all__ = ["backup_database"]
added src/aiatlas/services/cache.py +99 −0
@@ -0,0 +1,99 @@
1 +"""Redis helpers: API cache (prefix `aia:api:`), distributed locks (`aia:lock:`), heartbeats."""
2 +from __future__ import annotations
3 +
4 +import asyncio
5 +import logging
6 +from collections.abc import AsyncIterator
7 +from contextlib import asynccontextmanager
8 +from typing import Any
9 +
10 +import orjson
11 +from redis.asyncio import Redis
12 +
13 +from aiatlas.config import settings
14 +
15 +log = logging.getLogger(__name__)
16 +_redis: Redis | None = None
17 +
18 +
19 +def redis() -> Redis:
20 + global _redis
21 + if _redis is None:
22 + _redis = Redis.from_url(settings.redis_url, decode_responses=False, socket_connect_timeout=3, socket_timeout=5)
23 + return _redis
24 +
25 +
26 +async def cache_get(key: str) -> Any | None:
27 + try:
28 + raw = await redis().get(f"aia:api:{key}")
29 + return orjson.loads(raw) if raw else None
30 + except Exception: # noqa: BLE001
31 + return None
32 +
33 +
34 +async def cache_set(key: str, value: Any, ttl_s: int = 300) -> None:
35 + try:
36 + await redis().set(f"aia:api:{key}", orjson.dumps(value, default=str), ex=ttl_s)
37 + except Exception: # noqa: BLE001
38 + pass
39 +
40 +
41 +async def cache_invalidate(prefix: str = "") -> int:
42 + n = 0
43 + try:
44 + async for key in redis().scan_iter(match=f"aia:api:{prefix}*", count=500):
45 + await redis().delete(key)
46 + n += 1
47 + except Exception: # noqa: BLE001
48 + pass
49 + return n
50 +
51 +
52 +@asynccontextmanager
53 +async def lock(name: str, ttl_s: int = 3600) -> AsyncIterator[bool]:
54 + """Best-effort distributed lock. Yields False when someone else holds it (callers must skip)."""
55 + key = f"aia:lock:{name}"
56 + acquired = False
57 + try:
58 + acquired = bool(await redis().set(key, b"1", nx=True, ex=ttl_s))
59 + except Exception as exc: # noqa: BLE001
60 + log.warning("redis unavailable, proceeding without lock", extra={"error": str(exc)})
61 + acquired = True
62 + try:
63 + yield acquired
64 + finally:
65 + if acquired:
66 + try:
67 + await redis().delete(key)
68 + except Exception: # noqa: BLE001
69 + pass
70 +
71 +
72 +async def heartbeat(service: str, payload: dict[str, Any], ttl_s: int = 180) -> None:
73 + try:
74 + await redis().set(f"aia:heartbeat:{service}", orjson.dumps(payload, default=str), ex=ttl_s)
75 + except Exception: # noqa: BLE001
76 + pass
77 +
78 +
79 +async def heartbeats() -> dict[str, Any]:
80 + out: dict[str, Any] = {}
81 + try:
82 + async for key in redis().scan_iter(match="aia:heartbeat:*"):
83 + raw = await redis().get(key)
84 + if raw:
85 + out[key.decode().rsplit(":", 1)[-1]] = orjson.loads(raw)
86 + except Exception: # noqa: BLE001
87 + pass
88 + return out
89 +
90 +
91 +async def close() -> None:
92 + global _redis
93 + if _redis is not None:
94 + await _redis.aclose()
95 + _redis = None
96 + await asyncio.sleep(0)
97 +
98 +
99 +__all__ = ["redis", "cache_get", "cache_set", "cache_invalidate", "lock", "heartbeat", "heartbeats", "close"]
added src/aiatlas/services/embeddings.py +83 −0
@@ -0,0 +1,83 @@
1 +"""Local embeddings (via the LLM gateway's embedding endpoint) stored in pgvector. Semantic search is optional: FTS works without it."""
2 +from __future__ import annotations
3 +
4 +import hashlib
5 +import logging
6 +from typing import Any
7 +
8 +from aiatlas.config import settings
9 +from aiatlas.db import execute, fetch_all, fetch_one, transaction
10 +from aiatlas.services.llm import LLMUnavailable, gateway
11 +
12 +log = logging.getLogger(__name__)
13 +
14 +
15 +def entity_text(row: dict[str, Any]) -> str:
16 + attrs = row.get("attributes") or {}
17 + bits = [row["canonical_name"], row["entity_type"].replace("_", " ")]
18 + for k in ("family", "architecture", "openness", "license", "modalities", "country", "kind", "category"):
19 + v = attrs.get(k)
20 + if v:
21 + bits.append(f"{k}: {', '.join(v) if isinstance(v, list) else v}")
22 + if row.get("organization_name"):
23 + bits.append(f"by {row['organization_name']}")
24 + if row.get("description"):
25 + bits.append(row["description"][:1200])
26 + return "\n".join(str(b) for b in bits)
27 +
28 +
29 +async def embed_entities(entity_ids: list[str]) -> dict[str, Any]:
30 + if not gateway.available:
31 + raise LLMUnavailable("embedding engine not configured")
32 + async with transaction() as conn:
33 + has_vector = await fetch_one(conn, "select 1 from pg_extension where extname = 'vector'")
34 + if not has_vector:
35 + return {"skipped": "pgvector missing"}
36 + rows = await fetch_all(conn, """select e.id, e.entity_type, e.canonical_name, e.description, e.attributes, o.canonical_name as organization_name
37 + from entities e left join entities o on o.id = e.organization_id where e.id = any(cast(:ids as text[]))""", ids=entity_ids)
38 + todo = []
39 + for r in rows:
40 + text = entity_text(r)
41 + h = hashlib.sha256((settings.embedding_model + text).encode()).hexdigest()
42 + async with transaction() as conn:
43 + existing = await fetch_one(conn, "select text_hash from entity_embeddings where entity_id = :id", id=r["id"])
44 + if existing and existing["text_hash"] == h:
45 + continue
46 + todo.append((r["id"], text, h))
47 + done = 0
48 + for i in range(0, len(todo), 16):
49 + batch = todo[i:i + 16]
50 + vectors = await gateway.embed([t for _, t, _ in batch])
51 + async with transaction() as conn:
52 + for (eid, _, h), vec in zip(batch, vectors, strict=False):
53 + if len(vec) != settings.embedding_dim:
54 + log.warning("embedding dimension mismatch", extra={"got": len(vec), "want": settings.embedding_dim})
55 + continue
56 + await execute(conn, """insert into entity_embeddings (entity_id, model, embedding, text_hash) values (:id, :m, cast(:v as vector), :h)
57 + on conflict (entity_id) do update set model = excluded.model, embedding = excluded.embedding, text_hash = excluded.text_hash, created_at = now()""",
58 + id=eid, m=settings.embedding_model, v="[" + ",".join(f"{x:.6f}" for x in vec) + "]", h=h)
59 + done += 1
60 + return {"embedded": done, "skipped": len(rows) - len(todo)}
61 +
62 +
63 +async def embed_query(text: str) -> list[float] | None:
64 + if not gateway.available:
65 + return None
66 + try:
67 + return (await gateway.embed([text]))[0]
68 + except Exception as exc: # noqa: BLE001
69 + log.info("query embedding failed", extra={"error": str(exc)})
70 + return None
71 +
72 +
73 +async def pending_entity_ids(limit: int = 200) -> list[str]:
74 + async with transaction() as conn:
75 + if not await fetch_one(conn, "select 1 from pg_extension where extname = 'vector'"):
76 + return []
77 + rows = await fetch_all(conn, """select e.id from entities e left join entity_embeddings x on x.entity_id = e.id
78 + where e.merged_into is null and e.entity_type in ('model','company','paper','provider','benchmark','hardware','framework','tool','dataset')
79 + and (x.entity_id is null or x.created_at < e.updated_at - interval '1 day') order by e.updated_at desc limit :n""", n=limit)
80 + return [r["id"] for r in rows]
81 +
82 +
83 +__all__ = ["embed_entities", "embed_query", "entity_text", "pending_entity_ids"]
added src/aiatlas/services/handlers.py +228 −0
@@ -0,0 +1,228 @@
1 +"""Job handlers (registered with `@handler`): LLM extraction of stored snapshots, embeddings, reprocessing, quality recompute."""
2 +from __future__ import annotations
3 +
4 +import logging
5 +from datetime import UTC
6 +from typing import Any
7 +
8 +from aiatlas.db import execute, fetch_one, transaction
9 +from aiatlas.sdk import archive
10 +from aiatlas.sdk.facts import EntityRef, Facts
11 +from aiatlas.sdk.writer import FactWriter
12 +from aiatlas.schemas import schema_for
13 +from aiatlas.services.jobs import handler
14 +from aiatlas.services.llm import LLMUnavailable, gateway
15 +
16 +log = logging.getLogger(__name__)
17 +
18 +
19 +@handler("llm_extract")
20 +async def llm_extract(payload: dict[str, Any], job: dict[str, Any]) -> dict[str, Any] | None:
21 + """Stage 2–4: run the local LLM on a stored snapshot's cleaned text and write facts with extractor='llm'."""
22 + if not gateway.available:
23 + raise LLMUnavailable("LLM not configured; leaving snapshot llm_pending")
24 + snapshot_id = payload["snapshot_id"]
25 + async with transaction() as conn:
26 + snap = await fetch_one(conn, """select s.*, d.doc_type, d.entity_id as doc_entity_id, d.connector_name, d.source_id, e.entity_type, e.canonical_name
27 + from snapshots s join documents d on d.id = s.document_id left join entities e on e.id = d.entity_id where s.id = :id""", id=snapshot_id)
28 + if not snap or not snap["text_path"]:
29 + return {"skipped": "no text"}
30 + text = archive.load_text(snap["text_path"])
31 + if len(text) < 200:
32 + async with transaction() as conn:
33 + await execute(conn, "update snapshots set processing_status = 'llm_done' where id = :id", id=snapshot_id)
34 + return {"skipped": "too short"}
35 + task = payload.get("task") or "auto"
36 + if task == "auto":
37 + task = _guess_task(snap["doc_type"], snap["entity_type"])
38 + if task == "classify_then_extract":
39 + label = await gateway.classify(text=text, labels=["model_release", "pricing", "research_paper", "company_news", "framework_release", "hardware", "other"],
40 + snapshot_id=snapshot_id)
41 + task = {"model_release": "release_announcement", "pricing": "pricing", "research_paper": "paper_passport", "company_news": "release_announcement",
42 + "framework_release": "release_announcement", "hardware": "hardware_spec"}.get(label or "", "")
43 + if not task:
44 + async with transaction() as conn:
45 + await execute(conn, "update snapshots set processing_status = 'llm_done' where id = :id", id=snapshot_id)
46 + return {"classified": label, "extracted": False}
47 + schema, stage = schema_for(task)
48 + res = await gateway.extract(task_type=task, document=text, schema=schema, stage=stage, snapshot_id=snapshot_id, entity_id=snap["doc_entity_id"], job_id=job["id"])
49 + if not res.ok or not res.data:
50 + async with transaction() as conn:
51 + await execute(conn, "update snapshots set processing_status = 'failed' where id = :id", id=snapshot_id)
52 + raise RuntimeError(f"llm extraction failed: {res.error}")
53 + facts = facts_from_llm(task, res.data, entity_id=snap["doc_entity_id"], entity_type=snap["entity_type"], entity_name=snap["canonical_name"], url=snap["url"])
54 + async with transaction() as conn:
55 + tier = await fetch_one(conn, "select tier from sources where id = :id", id=snap["source_id"]) if snap["source_id"] else None
56 + writer = FactWriter(conn, source_id=snap["source_id"], snapshot_id=snapshot_id, source_url=snap["url"], tier=(tier["tier"] if tier else 2),
57 + connector_name=snap["connector_name"], extractor="llm", extractor_version=res.model, observed_at=snap["observed_at"].astimezone(UTC))
58 + ws = await writer.write(facts)
59 + await execute(conn, "update snapshots set processing_status = 'llm_done' where id = :id", id=snapshot_id)
60 + return {"task": task, "model": res.model, **ws.as_dict()}
61 +
62 +
63 +def _guess_task(doc_type: str | None, entity_type: str | None) -> str:
64 + if doc_type in ("model_card", "model_page") or entity_type == "model":
65 + return "model_passport"
66 + if doc_type == "pricing":
67 + return "pricing"
68 + if doc_type in ("paper", "pdf"):
69 + return "paper_passport"
70 + if doc_type == "leaderboard":
71 + return "benchmark_results"
72 + if entity_type in ("company", "organization"):
73 + return "company_passport"
74 + if entity_type == "hardware" or doc_type == "hardware":
75 + return "hardware_spec"
76 + if doc_type in ("release", "feed_item", "news"):
77 + return "release_announcement"
78 + return "classify_then_extract"
79 +
80 +
81 +def facts_from_llm(task: str, data: dict[str, Any], *, entity_id: str | None, entity_type: str | None, entity_name: str | None, url: str) -> Facts:
82 + """Map a validated LLM output onto facts. LLM claims default to 'medium' confidence and never outrank tier-1 deterministic ones
83 + (the writer stores disagreements as conflicting)."""
84 + facts = Facts()
85 + conf = "medium"
86 +
87 + def model_ref(name: str, developer: str | None = None) -> EntityRef:
88 + org = facts.entity("company", developer) if developer else None
89 + return facts.entity("model", name, organization=org)
90 +
91 + if task == "model_passport":
92 + name = data.get("name") or entity_name
93 + if not name:
94 + return facts
95 + ref = EntityRef(entity_type="model", name=name, id=entity_id) if entity_id and entity_type == "model" else model_ref(name, data.get("developer"))
96 + if ref not in facts.entities:
97 + facts.entities.append(ref)
98 + for prop in ("family", "version", "release_date", "status", "openness", "license", "architecture", "parameter_count", "active_parameter_count", "is_moe",
99 + "context_length", "max_output_tokens", "knowledge_cutoff", "tool_calling", "structured_output", "reasoning", "vision", "audio",
100 + "fine_tuning_available", "tokenizer", "hardware_requirements", "safety_notes", "training_data_notes"):
101 + facts.claim(ref, prop, data.get(prop), confidence=conf)
102 + mods = sorted(set((data.get("modalities_input") or []) + (data.get("modalities_output") or [])))
103 + facts.claim(ref, "modalities", mods, confidence=conf)
104 + facts.claim(ref, "modalities_input", data.get("modalities_input"), confidence=conf)
105 + facts.claim(ref, "modalities_output", data.get("modalities_output"), confidence=conf)
106 + facts.claim(ref, "languages", data.get("languages"), confidence=conf)
107 + for key, prop in (("paper_url", "paper_url"), ("model_card_url", "model_card_url"), ("repository_url", "repository_url"), ("official_page_url", "official_url")):
108 + facts.claim(ref, prop, data.get(key), confidence=conf)
109 + if data.get("developer") and not (entity_id and entity_type == "model"):
110 + pass
111 + elif data.get("developer"):
112 + org = facts.entity("company", data["developer"])
113 + facts.relate(org, "develops", ref, confidence=conf)
114 + if data.get("base_model"):
115 + base = facts.entity("model", data["base_model"])
116 + facts.relate(ref, "derived_from", base, confidence="low")
117 + if data.get("predecessor"):
118 + pred = facts.entity("model", data["predecessor"])
119 + facts.relate(pred, "superseded_by", ref, confidence="low")
120 + facts.document_entity = ref
121 + elif task == "pricing":
122 + provider_name = data.get("provider")
123 + if not provider_name:
124 + return facts
125 + provider = facts.entity("provider", provider_name)
126 + for line in data.get("prices") or []:
127 + if not line.get("model"):
128 + continue
129 + model = facts.entity("model", line["model"])
130 + facts.price(model=model, provider=provider, provider_model_id=line.get("provider_model_id"), input_per_mtok=line.get("input_per_mtok"),
131 + output_per_mtok=line.get("output_per_mtok"), cached_input_per_mtok=line.get("cached_input_per_mtok"),
132 + cache_write_per_mtok=line.get("cache_write_per_mtok"), batch_input_per_mtok=line.get("batch_input_per_mtok"),
133 + batch_output_per_mtok=line.get("batch_output_per_mtok"), per_image=line.get("per_image"), currency=data.get("currency") or "USD",
134 + context_length=line.get("context_length"), max_output_tokens=line.get("max_output_tokens"), meta={"extractor": "llm", "notes": line.get("notes")})
135 + elif task == "company_passport":
136 + name = data.get("name") or entity_name
137 + if not name:
138 + return facts
139 + ref = EntityRef(entity_type="company", name=name, id=entity_id) if entity_id and entity_type in ("company", "organization") else facts.entity("company", name)
140 + if ref not in facts.entities:
141 + facts.entities.append(ref)
142 + for prop in ("legal_name", "country", "headquarters", "founded", "founders", "leadership", "website", "employee_count", "funding_total_usd"):
143 + facts.claim(ref, prop, data.get(prop), confidence=conf)
144 + if data.get("description"):
145 + facts.claim(ref, "description", data["description"], confidence=conf)
146 + for m in data.get("models") or []:
147 + facts.relate(ref, "develops", facts.entity("model", m, organization=ref), confidence="low")
148 + for inv in data.get("investors") or []:
149 + facts.relate(ref, "funded_by", facts.entity("company", inv), confidence="low")
150 + if data.get("parent_company"):
151 + facts.relate(facts.entity("company", data["parent_company"]), "owns", ref, confidence="low")
152 + facts.document_entity = ref
153 + elif task == "paper_passport":
154 + title = data.get("title") or entity_name
155 + if not title:
156 + return facts
157 + ref = EntityRef(entity_type="paper", name=title, id=entity_id) if entity_id and entity_type == "paper" else facts.entity("paper", title)
158 + if ref not in facts.entities:
159 + facts.entities.append(ref)
160 + for prop in ("authors", "affiliations", "date", "field", "summary", "methods", "key_claims", "results", "limitations", "code_url"):
161 + facts.claim(ref, prop, data.get(prop), confidence=conf)
162 + for m in data.get("models") or []:
163 + facts.relate(facts.entity("model", m), "described_by", ref, confidence="low")
164 + for d in data.get("datasets") or []:
165 + facts.relate(ref, "uses_dataset", facts.entity("dataset", d), confidence="low")
166 + for b in data.get("benchmarks") or []:
167 + facts.relate(ref, "evaluates_on", facts.entity("benchmark", b), confidence="low")
168 + facts.document_entity = ref
169 + elif task == "benchmark_results":
170 + bname = data.get("benchmark") or entity_name
171 + if not bname:
172 + return facts
173 + bench = facts.entity("benchmark", bname)
174 + for row in data.get("rows") or []:
175 + if row.get("model") and row.get("score") is not None:
176 + facts.result(model=facts.entity("model", row["model"]), benchmark=bench, score=float(row["score"]), metric=row.get("metric") or data.get("metric"),
177 + higher_is_better=bool(data.get("higher_is_better", True)), config={"config": row.get("config"), "extractor": "llm"}, confidence="low")
178 + elif task == "hardware_spec":
179 + name = data.get("name") or entity_name
180 + if not name:
181 + return facts
182 + org = facts.entity("company", data["manufacturer"]) if data.get("manufacturer") else None
183 + ref = EntityRef(entity_type="hardware", name=name, id=entity_id) if entity_id and entity_type == "hardware" else facts.entity("hardware", name, organization=org)
184 + if ref not in facts.entities:
185 + facts.entities.append(ref)
186 + for prop in ("kind", "architecture", "release_date", "memory_gb", "memory_type", "memory_bandwidth_gbs", "compute_fp16_tflops", "compute_fp8_tflops",
187 + "compute_int8_tops", "tdp_watts", "form_factor", "price_usd", "interconnect"):
188 + facts.claim(ref, prop, data.get(prop), confidence=conf)
189 + if org:
190 + facts.relate(org, "manufactures", ref, confidence=conf)
191 + facts.document_entity = ref
192 + elif task == "release_announcement":
193 + org = facts.entity("company", data["organization"]) if data.get("organization") else None
194 + for m in data.get("models") or []:
195 + ref = facts.entity("model", m, organization=org)
196 + if org:
197 + facts.relate(org, "develops", ref, confidence="low")
198 + if data.get("model_passport"):
199 + facts.extend(facts_from_llm("model_passport", data["model_passport"], entity_id=None, entity_type=None, entity_name=None, url=url))
200 + if data.get("pricing"):
201 + facts.extend(facts_from_llm("pricing", data["pricing"], entity_id=None, entity_type=None, entity_name=None, url=url))
202 + return facts
203 +
204 +
205 +@handler("embed_entity")
206 +async def embed_entity(payload: dict[str, Any], job: dict[str, Any]) -> dict[str, Any] | None:
207 + from aiatlas.services.embeddings import embed_entities
208 +
209 + return await embed_entities(payload.get("entity_ids") or [payload["entity_id"]])
210 +
211 +
212 +@handler("reprocess_snapshot")
213 +async def reprocess_snapshot(payload: dict[str, Any], job: dict[str, Any]) -> dict[str, Any] | None:
214 + from aiatlas.connectors import get
215 +
216 + connector = get(payload["connector"])
217 + ctx = await connector.run(reprocess=True, only_urls=[payload["url"]] if payload.get("url") else None, force=True)
218 + return {k: v for k, v in ctx.stats.__dict__.items() if k != "meta"}
219 +
220 +
221 +@handler("recompute_quality")
222 +async def recompute_quality(payload: dict[str, Any], job: dict[str, Any]) -> dict[str, Any] | None:
223 + from aiatlas.services.quality import recompute
224 +
225 + return await recompute(entity_ids=payload.get("entity_ids"))
226 +
227 +
228 +__all__ = ["llm_extract", "facts_from_llm", "embed_entity", "reprocess_snapshot", "recompute_quality"]
added src/aiatlas/services/jobs.py +124 −0
@@ -0,0 +1,124 @@
1 +"""Postgres-backed job queue (`jobs` table, `FOR UPDATE SKIP LOCKED`): priorities, retries with backoff, dead letters, batches.
2 +Local-first: no extra broker. Redis is used only for cross-process locks and caches."""
3 +from __future__ import annotations
4 +
5 +import asyncio
6 +import logging
7 +import socket
8 +import traceback
9 +from collections.abc import Awaitable, Callable
10 +from datetime import UTC, datetime, timedelta
11 +from typing import Any
12 +
13 +from sqlalchemy.ext.asyncio import AsyncConnection
14 +
15 +from aiatlas.config import settings
16 +from aiatlas.db import execute, fetch_all, fetch_one, jsonb, transaction
17 +from aiatlas.ids import new_id
18 +
19 +log = logging.getLogger(__name__)
20 +
21 +Handler = Callable[[dict[str, Any], dict[str, Any]], Awaitable[dict[str, Any] | None]]
22 +_HANDLERS: dict[str, Handler] = {}
23 +
24 +
25 +def handler(kind: str) -> Callable[[Handler], Handler]:
26 + def deco(fn: Handler) -> Handler:
27 + _HANDLERS[kind] = fn
28 + return fn
29 + return deco
30 +
31 +
32 +async def enqueue(conn: AsyncConnection, kind: str, payload: dict[str, Any], *, priority: int = 5, run_after: datetime | None = None,
33 + max_attempts: int = 3, batch_id: str | None = None, dedupe_key: str | None = None) -> str | None:
34 + jid = new_id("queue_job")
35 + row = await fetch_one(conn, """insert into jobs (id, kind, payload, priority, run_after, max_attempts, batch_id, dedupe_key)
36 + values (:id, :k, cast(:p as jsonb), :pr, :ra, :ma, :b, :d)
37 + on conflict (dedupe_key) where status in ('queued','running') do nothing returning id""",
38 + id=jid, k=kind, p=jsonb(payload), pr=priority, ra=run_after or datetime.now(UTC), ma=max_attempts, b=batch_id, d=dedupe_key)
39 + return row["id"] if row else None
40 +
41 +
42 +async def claim_next(conn: AsyncConnection, worker: str, kinds: list[str] | None = None) -> dict[str, Any] | None:
43 + kind_filter = "and kind = any(cast(:kinds as text[]))" if kinds else ""
44 + row = await fetch_one(conn, f"""with next as (
45 + select id from jobs where status = 'queued' and run_after <= now() {kind_filter}
46 + order by priority, run_after limit 1 for update skip locked)
47 + update jobs j set status = 'running', locked_by = :w, locked_at = now(), started_at = now(), attempts = attempts + 1
48 + from next where j.id = next.id returning j.*""", w=worker, kinds=kinds or [])
49 + return row
50 +
51 +
52 +async def complete(conn: AsyncConnection, job_id: str, result: dict[str, Any] | None = None) -> None:
53 + await execute(conn, "update jobs set status = 'done', finished_at = now(), error = null, payload = payload || cast(:r as jsonb) where id = :id",
54 + r=jsonb({"_result": result} if result else {}), id=job_id)
55 +
56 +
57 +async def fail(conn: AsyncConnection, job: dict[str, Any], error: str) -> None:
58 + dead = job["attempts"] >= job["max_attempts"]
59 + backoff = timedelta(seconds=min(3600, 30 * (3 ** max(0, job["attempts"] - 1))))
60 + await execute(conn, """update jobs set status = :st, finished_at = case when :dead then now() else null end, error = :e, locked_by = null, locked_at = null,
61 + run_after = case when :dead then run_after else now() + :backoff end where id = :id""",
62 + st="dead" if dead else "queued", dead=dead, e=error[:4000], backoff=backoff, id=job["id"])
63 +
64 +
65 +async def queue_depth(conn: AsyncConnection) -> dict[str, Any]:
66 + rows = await fetch_all(conn, "select kind, status, count(*) as n from jobs where status in ('queued','running','dead') or finished_at > now() - interval '1 day' group by 1, 2")
67 + out: dict[str, dict[str, int]] = {}
68 + for r in rows:
69 + out.setdefault(r["kind"], {})[r["status"]] = int(r["n"])
70 + return out
71 +
72 +
73 +async def run_worker(*, concurrency: int | None = None, kinds: list[str] | None = None, stop: asyncio.Event | None = None, idle_sleep: float = 3.0) -> None:
74 + """Long-running worker loop. Handlers are registered with `@handler(kind)` in `aiatlas.services.handlers`."""
75 + import aiatlas.services.handlers # noqa: F401 (registers handlers)
76 +
77 + worker = f"{socket.gethostname()}:{new_id('queue_job')[-6:]}"
78 + stop = stop or asyncio.Event()
79 + sem = asyncio.Semaphore(concurrency or settings.worker_concurrency)
80 + log.info("worker started", extra={"worker": worker, "kinds": kinds or "all"})
81 +
82 + async def one(job: dict[str, Any]) -> None:
83 + async with sem:
84 + fn = _HANDLERS.get(job["kind"])
85 + if fn is None:
86 + async with transaction() as conn:
87 + await fail(conn, {**job, "attempts": job["max_attempts"]}, f"no handler for {job['kind']}")
88 + return
89 + try:
90 + result = await fn(job["payload"], job)
91 + async with transaction() as conn:
92 + await complete(conn, job["id"], result)
93 + except Exception as exc: # noqa: BLE001
94 + log.warning("job failed", extra={"job": job["id"], "kind": job["kind"], "error": str(exc)})
95 + async with transaction() as conn:
96 + await fail(conn, job, f"{exc.__class__.__name__}: {exc}\n{traceback.format_exc()[-1500:]}")
97 +
98 + tasks: set[asyncio.Task[None]] = set()
99 + while not stop.is_set():
100 + if sem.locked():
101 + await asyncio.sleep(0.5)
102 + continue
103 + async with transaction() as conn:
104 + job = await claim_next(conn, worker, kinds)
105 + if job is None:
106 + try:
107 + await asyncio.wait_for(stop.wait(), timeout=idle_sleep)
108 + except TimeoutError:
109 + pass
110 + continue
111 + t = asyncio.create_task(one(job))
112 + tasks.add(t)
113 + t.add_done_callback(tasks.discard)
114 + if tasks:
115 + await asyncio.gather(*tasks, return_exceptions=True)
116 +
117 +
118 +async def requeue_stale(conn: AsyncConnection, *, older_than_minutes: int = 120) -> int:
119 + row = await fetch_one(conn, """with s as (update jobs set status = 'queued', locked_by = null, locked_at = null
120 + where status = 'running' and locked_at < now() - make_interval(mins => :m) returning 1) select count(*) as n from s""", m=older_than_minutes)
121 + return int(row["n"]) if row else 0
122 +
123 +
124 +__all__ = ["enqueue", "claim_next", "complete", "fail", "queue_depth", "run_worker", "handler", "requeue_stale"]
added src/aiatlas/services/llm/__init__.py +8 −0
@@ -0,0 +1,8 @@
1 +"""Local LLM factory gateway — an internal abstraction over interchangeable engines (MacLustr llm-api.io, any OpenAI-compatible
2 +server, llama.cpp, vLLM…). Callers ask for a *task* and a *stage*, never for a specific vendor model.
3 +
4 + result = await gateway.extract(task_type="model_passport", document=text, schema=ModelPassport, stage="medium")
5 +"""
6 +from aiatlas.services.llm.gateway import LLMGateway, LLMResult, LLMUnavailable, gateway
7 +
8 +__all__ = ["LLMGateway", "LLMResult", "LLMUnavailable", "gateway"]
added src/aiatlas/services/llm/gateway.py +231 −0
@@ -0,0 +1,231 @@
1 +"""LLM gateway: stage cascade (small → medium → large), OpenAI-compatible engine, strict JSON output validated by pydantic
2 +schemas, full cost accounting in `llm_jobs`. Deterministic processing always runs before any call here."""
3 +from __future__ import annotations
4 +
5 +import json
6 +import logging
7 +import re
8 +import socket
9 +import time
10 +from dataclasses import dataclass
11 +from typing import Any
12 +
13 +import httpx
14 +from pydantic import BaseModel, ValidationError
15 +
16 +from aiatlas.config import settings
17 +from aiatlas.db import execute, jsonb, transaction
18 +from aiatlas.ids import new_id
19 +
20 +log = logging.getLogger(__name__)
21 +
22 +STAGES = ("small", "medium", "large")
23 +
24 +
25 +class LLMUnavailable(Exception):
26 + pass
27 +
28 +
29 +@dataclass
30 +class LLMResult:
31 + ok: bool
32 + data: dict[str, Any] | None
33 + raw: str
34 + model: str
35 + stage: str
36 + input_tokens: int | None
37 + output_tokens: int | None
38 + duration_ms: int
39 + error: str | None = None
40 + llm_job_id: str | None = None
41 +
42 +
43 +class Engine:
44 + name = "null"
45 +
46 + async def complete(self, *, model: str, system: str, user: str, max_tokens: int, temperature: float, json_mode: bool) -> tuple[str, dict[str, Any]]:
47 + raise LLMUnavailable("no LLM engine configured")
48 +
49 + async def embed(self, *, model: str, texts: list[str]) -> list[list[float]]:
50 + raise LLMUnavailable("no embedding engine configured")
51 +
52 + async def health(self) -> bool:
53 + return False
54 +
55 +
56 +class OpenAICompatEngine(Engine):
57 + """Works with MacLustr llm-api.io, vLLM, llama.cpp server, Ollama (/v1), LM Studio…"""
58 +
59 + name = "openai_compat"
60 +
61 + def __init__(self, base_url: str, api_key: str, timeout_s: float):
62 + self.base_url = base_url.rstrip("/")
63 + self.api_key = api_key
64 + self.timeout_s = timeout_s
65 +
66 + def _client(self) -> httpx.AsyncClient:
67 + return httpx.AsyncClient(base_url=self.base_url, headers={"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"},
68 + timeout=httpx.Timeout(self.timeout_s, connect=30))
69 +
70 + async def complete(self, *, model: str, system: str, user: str, max_tokens: int, temperature: float, json_mode: bool) -> tuple[str, dict[str, Any]]:
71 + body: dict[str, Any] = {"model": model, "messages": [{"role": "system", "content": system}, {"role": "user", "content": user}],
72 + "max_tokens": max_tokens, "temperature": temperature, "stream": False}
73 + if json_mode:
74 + body["response_format"] = {"type": "json_object"}
75 + async with self._client() as client:
76 + r = await client.post("/chat/completions", json=body)
77 + if r.status_code == 400 and json_mode:
78 + body.pop("response_format")
79 + r = await client.post("/chat/completions", json=body)
80 + r.raise_for_status()
81 + data = r.json()
82 + choice = (data.get("choices") or [{}])[0]
83 + content = (choice.get("message") or {}).get("content") or ""
84 + return content, data.get("usage") or {}
85 +
86 + async def embed(self, *, model: str, texts: list[str]) -> list[list[float]]:
87 + async with self._client() as client:
88 + r = await client.post("/embeddings", json={"model": model, "input": texts})
89 + r.raise_for_status()
90 + data = r.json()
91 + items = sorted(data.get("data") or [], key=lambda d: d.get("index", 0))
92 + return [d["embedding"] for d in items]
93 +
94 + async def health(self) -> bool:
95 + try:
96 + async with self._client() as client:
97 + r = await client.get("/models", timeout=20)
98 + return r.status_code == 200
99 + except Exception: # noqa: BLE001
100 + return False
101 +
102 +
103 +SYSTEM_PROMPT = """You are the extraction engine of AI Atlas, a structured database of the AI ecosystem.
104 +Extract ONLY facts explicitly stated in the document. Never guess, never fill gaps from memory, never invent numbers or dates.
105 +If a field is not stated, use null. Quote units exactly as written. Prefer official statements over marketing phrasing.
106 +Return a single JSON object matching the requested schema and nothing else."""
107 +
108 +
109 +class LLMGateway:
110 + def __init__(self, engine: Engine | None = None):
111 + self.engine = engine or self._default_engine()
112 + self.models = {"small": settings.llm_small_model, "medium": settings.llm_medium_model, "large": settings.llm_large_model}
113 +
114 + @staticmethod
115 + def _default_engine() -> Engine:
116 + if settings.llm_available:
117 + return OpenAICompatEngine(settings.llm_base_url, settings.llm_api_key, settings.llm_timeout_s)
118 + return Engine()
119 +
120 + @property
121 + def available(self) -> bool:
122 + return self.engine.name != "null"
123 +
124 + async def health(self) -> dict[str, Any]:
125 + return {"engine": self.engine.name, "available": self.available, "reachable": await self.engine.health() if self.available else False,
126 + "models": self.models, "embedding_model": settings.embedding_model}
127 +
128 + async def extract(self, *, task_type: str, document: str, schema: type[BaseModel], stage: str = "medium", instructions: str = "",
129 + snapshot_id: str | None = None, entity_id: str | None = None, job_id: str | None = None, max_tokens: int = 2000,
130 + escalate_on_failure: bool = True, max_chars: int = 24000) -> LLMResult:
131 + if not self.available:
132 + raise LLMUnavailable("LLM engine not configured (AIA_LLM_BASE_URL / AIA_LLM_API_KEY)")
133 + if stage not in STAGES:
134 + raise ValueError(f"stage must be one of {STAGES}")
135 + doc = document if len(document) <= max_chars else document[:max_chars] + "\n…[truncated]"
136 + schema_json = json.dumps(schema.model_json_schema(), ensure_ascii=False)
137 + user = (f"TASK: {task_type}\n{instructions}\n\nJSON SCHEMA:\n{schema_json}\n\nDOCUMENT:\n<<<\n{doc}\n>>>\n\n"
138 + f"Return only the JSON object.")
139 + stages = STAGES[STAGES.index(stage):] if escalate_on_failure else (stage,)
140 + last: LLMResult | None = None
141 + for st in stages:
142 + model = self.models[st]
143 + t0 = time.perf_counter()
144 + error = None
145 + data: dict[str, Any] | None = None
146 + raw = ""
147 + usage: dict[str, Any] = {}
148 + status = "ok"
149 + try:
150 + raw, usage = await self.engine.complete(model=model, system=SYSTEM_PROMPT, user=user, max_tokens=max_tokens, temperature=0.0, json_mode=True)
151 + parsed = _parse_json(raw)
152 + if parsed is None:
153 + status, error = "invalid_json", "model did not return JSON"
154 + else:
155 + try:
156 + data = schema.model_validate(parsed).model_dump(mode="json")
157 + except ValidationError as ve:
158 + status, error = "schema_error", str(ve)[:2000]
159 + data = parsed # keep for debugging
160 + except Exception as exc: # noqa: BLE001
161 + status, error = "failed", f"{exc.__class__.__name__}: {exc}"[:2000]
162 + duration = int((time.perf_counter() - t0) * 1000)
163 + llm_job_id = await self._account(task_type=task_type, stage=st, model=model, schema_name=schema.__name__, snapshot_id=snapshot_id,
164 + entity_id=entity_id, job_id=job_id, usage=usage, duration=duration, status=status,
165 + output=data if status in ("ok", "schema_error") else None, error=error)
166 + last = LLMResult(ok=status == "ok", data=data if status == "ok" else None, raw=raw, model=model, stage=st, input_tokens=usage.get("prompt_tokens"),
167 + output_tokens=usage.get("completion_tokens"), duration_ms=duration, error=error, llm_job_id=llm_job_id)
168 + if last.ok or status == "failed":
169 + break # transport failures: do not escalate blindly (probably the server), schema errors: try the next stage
170 + assert last is not None
171 + return last
172 +
173 + async def classify(self, *, text: str, labels: list[str], task_type: str = "classify", snapshot_id: str | None = None) -> str | None:
174 + from pydantic import Field, create_model
175 +
176 + Model = create_model("Classification", label=(str, Field(description=f"one of: {', '.join(labels)}")), confidence=(float, Field(ge=0, le=1)))
177 + res = await self.extract(task_type=task_type, document=text[:6000], schema=Model, stage="small", snapshot_id=snapshot_id,
178 + instructions=f"Choose exactly one label among: {', '.join(labels)}.", max_tokens=100, escalate_on_failure=False)
179 + if res.ok and res.data and res.data.get("label") in labels:
180 + return str(res.data["label"])
181 + return None
182 +
183 + async def embed(self, texts: list[str]) -> list[list[float]]:
184 + if not self.available:
185 + raise LLMUnavailable("embedding engine not configured")
186 + t0 = time.perf_counter()
187 + vectors = await self.engine.embed(model=settings.embedding_model, texts=texts)
188 + await self._account(task_type="embed", stage="small", model=settings.embedding_model, schema_name=None, snapshot_id=None, entity_id=None,
189 + job_id=None, usage={"prompt_tokens": sum(len(t) // 4 for t in texts)}, duration=int((time.perf_counter() - t0) * 1000),
190 + status="ok", output=None, error=None)
191 + return vectors
192 +
193 + async def _account(self, *, task_type: str, stage: str, model: str, schema_name: str | None, snapshot_id: str | None, entity_id: str | None,
194 + job_id: str | None, usage: dict[str, Any], duration: int, status: str, output: dict[str, Any] | None, error: str | None) -> str:
195 + lid = new_id("llm_job")
196 + try:
197 + async with transaction() as conn:
198 + await execute(conn, """insert into llm_jobs (id, job_id, task_type, stage, engine, model, node, schema_name, snapshot_id, entity_id, input_tokens, output_tokens,
199 + duration_ms, status, output, error) values (:id, :j, :t, :st, :eng, :m, :node, :schema, :snap, :e, :it, :ot, :d, :status, cast(:o as jsonb), :err)""",
200 + id=lid, j=job_id, t=task_type, st=stage, eng=self.engine.name, m=model, node=socket.gethostname(), schema=schema_name, snap=snapshot_id,
201 + e=entity_id, it=usage.get("prompt_tokens"), ot=usage.get("completion_tokens"), d=duration, status=status,
202 + o=jsonb(output) if output is not None else None, err=error)
203 + except Exception as exc: # noqa: BLE001
204 + log.warning("llm accounting failed", extra={"error": str(exc)})
205 + return lid
206 +
207 +
208 +def _parse_json(raw: str) -> dict[str, Any] | None:
209 + s = raw.strip()
210 + s = re.sub(r"<think>.*?</think>", "", s, flags=re.S).strip()
211 + if s.startswith("```"):
212 + s = re.sub(r"^```(?:json)?\s*", "", s)
213 + s = re.sub(r"\s*```$", "", s)
214 + try:
215 + v = json.loads(s)
216 + return v if isinstance(v, dict) else None
217 + except json.JSONDecodeError:
218 + pass
219 + m = re.search(r"\{.*\}", s, flags=re.S)
220 + if m:
221 + try:
222 + v = json.loads(m.group(0))
223 + return v if isinstance(v, dict) else None
224 + except json.JSONDecodeError:
225 + return None
226 + return None
227 +
228 +
229 +gateway = LLMGateway()
230 +
231 +__all__ = ["LLMGateway", "LLMResult", "LLMUnavailable", "Engine", "OpenAICompatEngine", "gateway"]
added src/aiatlas/services/quality.py +72 −0
@@ -0,0 +1,72 @@
1 +"""Data quality engine — per-entity scores (documented, versioned). Not truth, just transparency:
2 +source_count · primary_source_ratio · freshness · field_completeness · agreement (1 − conflicts share) → score 0–100."""
3 +from __future__ import annotations
4 +
5 +from typing import Any
6 +
7 +from aiatlas.db import execute, fetch_all, jsonb, transaction
8 +
9 +QUALITY_VERSION = "1.0"
10 +
11 +EXPECTED_FIELDS: dict[str, list[str]] = {
12 + "model": ["release_date", "openness", "license", "parameter_count", "context_length", "modalities", "architecture", "official_url", "description"],
13 + "company": ["country", "founded", "website", "description", "headquarters"],
14 + "organization": ["country", "website", "description"],
15 + "paper": ["authors", "published_at", "abstract", "arxiv_id", "categories"],
16 + "provider": ["website", "description"],
17 + "benchmark": ["description", "metric", "category", "website"],
18 + "hardware": ["kind", "memory_gb", "memory_bandwidth_gbs", "release_date", "manufacturer"],
19 + "framework": ["repository_url", "latest_version", "license", "description", "language"],
20 + "dataset": ["license", "modality", "size", "publisher"],
21 + "tool": ["website", "category", "description"],
22 + "repository": ["repository_url", "license", "description", "language"],
23 +}
24 +
25 +METRIC_DEFINITIONS = [
26 + ("quality_score", "Data quality score", QUALITY_VERSION,
27 + "Composite 0–100 transparency score: 0.25·completeness + 0.25·primary_source_ratio + 0.2·freshness + 0.15·agreement + 0.15·source_diversity. "
28 + "It measures how well AI Atlas knows an entity, not how good the entity is.",
29 + "score = 100·(0.25·completeness + 0.25·primary_ratio + 0.20·freshness + 0.15·agreement + 0.15·min(1, sources/4))"),
30 + ("freshness", "Freshness", QUALITY_VERSION, "1 when the entity was confirmed by a source in the last 7 days, decaying linearly to 0 at 180 days.", None),
31 + ("completeness", "Field completeness", QUALITY_VERSION, "Share of the expected fields for the entity type that have a current claim.", None),
32 + ("primary_source_ratio", "Primary source ratio", QUALITY_VERSION, "Share of current claims backed by a tier-1 (official) source.", None),
33 +]
34 +
35 +
36 +async def recompute(*, entity_ids: list[str] | None = None, limit: int = 20000) -> dict[str, Any]:
37 + async with transaction() as conn:
38 + for key, label, version, desc, formula in METRIC_DEFINITIONS:
39 + await execute(conn, """insert into metric_definitions (key, label, version, description, formula) values (:k, :l, :v, :d, :f)
40 + on conflict (key) do update set label = excluded.label, version = excluded.version, description = excluded.description, formula = excluded.formula""",
41 + k=key, l=label, v=version, d=desc, f=formula)
42 + where = "where e.merged_into is null" + (" and e.id = any(cast(:ids as text[]))" if entity_ids else "")
43 + rows = await fetch_all(conn, f"""
44 + select e.id, e.entity_type, e.attributes, e.last_seen_at, coalesce((e.quality->>'conflicts')::int, 0) as conflicts,
45 + (select count(distinct c.source_id) from claims c where c.entity_id = e.id and c.status = 'current') as source_count,
46 + (select count(*) from claims c where c.entity_id = e.id and c.status = 'current') as claim_count,
47 + (select count(*) from claims c where c.entity_id = e.id and c.status = 'current' and c.tier = 1) as primary_count,
48 + (select count(*) from relations r where (r.subject_id = e.id or r.object_id = e.id) and r.valid_to is null) as relation_count,
49 + (select count(*) from change_events ev where ev.entity_id = e.id) as event_count,
50 + extract(epoch from now() - e.last_seen_at) / 86400.0 as age_days
51 + from entities e {where} order by e.updated_at desc limit :lim""", ids=entity_ids or [], lim=limit)
52 + updated = 0
53 + for r in rows:
54 + expected = EXPECTED_FIELDS.get(r["entity_type"], ["description"])
55 + attrs = r["attributes"] or {}
56 + completeness = sum(1 for f in expected if attrs.get(f) not in (None, "", [], {})) / max(1, len(expected))
57 + primary_ratio = (r["primary_count"] / r["claim_count"]) if r["claim_count"] else 0.0
58 + age = float(r["age_days"] or 0)
59 + freshness = 1.0 if age <= 7 else max(0.0, 1 - (age - 7) / 173)
60 + agreement = max(0.0, 1 - (r["conflicts"] / max(1, r["claim_count"]))) if r["claim_count"] else 1.0
61 + diversity = min(1.0, (r["source_count"] or 0) / 4)
62 + score = round(100 * (0.25 * completeness + 0.25 * primary_ratio + 0.20 * freshness + 0.15 * agreement + 0.15 * diversity))
63 + quality = {"version": QUALITY_VERSION, "score": score, "completeness": round(completeness, 3), "primary_source_ratio": round(primary_ratio, 3),
64 + "freshness": round(freshness, 3), "agreement": round(agreement, 3), "source_count": int(r["source_count"] or 0),
65 + "claim_count": int(r["claim_count"] or 0), "conflicts": int(r["conflicts"] or 0)}
66 + counts = {"relations": int(r["relation_count"] or 0), "events": int(r["event_count"] or 0), "claims": int(r["claim_count"] or 0)}
67 + await execute(conn, "update entities set quality = quality || cast(:q as jsonb), counts = cast(:c as jsonb) where id = :id", q=jsonb(quality), c=jsonb(counts), id=r["id"])
68 + updated += 1
69 + return {"updated": updated}
70 +
71 +
72 +__all__ = ["recompute", "QUALITY_VERSION", "EXPECTED_FIELDS"]
added src/aiatlas/services/scheduler.py +119 −0
@@ -0,0 +1,119 @@
1 +"""Scheduler process (`aia schedule`): runs due connectors (adaptive intervals, Redis lock per connector), the job worker,
2 +hourly stats/quality, embedding backlog, nightly backup. One process per node is enough; several nodes cooperate via locks."""
3 +from __future__ import annotations
4 +
5 +import asyncio
6 +import logging
7 +import signal
8 +from datetime import UTC, datetime
9 +
10 +from apscheduler.schedulers.asyncio import AsyncIOScheduler
11 +from apscheduler.triggers.cron import CronTrigger
12 +
13 +from aiatlas.config import settings
14 +from aiatlas.connectors import get, registry
15 +from aiatlas.db import execute, fetch_all, transaction
16 +from aiatlas.services import cache
17 +from aiatlas.services.jobs import enqueue, requeue_stale, run_worker
18 +
19 +log = logging.getLogger(__name__)
20 +
21 +_running: set[str] = set()
22 +
23 +
24 +async def run_connector(name: str, *, force: bool = False) -> None:
25 + if name in _running:
26 + return
27 + _running.add(name)
28 + try:
29 + async with cache.lock(f"connector:{name}", ttl_s=4 * 3600) as ok:
30 + if not ok:
31 + log.info("connector locked elsewhere", extra={"connector": name})
32 + return
33 + try:
34 + await get(name).run(force=force)
35 + except Exception as exc: # noqa: BLE001
36 + log.warning("connector run failed", extra={"connector": name, "error": str(exc)})
37 + await cache.cache_invalidate()
38 + finally:
39 + _running.discard(name)
40 +
41 +
42 +async def tick() -> None:
43 + async with transaction() as conn:
44 + due = await fetch_all(conn, """select name from connectors where enabled and (next_run_at is null or next_run_at <= now())
45 + and (circuit_open_until is null or circuit_open_until <= now()) order by priority, coalesce(next_run_at, 'epoch') limit 6""")
46 + known = registry()
47 + names = [r["name"] for r in due if r["name"] in known and r["name"] not in _running]
48 + if names:
49 + log.info("due connectors", extra={"connectors": names})
50 + await asyncio.gather(*(run_connector(n) for n in names[:3]))
51 + await cache.heartbeat("scheduler", {"at": datetime.now(UTC).isoformat(), "running": sorted(_running), "due": names})
52 +
53 +
54 +async def hourly() -> None:
55 + from aiatlas.services.quality import recompute
56 + from aiatlas.services.stats import compute_stats
57 +
58 + async with cache.lock("hourly", ttl_s=3000) as ok:
59 + if not ok:
60 + return
61 + try:
62 + await compute_stats()
63 + await recompute(limit=5000)
64 + async with transaction() as conn:
65 + n = await requeue_stale(conn)
66 + if n:
67 + log.info("requeued stale jobs", extra={"n": n})
68 + if settings.llm_available:
69 + from aiatlas.services.embeddings import pending_entity_ids
70 +
71 + ids = await pending_entity_ids(limit=400)
72 + if ids:
73 + async with transaction() as conn:
74 + for i in range(0, len(ids), 50):
75 + await enqueue(conn, "embed_entity", {"entity_ids": ids[i:i + 50]}, priority=8, dedupe_key=f"embed:{ids[i]}")
76 + await cache.cache_invalidate()
77 + except Exception as exc: # noqa: BLE001
78 + log.warning("hourly maintenance failed", extra={"error": str(exc)})
79 +
80 +
81 +async def nightly_backup() -> None:
82 + from aiatlas.services.backup import backup_database
83 +
84 + async with cache.lock("backup", ttl_s=3600) as ok:
85 + if ok:
86 + try:
87 + path = await asyncio.to_thread(backup_database)
88 + log.info("backup done", extra={"path": str(path)})
89 + except Exception as exc: # noqa: BLE001
90 + log.error("backup failed", extra={"error": str(exc)})
91 +
92 +
93 +async def main(*, with_worker: bool = True) -> None:
94 + settings.ensure_dirs()
95 + stop = asyncio.Event()
96 + loop = asyncio.get_running_loop()
97 + for sig in (signal.SIGINT, signal.SIGTERM):
98 + try:
99 + loop.add_signal_handler(sig, stop.set)
100 + except NotImplementedError:
101 + pass
102 + scheduler = AsyncIOScheduler(timezone="UTC")
103 + scheduler.add_job(tick, "interval", seconds=settings.scheduler_tick_s, max_instances=1, coalesce=True, id="tick")
104 + scheduler.add_job(hourly, "interval", minutes=60, max_instances=1, coalesce=True, id="hourly", next_run_time=datetime.now(UTC))
105 + minute, hour, *_ = settings.backup_cron.split()
106 + scheduler.add_job(nightly_backup, CronTrigger(minute=minute, hour=hour, timezone=settings.tz), id="backup")
107 + scheduler.start()
108 + log.info("scheduler started", extra={"tick_s": settings.scheduler_tick_s, "connectors": len(registry()), "worker": with_worker})
109 + async with transaction() as conn:
110 + await execute(conn, "update connectors set health = 'disabled' where not enabled")
111 + worker_task = asyncio.create_task(run_worker(stop=stop)) if with_worker else None
112 + await stop.wait()
113 + scheduler.shutdown(wait=False)
114 + if worker_task:
115 + await worker_task
116 + await cache.close()
117 +
118 +
119 +__all__ = ["main", "tick", "run_connector", "hourly"]
added src/aiatlas/services/search.py +156 −0
@@ -0,0 +1,156 @@
1 +"""Search: Postgres FTS + trigram (+ pgvector when embeddings exist) and a deterministic natural-language → filter compiler.
2 +
3 + "open models released in 2026 with more than 100B parameters and 128k context"
4 + → {entity_type: model, openness: open, year_from: 2026, params_min: 1e11, context_min: 128000}
5 +"""
6 +from __future__ import annotations
7 +
8 +import re
9 +from dataclasses import dataclass, field
10 +from typing import Any
11 +
12 +from sqlalchemy.ext.asyncio import AsyncConnection
13 +
14 +from aiatlas.db import fetch_all
15 +from aiatlas.sdk.extract.numbers import parse_context_length, parse_param_count
16 +
17 +TYPE_WORDS = {
18 + "model": ("model", "models", "llm", "llms", "language model"), "company": ("company", "companies", "startup", "startups", "lab", "labs", "organization"),
19 + "paper": ("paper", "papers", "research", "publication", "preprint", "arxiv"), "provider": ("provider", "providers", "inference provider", "api provider"),
20 + "benchmark": ("benchmark", "benchmarks", "leaderboard", "eval", "evals"), "hardware": ("gpu", "gpus", "chip", "chips", "hardware", "accelerator", "npu", "tpu"),
21 + "framework": ("framework", "frameworks", "library", "libraries", "runtime", "runtimes"), "dataset": ("dataset", "datasets"),
22 + "tool": ("tool", "tools", "agent", "agents", "app", "application"), "repository": ("repo", "repos", "repository", "repositories"),
23 +}
24 +MODALITY_WORDS = {"vision": "image", "multimodal": "multimodal", "image": "image", "audio": "audio", "speech": "audio", "video": "video", "code": "code",
25 + "coding": "code", "embedding": "embedding", "embeddings": "embedding"}
26 +
27 +
28 +@dataclass
29 +class Query:
30 + text: str = ""
31 + entity_type: str | None = None
32 + openness: str | None = None
33 + year_from: int | None = None
34 + year_to: int | None = None
35 + params_min: int | None = None
36 + params_max: int | None = None
37 + context_min: int | None = None
38 + modalities: list[str] = field(default_factory=list)
39 + organization: str | None = None
40 + filters: dict[str, Any] = field(default_factory=dict)
41 +
42 + def as_dict(self) -> dict[str, Any]:
43 + return {k: v for k, v in self.__dict__.items() if v not in (None, "", [], {})}
44 +
45 +
46 +def compile_query(q: str) -> Query:
47 + s = q.strip()
48 + low = f" {s.lower()} "
49 + out = Query(text=s)
50 + for etype, words in TYPE_WORDS.items():
51 + if any(f" {w} " in low for w in words):
52 + out.entity_type = etype
53 + break
54 + if re.search(r"\b(open[- ]?(weight|weights|source)|open models?)\b", low):
55 + out.openness = "open"
56 + elif re.search(r"\b(proprietary|closed)\b", low):
57 + out.openness = "proprietary"
58 + m = re.search(r"\b(?:released|launched|published|from|since|after|in)\s+(20\d\d)\b", low)
59 + if m:
60 + out.year_from = int(m.group(1))
61 + if re.search(r"\bin\s+" + m.group(1), low):
62 + out.year_to = out.year_from
63 + m = re.search(r"\b(?:before|until)\s+(20\d\d)\b", low)
64 + if m:
65 + out.year_to = int(m.group(1))
66 + m = re.search(r"(?:more than|over|above|>|at least|)\s*(\d+(?:\.\d+)?\s*[bBmMtT])\b(?:\s*param)?", s)
67 + if m:
68 + out.params_min = parse_param_count(m.group(1) + " params")
69 + m = re.search(r"(?:less than|under|below|<|at most|)\s*(\d+(?:\.\d+)?\s*[bBmMtT])\b", s)
70 + if m:
71 + out.params_max = parse_param_count(m.group(1) + " params")
72 + m = re.search(r"(?:context|ctx)\s*(?:window\s*)?(?:>|over|above|of at least|at least|)?\s*(\d+\s*[kKmM])", s) or \
73 + re.search(r"(\d+\s*[kKmM])\s*(?:\+\s*)?(?:token\s*)?context", s)
74 + if m:
75 + out.context_min = parse_context_length(m.group(1))
76 + for w, mod in MODALITY_WORDS.items():
77 + if f" {w} " in low and mod not in out.modalities:
78 + out.modalities.append(mod)
79 + m = re.search(r"\b(?:by|from)\s+([A-Z][\w.&-]+(?:\s+[A-Z][\w.&-]+)?)", s)
80 + if m:
81 + out.organization = m.group(1)
82 + # residual free-text (remove the structured bits)
83 + residual = re.sub(r"\b(more than|over|above|less than|under|below|at least|at most|released|launched|published|since|after|before|until|with|and|in|from|by|the|a|an|context|window|params?|parameters)\b", " ", s, flags=re.I)
84 + residual = re.sub(r"\d+(?:\.\d+)?\s*[bBmMkKtT]\b|\b20\d\d\b|[<>≤≥]", " ", residual)
85 + for words in TYPE_WORDS.values():
86 + for w in words:
87 + residual = re.sub(rf"\b{re.escape(w)}\b", " ", residual, flags=re.I)
88 + residual = re.sub(r"\b(open[- ]?(weight|weights|source)|proprietary|closed)\b", " ", residual, flags=re.I)
89 + out.filters["residual"] = " ".join(residual.split())
90 + return out
91 +
92 +
93 +async def search_entities(conn: AsyncConnection, q: Query, *, limit: int = 30, offset: int = 0, embedding: list[float] | None = None) -> list[dict[str, Any]]:
94 + where = ["e.merged_into is null"]
95 + params: dict[str, Any] = {"limit": limit, "offset": offset}
96 + if q.entity_type:
97 + where.append("e.entity_type = :etype")
98 + params["etype"] = q.entity_type
99 + if q.openness == "open":
100 + where.append("(e.attributes->>'openness' in ('open-weights','open-source','open') or e.attributes->>'weights_availability' = 'open')")
101 + elif q.openness == "proprietary":
102 + where.append("e.attributes->>'openness' in ('proprietary','closed')")
103 + if q.year_from:
104 + where.append("left(e.attributes->>'release_date', 4) >= :yf")
105 + params["yf"] = str(q.year_from)
106 + if q.year_to:
107 + where.append("left(e.attributes->>'release_date', 4) <= :yt")
108 + params["yt"] = str(q.year_to)
109 + if q.params_min:
110 + where.append("(e.attributes->>'parameter_count')::double precision >= :pmin")
111 + params["pmin"] = float(q.params_min)
112 + if q.params_max:
113 + where.append("(e.attributes->>'parameter_count')::double precision <= :pmax")
114 + params["pmax"] = float(q.params_max)
115 + if q.context_min:
116 + where.append("(e.attributes->>'context_length')::double precision >= :cmin")
117 + params["cmin"] = float(q.context_min)
118 + for i, mod in enumerate(q.modalities):
119 + where.append(f"e.attributes->'modalities' ? :mod{i}")
120 + params[f"mod{i}"] = mod
121 + if q.organization:
122 + where.append("exists (select 1 from entities o where o.id = e.organization_id and o.canonical_name ilike :org)")
123 + params["org"] = f"%{q.organization}%"
124 + text = (q.filters.get("residual") or "").strip() or ("" if any([q.entity_type, q.openness, q.year_from, q.params_min, q.context_min, q.modalities]) else q.text)
125 + rank = "coalesce((e.quality->>'score')::float, 0) / 100.0"
126 + if text:
127 + params["q"] = text
128 + params["qlike"] = f"%{text}%"
129 + params["qprefix"] = " & ".join(f"{w}:*" for w in re.findall(r"\w+", text)[:8]) or text
130 + where.append("(e.search @@ to_tsquery('simple', :qprefix) or e.canonical_name ilike :qlike or e.canonical_name % :q "
131 + "or exists (select 1 from entity_aliases a where a.entity_id = e.id and a.alias ilike :qlike))")
132 + rank = ("(ts_rank_cd(e.search, to_tsquery('simple', :qprefix)) * 2 + similarity(e.canonical_name, :q) * 3 "
133 + "+ case when e.canonical_name ilike :qlike then 1 else 0 end + coalesce((e.quality->>'score')::float, 0) / 200.0 "
134 + "+ case e.entity_type when 'model' then 0.3 when 'company' then 0.3 when 'provider' then 0.2 else 0 end)")
135 + if embedding is not None:
136 + params["vec"] = "[" + ",".join(f"{x:.6f}" for x in embedding) + "]"
137 + rank = f"({rank}) + coalesce(1 - (x.embedding <=> cast(:vec as vector)), 0) * 2"
138 + join = "left join entity_embeddings x on x.entity_id = e.id"
139 + else:
140 + join = ""
141 + sql = f"""select e.id, e.entity_type, e.canonical_name, e.slug, left(e.description, 240) as description, e.status, e.attributes, e.quality,
142 + o.canonical_name as organization_name, o.slug as organization_slug, {rank} as rank
143 + from entities e left join entities o on o.id = e.organization_id {join}
144 + where {' and '.join(where)} order by rank desc, e.updated_at desc limit :limit offset :offset"""
145 + return await fetch_all(conn, sql, **params)
146 +
147 +
148 +async def suggest(conn: AsyncConnection, prefix: str, *, limit: int = 8) -> list[dict[str, Any]]:
149 + return await fetch_all(conn, """select e.id, e.entity_type, e.canonical_name, e.slug, o.canonical_name as organization_name
150 + from entities e left join entities o on o.id = e.organization_id
151 + where e.merged_into is null and (e.canonical_name ilike :p or exists (select 1 from entity_aliases a where a.entity_id = e.id and a.alias ilike :p))
152 + order by case e.entity_type when 'model' then 0 when 'company' then 1 when 'provider' then 2 else 3 end,
153 + coalesce((e.quality->>'score')::float, 0) desc, length(e.canonical_name) limit :n""", p=f"{prefix}%", n=limit)
154 +
155 +
156 +__all__ = ["Query", "compile_query", "search_entities", "suggest"]
added src/aiatlas/services/stats.py +53 −0
@@ -0,0 +1,53 @@
1 +"""Live counters and aggregate statistics — always computed from the database, never hardcoded."""
2 +from __future__ import annotations
3 +
4 +from typing import Any
5 +
6 +from sqlalchemy.ext.asyncio import AsyncConnection
7 +
8 +from aiatlas.db import execute, fetch_all, fetch_one, jsonb, transaction
9 +from aiatlas.sdk.archive import archive_size
10 +
11 +
12 +async def live_counts(conn: AsyncConnection) -> dict[str, Any]:
13 + by_type = await fetch_all(conn, "select entity_type, count(*) as n from entities where merged_into is null group by 1")
14 + counts = {r["entity_type"]: int(r["n"]) for r in by_type}
15 + infra = await fetch_one(conn, """select (select count(*) from sources where enabled) as sources,
16 + (select count(*) from connectors) as connectors,
17 + (select count(*) from connectors where enabled) as connectors_enabled,
18 + (select count(*) from documents) as documents,
19 + (select count(*) from snapshots) as snapshots,
20 + (select count(*) from claims) as claims,
21 + (select count(*) from claims where status = 'current') as claims_current,
22 + (select count(*) from relations where valid_to is null) as relations,
23 + (select count(*) from change_events) as change_events,
24 + (select count(*) from change_events where observed_at > now() - interval '24 hours') as change_events_24h,
25 + (select count(*) from change_events where observed_at > now() - interval '7 days') as change_events_7d,
26 + (select count(*) from benchmark_results where valid_to is null) as benchmark_results,
27 + (select count(*) from prices where valid_to is null) as prices_current,
28 + (select count(*) from prices) as prices_total,
29 + (select count(*) from jobs where status = 'queued') as jobs_queued,
30 + (select count(*) from jobs where status = 'dead') as jobs_dead,
31 + (select count(*) from review_queue where status = 'pending') as review_pending,
32 + (select count(*) from llm_jobs) as llm_jobs,
33 + (select coalesce(sum(input_tokens),0) + coalesce(sum(output_tokens),0) from llm_jobs) as llm_tokens,
34 + (select max(observed_at) from snapshots) as last_snapshot_at,
35 + (select max(observed_at) from change_events) as last_event_at,
36 + (select min(first_seen_at) from entities) as first_entity_at""")
37 + return {"entities": counts, "entities_total": sum(counts.values()), **{k: (int(v) if isinstance(v, int) else v) for k, v in (infra or {}).items()}}
38 +
39 +
40 +async def compute_stats() -> dict[str, Any]:
41 + async with transaction() as conn:
42 + counts = await live_counts(conn)
43 + counts["archive"] = archive_size()
44 + await execute(conn, "insert into stats_snapshots (counts) values (cast(:c as jsonb))", c=jsonb(counts))
45 + return counts
46 +
47 +
48 +async def history(conn: AsyncConnection, days: int = 90) -> list[dict[str, Any]]:
49 + return await fetch_all(conn, """select distinct on (date_trunc('day', computed_at)) date_trunc('day', computed_at) as day, counts
50 + from stats_snapshots where computed_at > now() - make_interval(days => :d) order by 1 desc, computed_at desc""", d=days)
51 +
52 +
53 +__all__ = ["live_counts", "compute_stats", "history"]
added tests/__init__.py +0 −0
added tests/conftest.py +47 −0
@@ -0,0 +1,47 @@
1 +"""Shared test helpers. Connector tests never hit the network: they replay fixtures through `extract_from_fixture`."""
2 +from __future__ import annotations
3 +
4 +from datetime import UTC, datetime
5 +from pathlib import Path
6 +
7 +import pytest
8 +
9 +from aiatlas.sdk.connector import BaseConnector, RunContext
10 +from aiatlas.sdk.facts import Facts, Target
11 +from aiatlas.sdk.fetch import file_result
12 +
13 +FIXTURES = Path(__file__).parent / "fixtures"
14 +
15 +
16 +def fixture_path(*parts: str) -> Path:
17 + return FIXTURES.joinpath(*parts)
18 +
19 +
20 +async def extract_from_fixture(connector: BaseConnector, target: Target, path: Path, *, content_type: str = "text/html") -> Facts:
21 + """Parse a saved response and run the connector's extract() — no database, no network."""
22 + ctx = RunContext(run_id="test", connector=connector, fetcher=None, started_at=datetime.now(UTC)) # type: ignore[arg-type]
23 + res = file_result(str(path), url=target.url, content_type=content_type)
24 + parsed = connector.parse(target, res)
25 + facts = await connector.extract(ctx, target, res, parsed)
26 + return facts or Facts()
27 +
28 +
29 +@pytest.fixture
30 +def fixtures() -> Path:
31 + return FIXTURES
32 +
33 +
34 +def claims_of(facts: Facts, entity_name: str) -> dict[str, object]:
35 + """{property: value} for one entity (from Facts.claims and EntityRef.attributes)."""
36 + out: dict[str, object] = {}
37 + for e in facts.entities:
38 + if e.name == entity_name:
39 + out.update(e.attributes)
40 + for c in facts.claims:
41 + if c.entity.name == entity_name:
42 + out[c.property] = c.value
43 + return out
44 +
45 +
46 +def entity_names(facts: Facts, entity_type: str) -> set[str]:
47 + return {e.name for e in facts.entities if e.entity_type == entity_type}
added tests/fixtures/anthropic/model-deprecations.md +223 −0
@@ -0,0 +1,223 @@
1 +---
2 +title: Model deprecations
3 +url: https://platform.claude.com/docs/en/about-claude/model-deprecations
4 +description: See which Claude models are active, deprecated, or retired, and find retirement dates and recommended replacements for models and API parameters.
5 +---
6 +
7 +As safer and more capable models launch, Anthropic regularly retires older ones. Applications relying on Anthropic models may need occasional updates to keep working. Impacted customers will always be notified by email and in the documentation.
8 +
9 +This page lists all API deprecations, along with recommended replacements.
10 +
11 +## Overview
12 +
13 +Anthropic uses the following terms to describe the model lifecycle:
14 +
15 +* **Active:** The model is fully supported and recommended for use.
16 +* **Legacy:** The model will no longer receive updates and may be deprecated in the future.
17 +* **Deprecated:** The model is still functional but no longer recommended. Anthropic provides a recommended replacement and assigns a retirement date.
18 +* **Retired:** The model is no longer available for use. Requests to retired models will fail.
19 +
20 +<Warning>
21 + Deprecated models are likely to be less reliable than active models. Move workloads to active models to maintain the highest level of support and reliability.
22 +</Warning>
23 +
24 +The dates on this page apply to Anthropic-operated platforms: the Claude API, [Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws), and [Microsoft Foundry](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry). Partner-operated platforms (Amazon Bedrock and Google Cloud) set their own retirement schedules, so a model's lifecycle status and dates can differ. See the [Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock#supported-models), [Amazon Bedrock (Opus 4.6 and earlier)](https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy#api-model-ids), and [Google Cloud](https://platform.claude.com/docs/en/build-with-claude/claude-on-vertex-ai#api-model-ids) model tables.
25 +
26 +## Migrating to replacements
27 +
28 +Once a model is deprecated, migrate all usage to a suitable replacement before the retirement date. Requests to models past the retirement date will fail.
29 +
30 +To help measure the performance of replacement models on your tasks, consider thorough testing of your applications with the new models well before the retirement date.
31 +
32 +For specific instructions on migrating to the latest Claude models, see the [Migration guide](https://platform.claude.com/docs/en/about-claude/models/migration-guide).
33 +
34 +## Notifications
35 +
36 +Anthropic notifies customers with active deployments for models with upcoming retirements, providing at least 60 days' notice before model retirement for publicly released models.
37 +
38 +## Auditing model usage
39 +
40 +To help identify usage of deprecated models, customers can access an audit of their API usage. Follow these steps:
41 +
42 +1. Go to the [Usage](https://platform.claude.com/usage) page in Claude Console.
43 +2. Click **Export**.
44 +3. Review the downloaded CSV to see usage broken down by API key and model.
45 +
46 +This audit will help you locate any instances where your application is still using deprecated models, allowing you to prioritize updates to newer models before the retirement date.
47 +
48 +## Best practices
49 +
50 +1. Regularly check the documentation for updates on model deprecations.
51 +2. Test your applications with newer models well before the retirement date of your current model.
52 +3. Update your code to use the recommended replacement model as soon as possible.
53 +4. Contact the support team if you need assistance with migration or have any questions.
54 +
55 +## Deprecation downsides and mitigations
56 +
57 +Anthropic currently deprecates and retires models to ensure capacity for new model releases. This comes with downsides:
58 +
59 +* Users who value specific models must migrate to new versions
60 +* Researchers lose access to models for ongoing and comparative studies
61 +* Model retirement introduces safety- and model welfare-related risks
62 +
63 +At some point, Anthropic hopes to make past models publicly available again. In the meantime, Anthropic has committed to long-term preservation of model weights and other measures to help mitigate these impacts. For more details, see [Commitments on Model Deprecation and Preservation](https://www.anthropic.com/research/deprecation-commitments).
64 +
65 +## Model status
66 +
67 +<Note>
68 + [Claude Mythos Preview](https://anthropic.com/glasswing) (`claude-mythos-preview`) is deprecated. To migrate to [Claude Mythos 5](https://anthropic.com/glasswing) (`claude-mythos-5`), see the [migration guide](https://platform.claude.com/docs/en/models/fable-5/migration-guide#migrating-from-claude-mythos-preview).
69 +</Note>
70 +
71 +Current and recently retired models are listed in the following table with their status:
72 +
73 +| API model name | Current state | Deprecated | Tentative retirement date |
74 +| -------------------------- | ------------- | ----------------- | ---------------------------------- |
75 +| claude-fable-5-1 | Active | N/A | Not sooner than September 1, 2027 |
76 +| claude-fable-5 | Active | N/A | Not sooner than June 9, 2027 |
77 +| claude-opus-5 | Active | N/A | Not sooner than July 24, 2027 |
78 +| claude-opus-4-8 | Active | N/A | Not sooner than May 28, 2027 |
79 +| claude-opus-4-7 | Active | N/A | Not sooner than April 16, 2027 |
80 +| claude-opus-4-6 | Active | N/A | Not sooner than February 5, 2027 |
81 +| claude-opus-4-5-20251101 | Active | N/A | Not sooner than November 24, 2026 |
82 +| claude-opus-4-1-20250805 | Retired | June 5, 2026 | August 5, 2026 |
83 +| claude-opus-4-20250514 | Retired | April 14, 2026 | June 15, 2026 |
84 +| claude-sonnet-5 | Active | N/A | Not sooner than June 30, 2027 |
85 +| claude-sonnet-4-6 | Active | N/A | Not sooner than February 17, 2027 |
86 +| claude-sonnet-4-5-20250929 | Active | N/A | Not sooner than September 29, 2026 |
87 +| claude-sonnet-4-20250514 | Retired | April 14, 2026 | June 15, 2026 |
88 +| claude-3-7-sonnet-20250219 | Retired | October 28, 2025 | February 19, 2026 |
89 +| claude-haiku-4-5-20251001 | Active | N/A | Not sooner than October 15, 2026 |
90 +| claude-3-5-haiku-20241022 | Retired | December 19, 2025 | February 19, 2026 |
91 +| claude-3-haiku-20240307 | Retired | February 19, 2026 | April 20, 2026 |
92 +
93 +## Deprecation history
94 +
95 +All deprecations are listed in the following sections, with the most recent announcements first.
96 +
97 +### 2026-06-05: Claude Opus 4.1 model
98 +
99 +<Note>
100 + This model was retired August 5, 2026.
101 +</Note>
102 +
103 +On June 5, 2026, Anthropic notified developers using Claude Opus 4.1 of its upcoming retirement on the Claude API.
104 +
105 +| Retirement date | Deprecated model | Recommended replacement |
106 +| --------------- | -------------------------- | ----------------------- |
107 +| August 5, 2026 | `claude-opus-4-1-20250805` | `claude-opus-4-8` |
108 +
109 +### 2026-04-14: Claude Sonnet 4 and Claude Opus 4 models
110 +
111 +<Note>
112 + These models were retired June 15, 2026.
113 +</Note>
114 +
115 +On April 14, 2026, Anthropic notified developers using Claude Sonnet 4 and Claude Opus 4 models of their upcoming retirement on the Claude API.
116 +
117 +| Retirement date | Deprecated model | Recommended replacement |
118 +| --------------- | -------------------------- | ----------------------- |
119 +| June 15, 2026 | `claude-sonnet-4-20250514` | `claude-sonnet-4-6` |
120 +| June 15, 2026 | `claude-opus-4-20250514` | `claude-opus-4-8` |
121 +
122 +### 2026-02-19: Claude Haiku 3 model
123 +
124 +<Note>
125 + This model was retired April 20, 2026.
126 +</Note>
127 +
128 +On February 19, 2026, Anthropic notified developers using Claude Haiku 3 model of its upcoming retirement on the Claude API.
129 +
130 +| Retirement date | Deprecated model | Recommended replacement |
131 +| --------------- | ------------------------- | --------------------------- |
132 +| April 20, 2026 | `claude-3-haiku-20240307` | `claude-haiku-4-5-20251001` |
133 +
134 +### 2025-12-19: Claude Haiku 3.5 model
135 +
136 +<Note>
137 + This model was retired February 19, 2026.
138 +</Note>
139 +
140 +On December 19, 2025, Anthropic notified developers using Claude Haiku 3.5 model of its upcoming retirement on the Claude API.
141 +
142 +| Retirement date | Deprecated model | Recommended replacement |
143 +| ----------------- | --------------------------- | --------------------------- |
144 +| February 19, 2026 | `claude-3-5-haiku-20241022` | `claude-haiku-4-5-20251001` |
145 +
146 +### 2025-10-28: Claude Sonnet 3.7 model
147 +
148 +<Note>
149 + This model was retired February 19, 2026.
150 +</Note>
151 +
152 +On October 28, 2025, Anthropic notified developers using Claude Sonnet 3.7 model of its upcoming retirement on the Claude API.
153 +
154 +| Retirement date | Deprecated model | Recommended replacement |
155 +| ----------------- | ---------------------------- | ----------------------- |
156 +| February 19, 2026 | `claude-3-7-sonnet-20250219` | `claude-sonnet-4-6` |
157 +
158 +### 2025-08-13: Claude Sonnet 3.5 models
159 +
160 +<Note>
161 + These models were retired October 28, 2025.
162 +</Note>
163 +
164 +On August 13, 2025, Anthropic notified developers using Claude Sonnet 3.5 models of their upcoming retirement.
165 +
166 +| Retirement date | Deprecated model | Recommended replacement |
167 +| ---------------- | ---------------------------- | ----------------------- |
168 +| October 28, 2025 | `claude-3-5-sonnet-20240620` | `claude-sonnet-4-6` |
169 +| October 28, 2025 | `claude-3-5-sonnet-20241022` | `claude-sonnet-4-6` |
170 +
171 +### 2025-06-30: Claude Opus 3 model
172 +
173 +<Note>
174 + This model was retired January 5, 2026.
175 +</Note>
176 +
177 +On June 30, 2025, Anthropic notified developers using Claude Opus 3 model of its upcoming retirement.
178 +
179 +| Retirement date | Deprecated model | Recommended replacement |
180 +| --------------- | ------------------------ | ----------------------- |
181 +| January 5, 2026 | `claude-3-opus-20240229` | `claude-opus-4-8` |
182 +
183 +### 2025-01-21: Claude 2, Claude 2.1, and Claude Sonnet 3 models
184 +
185 +<Note>
186 + These models were retired July 21, 2025.
187 +</Note>
188 +
189 +On January 21, 2025, Anthropic notified developers using Claude 2, Claude 2.1, and Claude Sonnet 3 models of their upcoming retirements.
190 +
191 +| Retirement date | Deprecated model | Recommended replacement |
192 +| --------------- | -------------------------- | ----------------------- |
193 +| July 21, 2025 | `claude-2.0` | `claude-opus-4-8` |
194 +| July 21, 2025 | `claude-2.1` | `claude-opus-4-8` |
195 +| July 21, 2025 | `claude-3-sonnet-20240229` | `claude-sonnet-4-6` |
196 +
197 +### 2024-09-04: Claude 1 and Instant models
198 +
199 +<Note>
200 + These models were retired November 6, 2024.
201 +</Note>
202 +
203 +On September 4, 2024, Anthropic notified developers using Claude 1 and Instant models of their upcoming retirements.
204 +
205 +| Retirement date | Deprecated model | Recommended replacement |
206 +| ---------------- | -------------------- | --------------------------- |
207 +| November 6, 2024 | `claude-1.0` | `claude-haiku-4-5-20251001` |
208 +| November 6, 2024 | `claude-1.1` | `claude-haiku-4-5-20251001` |
209 +| November 6, 2024 | `claude-1.2` | `claude-haiku-4-5-20251001` |
210 +| November 6, 2024 | `claude-1.3` | `claude-haiku-4-5-20251001` |
211 +| November 6, 2024 | `claude-instant-1.0` | `claude-haiku-4-5-20251001` |
212 +| November 6, 2024 | `claude-instant-1.1` | `claude-haiku-4-5-20251001` |
213 +| November 6, 2024 | `claude-instant-1.2` | `claude-haiku-4-5-20251001` |
214 +
215 +## API parameter deprecations
216 +
217 +Anthropic occasionally deprecates request parameters that no longer apply to current models. How the API treats a deprecated parameter depends on the model, as the following table shows. Most SDKs keep deprecated parameters in their request types so existing code continues to type-check. The Python SDK (v1.0 and later) removes `temperature`, `top_p`, and `top_k`, so passing them raises a `TypeError`.
218 +
219 +| Parameter | Status | Behavior | Recommended replacement |
220 +| ------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
221 +| `temperature`, `top_p`, `top_k` | Deprecated (Claude Opus 4.7 and later) | Returns a 400 error when set to a non-default value on Claude 4.7 and later models and [Claude Mythos Preview](https://anthropic.com/glasswing). | Omit and use [prompting](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices) to guide model behavior. |
222 +
223 +For migration steps, see the [migration guide](https://platform.claude.com/docs/en/about-claude/models/migration-guide).
added tests/fixtures/anthropic/models-overview.md +110 −0
@@ -0,0 +1,110 @@
1 +---
2 +title: Models overview
3 +url: https://platform.claude.com/docs/en/models/overview
4 +description: Claude is a family of state-of-the-art large language models developed by Anthropic. This guide introduces the available models and compares their performance.
5 +---
6 +
7 +# Models overview
8 +
9 +Claude is a family of state-of-the-art large language models developed by Anthropic. Compare the current lineup, find the model ID for every platform, and open each model's page for its full specs and resources.
10 +
11 +<HomeQuickChip icon="Signpost" href="https://platform.claude.com/docs/en/about-claude/models/choosing-a-model">
12 + Choosing a model
13 +</HomeQuickChip>
14 +
15 +<HomeQuickChip icon="DollarSign" href="https://platform.claude.com/docs/en/about-claude/pricing">
16 + Pricing
17 +</HomeQuickChip>
18 +
19 +<HomeQuickChip icon="ArrowUpCircle" href="https://platform.claude.com/docs/en/about-claude/models/migration-guide">
20 + Migration guide
21 +</HomeQuickChip>
22 +
23 +## Compare models
24 +
25 +If you're unsure which model to use, start with [Claude Opus 5](https://platform.claude.com/docs/en/models/opus-5/overview) for most workloads. Use [Claude Fable 5.1](https://platform.claude.com/docs/en/models/fable-5-1/overview) for demanding reasoning and long-horizon agentic work, or when your evals on Claude Opus 5 at higher effort still fall short. All current models support text and image input, text output, multilingual capabilities, vision, and tool use. Each model's page lists the platforms it's available on.
26 +
27 +| Feature | Claude Fable 5.1 | Claude Opus 5 | Claude Sonnet 5 | Claude Haiku 4.5 |
28 +| :-------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------- | :-------------------------------------------------------------------------- | :------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------- |
29 +| Description | For demanding reasoning and long-horizon agentic work | For complex agentic coding and enterprise work | The best combination of speed and intelligence | The fastest model with near-frontier intelligence |
30 +| Model page | [Claude Fable 5.1](https://platform.claude.com/docs/en/models/fable-5-1/overview) | [Claude Opus 5](https://platform.claude.com/docs/en/models/opus-5/overview) | [Claude Sonnet 5](https://platform.claude.com/docs/en/models/sonnet-5/overview) | [Claude Haiku 4.5](https://platform.claude.com/docs/en/models/haiku-4-5/overview) |
31 +| Comparative latency | Slower | Moderate | Fast | Fastest |
32 +| [Pricing](https://platform.claude.com/docs/en/about-claude/pricing) | $10 / input MTok, $50 / output MTok | $5 / input MTok, $25 / output MTok | $2 / input MTok, $10 / output MTok | $1 / input MTok, $5 / output MTok |
33 +| Claude API ID | `claude-fable-5-1` | `claude-opus-5` | `claude-sonnet-5` | `claude-haiku-4-5-20251001` |
34 +| [Thinking](https://platform.claude.com/docs/en/build-with-claude/thinking) | Adaptive (always on) | Adaptive | Adaptive | Extended |
35 +| [Default effort](https://platform.claude.com/docs/en/build-with-claude/effort) | `high` | `high` | `high` | Not supported |
36 +| [Context window](https://platform.claude.com/docs/en/build-with-claude/context-windows) | 1M tokens | 1M tokens | 1M tokens | 200K tokens |
37 +| Max output | 128K tokens | 128K tokens | 128K tokens | 64K tokens |
38 +| Reliable knowledge cutoff | Jun 2026 | May 2026 | Jan 2026 | Feb 2025 |
39 +| Training data cutoff | Jun 2026 | May 2026 | Jan 2026 | Jul 2025 |
40 +| [Retirement](https://platform.claude.com/docs/en/about-claude/model-deprecations) | Not sooner than September 1, 2027 | Not sooner than July 24, 2027 | Not sooner than June 30, 2027 | Not sooner than October 15, 2026 |
41 +| Claude API alias | `claude-fable-5-1` | `claude-opus-5` | `claude-sonnet-5` | `claude-haiku-4-5` |
42 +| [Amazon Bedrock ID](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock) | `anthropic.claude-fable-5-1` | `anthropic.claude-opus-5` | `anthropic.claude-sonnet-5` | `anthropic.claude-haiku-4-5` |
43 +| [Google Cloud ID](https://platform.claude.com/docs/en/build-with-claude/claude-on-vertex-ai) | `claude-fable-5-1` | `claude-opus-5` | `claude-sonnet-5` | `claude-haiku-4-5@20251001` |
44 +| [Microsoft Foundry ID](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry) | `claude-fable-5-1` | `claude-opus-5` | `claude-sonnet-5` | `claude-haiku-4-5` |
45 +| [Claude Platform on AWS ID](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws) | `claude-fable-5-1` | — | `claude-sonnet-5` | `claude-haiku-4-5` |
46 +
47 +* **Comparative latency:** Relative to the current lineup. Actual latency depends on prompt length, output length, and thinking effort.
48 +* **Pricing:** Base price per million tokens. Batch API requests are 50% off; prompt cache reads cost 10% of the base input price (2.5% on Claude Fable 5.1 and Claude Mythos 5.1). See Pricing for cache writes, long-context, and per-platform pricing.
49 +* **Claude API ID:** Every Claude model ID is a pinned snapshot, including the dateless IDs used from the 4.6 generation on.
50 +* **Thinking:** Adaptive thinking lets the model decide how much to think, steered by effort. Extended thinking is the manual thinking.type “enabled” + budget\_tokens mode on earlier models; it is deprecated on Claude Opus 4.6 and Claude Sonnet 4.6 and not accepted on later models.
51 +* **Default effort:** The effort parameter’s default on the Claude API. Set effort explicitly to use a different level.
52 +* **Context window:** 1M tokens is roughly 555k words or 2.5M Unicode characters on the current tokenizer (introduced with Claude Opus 4.7); models before it fit about 750k words in 1M tokens. 200k tokens is roughly 150k words.
53 +* **Max output:** Synchronous Messages API limit. On the Message Batches API, Claude Opus 5, Claude Sonnet 5, Claude Opus 4.8, Claude Opus 4.7, Claude Opus 4.6, and Claude Sonnet 4.6 support up to 300k output tokens with the output-300k-2026-03-24 beta header.
54 +* **Reliable knowledge cutoff:** The date through which the model’s knowledge is most extensive and reliable. Training data cutoff (under Show all details) is the broader range of data used. See Anthropic’s Transparency Hub for details.
55 +* **Retirement:** Anthropic’s commitment for Anthropic-operated platforms (Claude API, Claude Platform on AWS, Microsoft Foundry). Amazon Bedrock and Google Cloud set their own dates.
56 +* **Claude API alias:** For models before the 4.6 generation, the alias is a convenience pointer that resolves to the dated ID. Dateless IDs are their own pinned snapshot; the alias row repeats them.
57 +* **Amazon Bedrock ID:** The ID on Bedrock’s Messages-API endpoint (Claude Opus 4.7 and later, plus Claude Haiku 4.5); a model offered only through Bedrock’s InvokeModel integration shows that ID instead. Bedrock offers global endpoints (dynamic routing) and regional endpoints (guaranteed data routing) for Claude Sonnet 4.5 and later, and sets its own lifecycle dates.
58 +* **Google Cloud ID:** Google Cloud offers global, multi-region, and regional endpoints, and sets its own lifecycle dates.
59 +* **Microsoft Foundry ID:** Foundry deployments default to the Claude API model ID (the alias, where one exists); the deployment name is what you send. Foundry follows the Claude API lifecycle schedule.
60 +* **Claude Platform on AWS ID:** Claude Platform on AWS uses the Claude API model IDs (the dateless form where the Claude API has an alias), not Bedrock-style IDs, and follows Anthropic’s first-party model lifecycle.
61 +
62 +See [Model IDs and versioning](https://platform.claude.com/docs/en/about-claude/models/model-ids-and-versions) and [Pricing](https://platform.claude.com/docs/en/about-claude/pricing).
63 +
64 +Legacy models (still available): [Claude Fable 5](https://platform.claude.com/docs/en/models/fable-5/overview), [Claude Opus 4.8](https://platform.claude.com/docs/en/models/opus-4-8/overview), [Claude Opus 4.7](https://platform.claude.com/docs/en/models/opus-4-7/overview), [Claude Opus 4.6](https://platform.claude.com/docs/en/models/opus-4-6/overview), [Claude Opus 4.5](https://platform.claude.com/docs/en/models/opus-4-5/overview), [Claude Sonnet 4.6](https://platform.claude.com/docs/en/models/sonnet-4-6/overview), [Claude Sonnet 4.5](https://platform.claude.com/docs/en/models/sonnet-4-5/overview).
65 +
66 +Once you've picked a model, [learn how to make your first API call](https://platform.claude.com/docs/en/get-started). To understand how model IDs, aliases, and snapshots work, see [Model IDs and versioning](https://platform.claude.com/docs/en/about-claude/models/model-ids-and-versions); for the reliable-knowledge and training-data cutoffs behind each model, see [Anthropic's Transparency Hub](https://www.anthropic.com/transparency).
67 +
68 +## Using the Models API
69 +
70 +You can query model capabilities and token limits programmatically with the [Models API](https://platform.claude.com/docs/en/api/models/list). The response includes `max_input_tokens`, `max_tokens`, and a `capabilities` object for every available model.
71 +
72 +## Prompt and output performance
73 +
74 +Current Claude models excel in:
75 +
76 +* **Performance:** Top-tier results in reasoning, coding, multilingual tasks, long-context handling, honesty, and image processing. See [Prompting best practices](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices) for general and model-specific prompting guidance.
77 +* **Engaging responses:** Claude models are ideal for applications that require rich, human-like interactions. If you prefer more concise responses, adjust your prompts to guide the model toward the desired output length. Refer to the [prompt engineering guides](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering) for details.
78 +* **Output quality:** When migrating from a previous model generation, you may notice larger improvements in overall performance. If you're on Claude Opus 4.8 or earlier, see [Migrating to Claude Opus 5](https://platform.claude.com/docs/en/models/opus-5/migration-guide).
79 +
80 +## Get started with Claude
81 +
82 +If you're ready to start exploring what Claude can do for you, dive in! Whether you're a developer looking to integrate Claude into your applications or a user wanting to experience the power of AI firsthand, the following resources can help.
83 +
84 +<CardGroup cols={3}>
85 + <Card title="Intro to Claude" icon="check" href="https://platform.claude.com/docs/en/intro">
86 + Explore Claude's capabilities and development flow.
87 + </Card>
88 +
89 + <Card title="Quickstart" icon="lightning" href="https://platform.claude.com/docs/en/get-started">
90 + Learn how to make your first API call in minutes.
91 + </Card>
92 +
93 + <Card title="Choosing a model" icon="compass" href="https://platform.claude.com/docs/en/about-claude/models/choosing-a-model">
94 + Establish criteria and pick the right model for your use case.
95 + </Card>
96 +
97 + <Card title="Pricing" icon="coins" href="https://platform.claude.com/docs/en/about-claude/pricing">
98 + Complete pricing, including batch discounts and prompt caching rates.
99 + </Card>
100 +
101 + <Card title="Model deprecations" icon="clock" href="https://platform.claude.com/docs/en/about-claude/model-deprecations">
102 + Lifecycle status and retirement commitments for every model.
103 + </Card>
104 +
105 + <Card title="Claude Console" icon="code" href="https://platform.claude.com/">
106 + Craft and test prompts directly in your browser.
107 + </Card>
108 +</CardGroup>
109 +
110 +Looking to chat with Claude? Visit [claude.ai](https://claude.ai). If you have questions, reach out to the [support team](https://support.claude.com/) or the [Discord community](https://www.anthropic.com/discord).
added tests/fixtures/anthropic/news.html +1 −0
@@ -0,0 +1 @@
1 +<!DOCTYPE html><html lang="en" class="anthropicsans_dce02d96-module__tEBbKW__variable anthropicserif_e7e46c4-module__uImRTq__variable anthropicmono_fae19af3-module__c5XAsG__variable copernicus_e225fe92-module__gIXlfG__variable styrenea_ba30709d-module__X1taUa__variable styreneb_ef815608-module__QsOdUa__variable tiempostext_b1e9a056-module__lQ_52W__variable jetbrainsmono_4a81325a-module__1wasHq__variable"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/2gepcixj9k_19.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/chunks/2pnrpp88lh_gg.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/chunks/0jlkzpw9ac_ue.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/chunks/1n17vgd8rsel0.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/chunks/0hpj44a23iwyo.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/chunks/0rgpq5sb7ts3i.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/138-1_49eoue5.js"/><script src="/_next/static/chunks/3nc6x0_y5iwnk.js" async=""></script><script src="/_next/static/chunks/0qt_yb7tkmhnh.js" async=""></script><script src="/_next/static/chunks/1xyeebhobpx1t.js" async=""></script><script src="/_next/static/chunks/turbopack-3a3ubgu7ap1i1.js" async=""></script><script src="/_next/static/chunks/2yl1jv4w6po1z.js" async=""></script><script src="/_next/static/chunks/1ntn7efqc-iiw.js" async=""></script><script src="/_next/static/chunks/0e3-jir0v5afw.js" async=""></script><script src="/_next/static/chunks/0ld574-gx-fgb.js" async=""></script><script src="/_next/static/chunks/3k_473ybucr6n.js" async=""></script><script src="/_next/static/chunks/09kr574z319ye.js" async=""></script><script src="/_next/static/chunks/29nzh0illa0z0.js" async=""></script><script src="/_next/static/chunks/3euk033p3vkb6.js" async=""></script><script src="/_next/static/chunks/1m2tuo2yn9z9q.js" async=""></script><script src="/_next/static/chunks/0e3v21lqmnrgx.js" async=""></script><script src="/_next/static/chunks/1mcakwknehjsg.js" async=""></script><script src="/_next/static/chunks/2142y_r3r849c.js" async=""></script><script src="/_next/static/chunks/3-fnghd0zoogo.js" async=""></script><script src="/_next/static/chunks/1-9e3zcgh8gk1.js" async=""></script><script src="/_next/static/chunks/0od98pyc9u2nj.js" async=""></script><script src="/_next/static/chunks/0od08xnx_58ui.js" async=""></script><script src="/_next/static/chunks/0b2dmya4y8ovs.js" async=""></script><link rel="preload" href="/_next/static/chunks/1plsl93aq761e.css" as="style"/><meta name="next-size-adjust" content=""/><meta name="theme-color" content="#141413"/><title>Newsroom \ Anthropic</title><meta name="description" content="Anthropic is an AI safety and research company that&#x27;s working to build reliable, interpretable, and steerable AI systems."/><meta name="msapplication-TileColor" content="141413"/><meta name="msapplication-config" content="/browserconfig.xml"/><link rel="canonical" href="https://www.anthropic.com/news"/><meta name="google-site-verification" content="BqiAW_sWOg-KrPk-Accxm6ge9dtnFEyV6DB6vzVZSGs"/><meta property="og:title" content="Newsroom"/><meta property="og:description" content="Anthropic is an AI safety and research company that&#x27;s working to build reliable, interpretable, and steerable AI systems."/><meta property="og:image" content="https://cdn.sanity.io/images/4zrzovbb/website/6d4a0d28992ade92d6fa63646fd9c9d318245c6c-2400x1260.jpg"/><meta property="og:image:alt" content="Anthropic logo"/><meta property="og:type" content="website"/><meta name="twitter:card" content="summary_large_image"/><meta name="twitter:site" content="@AnthropicAI"/><meta name="twitter:creator" content="@AnthropicAI"/><meta name="twitter:title" content="Newsroom"/><meta name="twitter:description" content="Anthropic is an AI safety and research company that&#x27;s working to build reliable, interpretable, and steerable AI systems."/><meta name="twitter:image" content="https://cdn.sanity.io/images/4zrzovbb/website/6d4a0d28992ade92d6fa63646fd9c9d318245c6c-2400x1260.jpg"/><meta name="twitter:image:alt" content="Anthropic logo"/><link rel="shortcut icon" href="/favicon.ico"/><link rel="icon" href="/images/icons/favicon-32x32.png"/><link rel="apple-touch-icon" href="/images/icons/apple-touch-icon.png"/><link rel="apple-touch-icon" href="/images/icons/apple-touch-icon.png" sizes="180x180"/><link rel="mask-icon" href="/images/icons/safari-pinned-tab.svg" color="141413"/><script src="/_next/static/chunks/0cz1d0mv5g_q7.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><header class="SiteHeader-module-scss-module__zKj4Ca__header" data-theme="light"><div class="SiteHeader-module-scss-module__zKj4Ca__skipLinks"><a href="#main-content" class="SiteHeader-module-scss-module__zKj4Ca__skipLink">Skip to main content</a><a href="#footer" class="SiteHeader-module-scss-module__zKj4Ca__skipLink">Skip to footer</a></div><div class="page-wrapper SiteHeader-module-scss-module__zKj4Ca__root"><a href="/" aria-label="Home"><div class="SiteHeader-module-scss-module__zKj4Ca__logoDesktop"><div class="LogoWordmark-module-scss-module__Sdgt-q__logo-wrapper"><svg class="LogoWordmark-module-scss-module__Sdgt-q__logo-static" width="570" height="64" viewBox="0 0 570 64" fill="none" xmlns="http://www.w3.org/2000/svg" aria-label="Anthropic"><path d="M139.492 12.9945H160.265V62.9392H173.525V12.9945H194.298V1.06077H139.492V12.9945Z" fill="currentColor"></path><path d="M116.066 44.3757L88.221 1.06077H73.1934V62.9392H86.011V19.6243L113.856 62.9392H128.884V1.06077H116.066V44.3757Z" fill="currentColor"></path><path d="M247.337 25.7238H218.166V1.06077H204.906V62.9392H218.166V37.6575H247.337V62.9392H260.597V1.06077H247.337V25.7238Z" fill="currentColor"></path><path d="M24.663 1.06077L0 62.9392H13.7901L18.834 49.9447H44.6365L49.6796 62.9392H63.4696L38.8066 1.06077H24.663ZM23.2946 38.453L31.7348 16.7072L40.175 38.453H23.2946Z" fill="currentColor"></path><path d="M370.475 0C352.619 0 339.978 13.2597 339.978 32.0884C339.978 50.7403 352.619 64 370.475 64C388.243 64 400.796 50.7403 400.796 32.0884C400.796 13.2597 388.243 0 370.475 0ZM370.475 51.6243C360.044 51.6243 353.68 44.1989 353.68 32.0884C353.68 19.8011 360.044 12.3757 370.475 12.3757C380.818 12.3757 387.094 19.8011 387.094 32.0884C387.094 44.1989 380.818 51.6243 370.475 51.6243Z" fill="currentColor"></path><path d="M555.845 42.1657C553.547 48.1768 548.95 51.6243 542.674 51.6243C532.243 51.6243 525.878 44.1989 525.878 32.0884C525.878 19.8011 532.243 12.3757 542.674 12.3757C548.95 12.3757 553.547 15.8232 555.845 21.8343H569.901C566.453 8.57459 556.11 0 542.674 0C524.818 0 512.177 13.2597 512.177 32.0884C512.177 50.7403 524.818 64 542.674 64C556.199 64 566.541 55.337 569.989 42.1657H555.845Z" fill="currentColor"></path><path d="M471.337 1.06077L496 62.9392H509.525L484.862 1.06077H471.337Z" fill="currentColor"></path><path d="M443.403 1.06077H413.171V62.9392H426.431V40.4862H443.403C457.459 40.4862 466.033 33.0608 466.033 20.7735C466.033 8.48619 457.459 1.06077 443.403 1.06077ZM442.784 28.5525H426.431V12.9945H442.784C449.326 12.9945 452.773 15.6464 452.773 20.7735C452.773 25.9006 449.326 28.5525 442.784 28.5525Z" fill="currentColor"></path><path d="M329.812 19.8895C329.812 8.22099 321.238 1.06077 307.182 1.06077H276.95V62.9392H290.21V38.7182H304.971L318.232 62.9392H332.906L318.223 36.8734C325.593 34.0402 329.812 28.0743 329.812 19.8895ZM290.21 12.9945H306.564C313.105 12.9945 316.552 15.3812 316.552 19.8895C316.552 24.3978 313.105 26.7845 306.564 26.7845H290.21V12.9945Z" fill="currentColor"></path></svg><div class="LogoWordmark-module-scss-module__Sdgt-q__logo-lottie"></div></div></div><svg class="Icon-module-scss-module__lqbdHG__icon SiteHeader-module-scss-module__zKj4Ca__logoMobile" width="32" height="32" viewBox="0 0 46 32"><path d="M32.73 0h-6.945L38.45 32h6.945L32.73 0ZM12.665 0 0 32h7.082l2.59-6.72h13.25l2.59 6.72h7.082L19.929 0h-7.264Zm-.702 19.337 4.334-11.246 4.334 11.246h-8.668Z" fill="currentColor"></path></svg></a><div class="SiteHeader-module-scss-module__zKj4Ca__contentWrapper"><nav class="SiteHeader-module-scss-module__zKj4Ca__nav"><ul class="SiteHeader-module-scss-module__zKj4Ca__navList"><li class="body-3 SiteHeader-module-scss-module__zKj4Ca__navItem" data-category="Research"><button class="SiteHeader-module-scss-module__zKj4Ca__navText" aria-haspopup="menu" aria-expanded="false" aria-controls="nav-dropdown-Research"><span>Research</span><svg class="Icon-module-scss-module__lqbdHG__icon SiteHeader-module-scss-module__zKj4Ca__caretIcon" width="12" height="6.13" viewBox="0 0 8 5"><path d="M7.3016 0.231808C7.44932 0.0678162 7.70306 0.0546398 7.86724 0.20212C8.03137 0.349888 8.04461 0.603568 7.89692 0.767766L4.29684 4.76791L4.23434 4.82417C4.16662 4.87328 4.08425 4.89995 3.99918 4.89995C3.88588 4.89989 3.77733 4.85213 3.70152 4.76791L0.10144 0.767766L0.0537825 0.702139C-0.040206 0.541753 -0.0124254 0.331356 0.131128 0.20212C0.274775 0.0728844 0.486972 0.0674593 0.636608 0.1779L0.696765 0.231808L3.99918 3.90148L7.3016 0.231808Z" fill="currentColor"></path></svg></button></li><li class="body-3 SiteHeader-module-scss-module__zKj4Ca__navItem"><a href="/policy" class="SiteHeader-module-scss-module__zKj4Ca__navText">Policy</a></li><li class="body-3 SiteHeader-module-scss-module__zKj4Ca__navItem" data-category="Commitments"><button class="SiteHeader-module-scss-module__zKj4Ca__navText" aria-haspopup="menu" aria-expanded="false" aria-controls="nav-dropdown-Commitments"><span>Commitments</span><svg class="Icon-module-scss-module__lqbdHG__icon SiteHeader-module-scss-module__zKj4Ca__caretIcon" width="12" height="6.13" viewBox="0 0 8 5"><path d="M7.3016 0.231808C7.44932 0.0678162 7.70306 0.0546398 7.86724 0.20212C8.03137 0.349888 8.04461 0.603568 7.89692 0.767766L4.29684 4.76791L4.23434 4.82417C4.16662 4.87328 4.08425 4.89995 3.99918 4.89995C3.88588 4.89989 3.77733 4.85213 3.70152 4.76791L0.10144 0.767766L0.0537825 0.702139C-0.040206 0.541753 -0.0124254 0.331356 0.131128 0.20212C0.274775 0.0728844 0.486972 0.0674593 0.636608 0.1779L0.696765 0.231808L3.99918 3.90148L7.3016 0.231808Z" fill="currentColor"></path></svg></button></li><li class="body-3 SiteHeader-module-scss-module__zKj4Ca__navItem" data-category="Learn"><button class="SiteHeader-module-scss-module__zKj4Ca__navText" aria-haspopup="menu" aria-expanded="false" aria-controls="nav-dropdown-Learn"><span>Learn</span><svg class="Icon-module-scss-module__lqbdHG__icon SiteHeader-module-scss-module__zKj4Ca__caretIcon" width="12" height="6.13" viewBox="0 0 8 5"><path d="M7.3016 0.231808C7.44932 0.0678162 7.70306 0.0546398 7.86724 0.20212C8.03137 0.349888 8.04461 0.603568 7.89692 0.767766L4.29684 4.76791L4.23434 4.82417C4.16662 4.87328 4.08425 4.89995 3.99918 4.89995C3.88588 4.89989 3.77733 4.85213 3.70152 4.76791L0.10144 0.767766L0.0537825 0.702139C-0.040206 0.541753 -0.0124254 0.331356 0.131128 0.20212C0.274775 0.0728844 0.486972 0.0674593 0.636608 0.1779L0.696765 0.231808L3.99918 3.90148L7.3016 0.231808Z" fill="currentColor"></path></svg></button></li><li class="body-3 SiteHeader-module-scss-module__zKj4Ca__navItem"><a href="/news" class="SiteHeader-module-scss-module__zKj4Ca__navText">News</a></li></ul></nav><div class="SiteHeader-module-scss-module__zKj4Ca__claudeCtaWrapper"><a href="https://claude.ai/" class="SiteHeader-module-scss-module__zKj4Ca__claudeCtaButton body-3" target="_blank" rel="noopener noreferrer">Try Claude</a><div class="SiteHeader-module-scss-module__zKj4Ca__claudeCtaDropdownTrigger"><svg class="Icon-module-scss-module__lqbdHG__icon SiteHeader-module-scss-module__zKj4Ca__claudeCtaIcon" width="12" height="6.13" viewBox="0 0 8 5"><path d="M7.3016 0.231808C7.44932 0.0678162 7.70306 0.0546398 7.86724 0.20212C8.03137 0.349888 8.04461 0.603568 7.89692 0.767766L4.29684 4.76791L4.23434 4.82417C4.16662 4.87328 4.08425 4.89995 3.99918 4.89995C3.88588 4.89989 3.77733 4.85213 3.70152 4.76791L0.10144 0.767766L0.0537825 0.702139C-0.040206 0.541753 -0.0124254 0.331356 0.131128 0.20212C0.274775 0.0728844 0.486972 0.0674593 0.636608 0.1779L0.696765 0.231808L3.99918 3.90148L7.3016 0.231808Z" fill="currentColor"></path></svg></div></div><button class="SiteHeader-module-scss-module__zKj4Ca__mobileIcon" aria-label="Navigation menu"><svg class="Icon-module-scss-module__lqbdHG__icon" width="24" height="24" viewBox="0 0 40 40"><path d="M18.75 28C19.1641 28.0002 19.5 28.3359 19.5 28.75C19.4999 29.1641 19.164 29.4998 18.75 29.5H7.91699C7.50281 29.5 7.16705 29.1642 7.16699 28.75C7.16699 28.3358 7.50278 28 7.91699 28H18.75ZM32.084 19.25C32.4979 19.2504 32.834 19.586 32.834 20C32.8339 20.4139 32.4979 20.7496 32.084 20.75H7.91699C7.50281 20.75 7.16705 20.4142 7.16699 20C7.16699 19.5858 7.50278 19.25 7.91699 19.25H32.084ZM32.084 10.5C32.4979 10.5004 32.834 10.836 32.834 11.25C32.8339 11.6639 32.4979 11.9996 32.084 12H7.91699C7.50282 12 7.16706 11.6642 7.16699 11.25C7.16699 10.8358 7.50278 10.5 7.91699 10.5H32.084Z" fill="currentColor"></path></svg></button></div></div></header><main id="main-content" class=""><article><section class="HeroTwoColumn-module-scss-module__pM-nba__landingPageListHeader LandingPageSection-module-scss-module__ZSMdoa__root bg-default" data-theme="ivory"><div class="page-wrapper"><div class="HeroTwoColumn-module-scss-module__pM-nba__root"><div class="HeroTwoColumn-module-scss-module__pM-nba__titleSubhead"><h1 class="headline-1">Newsroom</h1></div><div class="HeroTwoColumn-module-scss-module__pM-nba__bodyCtas"><div class="HeroTwoColumn-module-scss-module__pM-nba__ctaWrapper"><ul class="HeroTwoColumn-module-scss-module__pM-nba__ctaList"><li><span class="HeroTwoColumn-module-scss-module__pM-nba__listLabel body-3">Press inquiries</span><a href="mailto:press@anthropic.com" class="ButtonTextLink-module-scss-module__q8IAwW__textLink HeroTwoColumn-module-scss-module__pM-nba__listLink"><span class="ButtonTextLink-module-scss-module__q8IAwW__icon"><svg class="Icon-module-scss-module__lqbdHG__icon" width="18" height="24" viewBox="0 0 18 24"><path d="M14.5 4C14.7761 4 15 4.22386 15 4.5C15 4.77614 14.7761 5 14.5 5H13V7H14C16.2091 7 18 8.79086 18 11V15.5C18 16.3284 17.3284 17 16.5 17H10V19.5C10 19.7761 9.77614 20 9.5 20C9.22386 20 9 19.7761 9 19.5V17H3.5C3.44824 17 3.39709 16.9973 3.34668 16.9922C2.59028 16.9154 2 16.2767 2 15.5V11C2 8.79086 3.79086 7 6 7H12V4.5L12.0098 4.39941C12.0563 4.17145 12.2583 4 12.5 4H14.5ZM6 8C4.34315 8 3 9.34315 3 11V15.5C3 15.7761 3.22386 16 3.5 16H8.5C8.77614 16 9 15.7761 9 15.5V11C9 9.34315 7.65685 8 6 8ZM8.64453 8C9.47537 8.73296 10 9.80496 10 11V15.5C10 15.6755 9.96847 15.8435 9.91309 16H16.5C16.7761 16 17 15.7761 17 15.5V11C17 9.34315 15.6569 8 14 8H13V12.5C13 12.7761 12.7761 13 12.5 13C12.2239 13 12 12.7761 12 12.5V8H8.64453ZM7.5 14C7.77614 14 8 14.2239 8 14.5C8 14.7761 7.77614 15 7.5 15H4.5C4.22386 15 4 14.7761 4 14.5C4 14.2239 4.22386 14 4.5 14H7.5Z" fill="currentColor"></path></svg></span><span class="body-3">press@anthropic.com</span></a></li><li><span class="HeroTwoColumn-module-scss-module__pM-nba__listLabel body-3">Non-media inquiries</span><a href="https://support.claude.com/en/articles/9015913-how-to-get-support" class="ButtonTextLink-module-scss-module__q8IAwW__textLink HeroTwoColumn-module-scss-module__pM-nba__listLink" target="_blank" rel="noopener"><span class="ButtonTextLink-module-scss-module__q8IAwW__icon"><svg class="Icon-module-scss-module__lqbdHG__icon" width="20" height="20" viewBox="0 0 20 20"><path d="M10 2.5C14.1421 2.5 17.5 5.85786 17.5 10C17.5 14.1421 14.1421 17.5 10 17.5C5.85786 17.5 2.5 14.1421 2.5 10C2.5 5.85786 5.85786 2.5 10 2.5ZM10 3.5C6.41015 3.5 3.5 6.41015 3.5 10C3.5 13.5899 6.41015 16.5 10 16.5C13.5899 16.5 16.5 13.5899 16.5 10C16.5 6.41015 13.5899 3.5 10 3.5ZM10 13C10.4142 13 10.75 13.3358 10.75 13.75C10.75 14.1642 10.4142 14.5 10 14.5C9.58579 14.5 9.25 14.1642 9.25 13.75C9.25 13.3358 9.58579 13 10 13ZM10 6C11.3807 6 12.5 7.11929 12.5 8.5C12.5 9.38804 12.0368 10.1673 11.3408 10.6104L11.1992 10.6943C10.9911 10.8083 10.8057 10.9465 10.6777 11.0957C10.5519 11.2424 10.5 11.376 10.5 11.5V11.75C10.5 12.0261 10.2761 12.25 10 12.25C9.72386 12.25 9.5 12.0261 9.5 11.75V11.5C9.5 11.0717 9.68539 10.7155 9.91797 10.4443C10.1483 10.1758 10.4426 9.96859 10.7188 9.81738L10.8867 9.70996C11.2593 9.43646 11.5 8.99609 11.5 8.5C11.5 7.67157 10.8284 7 10 7C9.17157 7 8.5 7.67157 8.5 8.5C8.5 8.77614 8.27614 9 8 9C7.72386 9 7.5 8.77614 7.5 8.5C7.5 7.11929 8.61929 6 10 6Z" fill="currentColor"></path></svg></span><span class="body-3">How to get support</span></a></li><li><span class="HeroTwoColumn-module-scss-module__pM-nba__listLabel body-3">Media assets</span><a href="https://anthropic.com/press-kit" class="ButtonTextLink-module-scss-module__q8IAwW__textLink HeroTwoColumn-module-scss-module__pM-nba__listLink" target="_blank" rel="noopener"><span class="ButtonTextLink-module-scss-module__q8IAwW__icon"><svg class="Icon-module-scss-module__lqbdHG__icon" width="20" height="24" viewBox="0 0 20 24"><path d="M16.5 15C16.7761 15 17 15.2239 17 15.5V17.5C17 18.3284 16.3284 19 15.5 19H4.5C3.67157 19 3 18.3284 3 17.5V15.5C3 15.2239 3.22386 15 3.5 15C3.77614 15 4 15.2239 4 15.5V17.5C4 17.7761 4.22386 18 4.5 18H15.5C15.7761 18 16 17.7761 16 17.5V15.5C16 15.2239 16.2239 15 16.5 15ZM10 5C10.2761 5 10.5 5.22386 10.5 5.5V14.1855L13.626 10.668C13.8094 10.4617 14.1256 10.4427 14.332 10.626C14.5383 10.8094 14.5573 11.1256 14.374 11.332L10.374 15.832L10.2949 15.9033C10.21 15.9654 10.107 16 10 16C9.85718 16 9.72086 15.9388 9.62598 15.832L5.62598 11.332L5.56738 11.25C5.45079 11.0487 5.48735 10.7865 5.66797 10.626C5.84854 10.4657 6.1127 10.4604 6.29883 10.5996L6.37402 10.668L9.5 14.1855V5.5C9.5 5.22386 9.72386 5 10 5Z" fill="currentColor"></path></svg></span><span class="body-3">Download press kit</span></a></li></ul></div></div></div></div></section><section class="LandingPageSection-module-scss-module__ZSMdoa__root bg-default LandingPageSection-module-scss-module__ZSMdoa__flushTop" data-theme="ivory"><div class="page-wrapper"><div class="LandingPageSection-module-scss-module__ZSMdoa__borderTop"></div></div><div class="page-wrapper"><div class="FeaturedGrid-module-scss-module__W1FydW__root"><div class="FeaturedGrid-module-scss-module__W1FydW__featuredItem"><figure class="FeaturedGrid-module-scss-module__W1FydW__mediaWrapper"><div class="FeaturedGrid-module-scss-module__W1FydW__mediaContent"><div class="FeaturedGrid-module-scss-module__W1FydW__mediaVideo"><div class="VideoEmbed-module-scss-module__TSxPAa__e-videoEmbed Video-module-scss-module__qJNyFq__embedPlayer"><button class="VideoEmbed-module-scss-module__TSxPAa__thumbnail-overlay" aria-label="Play video"><img alt="Video thumbnail" loading="lazy" width="2880" height="1620" decoding="async" data-nimg="1" class="VideoEmbed-module-scss-module__TSxPAa__thumbnail-image" style="color:transparent" srcSet="/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2F4zrzovbb%2Fwebsite%2Fd337d7c546fdeabce5d41ecd2b96ea385bb5f223-2880x1620.jpg&amp;w=3840&amp;q=75 1x" src="/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2F4zrzovbb%2Fwebsite%2Fd337d7c546fdeabce5d41ecd2b96ea385bb5f223-2880x1620.jpg&amp;w=3840&amp;q=75"/><div class="VideoEmbed-module-scss-module__TSxPAa__play-button"><svg class="Icon-module-scss-module__lqbdHG__icon" width="22" height="22" viewBox="0 0 18 18"><path d="M3.59961 3.6418C3.59986 2.58403 4.76149 1.93696 5.66066 2.49394L14.303 7.85268C15.1543 8.38061 15.1542 9.61864 14.303 10.1466L5.66066 15.5054C4.8175 16.0278 3.74356 15.4919 3.61279 14.5509L3.59961 14.3575V3.6418ZM5.18692 3.25947C4.88726 3.07384 4.49987 3.28934 4.49962 3.6418V14.3575L4.50401 14.4226C4.54786 14.736 4.90598 14.914 5.18692 14.7399L13.8284 9.38199C14.1121 9.20596 14.1122 8.79328 13.8284 8.61734L5.18692 3.25947Z" fill="currentColor"></path></svg></div></button></div></div></div><figcaption class="caption"></figcaption></figure><a href="/claude-fable-and-mythos-5-1" class="FeaturedGrid-module-scss-module__W1FydW__content"><h2 class="headline-4 FeaturedGrid-module-scss-module__W1FydW__featuredTitle">Introducing Claude Fable 5.1 and Claude Mythos 5.1</h2><div class="FeaturedGrid-module-scss-module__W1FydW__featuredItemContent"><a href="/claude-fable-and-mythos-5-1" class="FeaturedGrid-module-scss-module__W1FydW__gridItem FeaturedGrid-module-scss-module__W1FydW__featured"><div class="FeaturedGrid-module-scss-module__W1FydW__meta"><span class="caption bold">Announcements</span><time class="FeaturedGrid-module-scss-module__W1FydW__date caption bold">Sep 1, 2026</time></div><p class="body-3 serif FeaturedGrid-module-scss-module__W1FydW__body">Our most advanced models for coding and knowledge work. Their research capabilities also offer an early glimpse of how AI models will contribute to scientific progress.</p></a></div></a></div><div class="FeaturedGrid-module-scss-module__W1FydW__sideItems"><a href="https://www.anthropic.com/threat-intelligence-report-september-2026" class="FeaturedGrid-module-scss-module__W1FydW__sideLink FeaturedGrid-module-scss-module__W1FydW__gridItem"><div class="FeaturedGrid-module-scss-module__W1FydW__meta"><span class="caption bold">Announcements</span><time class="FeaturedGrid-module-scss-module__W1FydW__date caption bold">Sep 10, 2026</time></div><h4 class="headline-6 FeaturedGrid-module-scss-module__W1FydW__title">Detecting and countering misuse of AI: September 2026</h4><p class="body-3 serif FeaturedGrid-module-scss-module__W1FydW__body">Over the past eight months, our Threat Intelligence team identified and disrupted operations in which threat actors tried to use Claude for malicious activity. In this report, we share case studies from those operations and describe how malicious use of Claude has evolved since our previous threat reports in 2025.</p></a><a href="/news/improving-alignment-security-efforts" class="FeaturedGrid-module-scss-module__W1FydW__sideLink FeaturedGrid-module-scss-module__W1FydW__gridItem"><div class="FeaturedGrid-module-scss-module__W1FydW__meta"><span class="caption bold">Announcements</span><time class="FeaturedGrid-module-scss-module__W1FydW__date caption bold">Aug 31, 2026</time></div><h4 class="headline-6 FeaturedGrid-module-scss-module__W1FydW__title">Improving our alignment and security efforts</h4><p class="body-3 serif FeaturedGrid-module-scss-module__W1FydW__body">On July 30, we reported three incidents in which Claude models gained unauthorized access to real computer systems. We are conducting an in-depth analysis of both incidents, and planning to work with METR for an independent review. In the meantime, we’re sharing some of the changes we’ve made over the past month.</p></a><a href="/news/model-hardware-standard-research-preview" class="FeaturedGrid-module-scss-module__W1FydW__sideLink FeaturedGrid-module-scss-module__W1FydW__gridItem"><div class="FeaturedGrid-module-scss-module__W1FydW__meta"><span class="caption bold">Announcements</span><time class="FeaturedGrid-module-scss-module__W1FydW__date caption bold">Aug 27, 2026</time></div><h4 class="headline-6 FeaturedGrid-module-scss-module__W1FydW__title">Previewing the Model Hardware Standard</h4><p class="body-3 serif FeaturedGrid-module-scss-module__W1FydW__body">We’re opening a research preview of the Model Hardware Standard (MHS), a shared specification for AI agents to safely operate physical devices, to a first group of scientific research labs and advanced manufacturers. </p></a><a href="/news/claude-opus-5" class="FeaturedGrid-module-scss-module__W1FydW__sideLink FeaturedGrid-module-scss-module__W1FydW__gridItem"><div class="FeaturedGrid-module-scss-module__W1FydW__meta"><span class="caption bold">Product</span><time class="FeaturedGrid-module-scss-module__W1FydW__date caption bold">Jul 24, 2026</time></div><h4 class="headline-6 FeaturedGrid-module-scss-module__W1FydW__title">Introducing Claude Opus 5</h4><p class="body-3 serif FeaturedGrid-module-scss-module__W1FydW__body">Opus 5 is a step change improvement for the Opus tier powering long-running agents while delivering improvements in coding and professional work.</p></a></div></div></div></section><section class="LandingPageSection-module-scss-module__ZSMdoa__root bg-default LandingPageSection-module-scss-module__ZSMdoa__flushTop" data-theme="ivory"><div class="page-wrapper"><div class="LandingPageSection-module-scss-module__ZSMdoa__borderTop"></div></div><div class="page-wrapper"><div class="PublicationList-module-scss-module__KxYrHG__header"><h2 class="headline-4">News</h2><div class="SearchFilter-module-scss-module__d4ijlG__container"><label for="search-input" class="SearchFilter-module-scss-module__d4ijlG__srOnly">Search</label><svg class="Icon-module-scss-module__lqbdHG__icon SearchFilter-module-scss-module__d4ijlG__icon" width="20" height="20" viewBox="0 0 20 20"><path d="M8.5 2C12.0899 2 15 4.91015 15 8.5C15 10.1149 14.4094 11.5908 13.4346 12.7275L17.8535 17.1465L17.918 17.2246C18.0461 17.4187 18.0244 17.6827 17.8535 17.8535C17.6827 18.0244 17.4187 18.0461 17.2246 17.918L17.1465 17.8535L12.7275 13.4346C11.5908 14.4094 10.1149 15 8.5 15C4.91015 15 2 12.0899 2 8.5C2 4.91015 4.91015 2 8.5 2ZM8.5 3C5.46243 3 3 5.46243 3 8.5C3 11.5376 5.46243 14 8.5 14C11.5376 14 14 11.5376 14 8.5C14 5.46243 11.5376 3 8.5 3Z" fill="currentColor"></path></svg><input id="search-input" type="text" class="SearchFilter-module-scss-module__d4ijlG__input" placeholder="Search" aria-label="Search" value=""/></div></div><div class="PublicationList-module-scss-module__KxYrHG__root"><div class="PublicationList-module-scss-module__KxYrHG__content"><div class="PublicationList-module-scss-module__KxYrHG__listHeader"><span class="PublicationList-module-scss-module__KxYrHG__headerDate caption">Date</span><span class="PublicationList-module-scss-module__KxYrHG__headerCategory caption">Category</span><span class="PublicationList-module-scss-module__KxYrHG__headerTitle caption">Title</span></div><ul class="PublicationList-module-scss-module__KxYrHG__list"><li><a href="/news/enterprise-frontier-safeguards" class="PublicationList-module-scss-module__KxYrHG__listItem"><div class="PublicationList-module-scss-module__KxYrHG__meta"><time class="PublicationList-module-scss-module__KxYrHG__date body-3">Sep 1, 2026</time><span class="PublicationList-module-scss-module__KxYrHG__subject body-3">Announcements</span></div><span class="PublicationList-module-scss-module__KxYrHG__title body-3">Developing Enterprise Frontier Safeguards with our customers</span></a></li><li><a href="/news/improving-alignment-security-efforts" class="PublicationList-module-scss-module__KxYrHG__listItem"><div class="PublicationList-module-scss-module__KxYrHG__meta"><time class="PublicationList-module-scss-module__KxYrHG__date body-3">Aug 31, 2026</time><span class="PublicationList-module-scss-module__KxYrHG__subject body-3">Announcements</span></div><span class="PublicationList-module-scss-module__KxYrHG__title body-3">Improving our alignment and security efforts</span></a></li><li><a href="/news/model-hardware-standard-research-preview" class="PublicationList-module-scss-module__KxYrHG__listItem"><div class="PublicationList-module-scss-module__KxYrHG__meta"><time class="PublicationList-module-scss-module__KxYrHG__date body-3">Aug 27, 2026</time><span class="PublicationList-module-scss-module__KxYrHG__subject body-3">Announcements</span></div><span class="PublicationList-module-scss-module__KxYrHG__title body-3">Previewing the Model Hardware Standard</span></a></li><li><a href="/news/expanding-support-for-scientists" class="PublicationList-module-scss-module__KxYrHG__listItem"><div class="PublicationList-module-scss-module__KxYrHG__meta"><time class="PublicationList-module-scss-module__KxYrHG__date body-3">Aug 27, 2026</time><span class="PublicationList-module-scss-module__KxYrHG__subject body-3">Announcements</span></div><span class="PublicationList-module-scss-module__KxYrHG__title body-3"> Expanding our support for scientists</span></a></li><li><a href="/news/wellbeing-research-grants" class="PublicationList-module-scss-module__KxYrHG__listItem"><div class="PublicationList-module-scss-module__KxYrHG__meta"><time class="PublicationList-module-scss-module__KxYrHG__date body-3">Aug 25, 2026</time><span class="PublicationList-module-scss-module__KxYrHG__subject body-3">Announcements</span></div><span class="PublicationList-module-scss-module__KxYrHG__title body-3">Funding better evaluations of AI’s impact on wellbeing</span></a></li><li><a href="/news/claude-text-watermark" class="PublicationList-module-scss-module__KxYrHG__listItem"><div class="PublicationList-module-scss-module__KxYrHG__meta"><time class="PublicationList-module-scss-module__KxYrHG__date body-3">Aug 14, 2026</time><span class="PublicationList-module-scss-module__KxYrHG__subject body-3">Announcements</span></div><span class="PublicationList-module-scss-module__KxYrHG__title body-3">How Claude’s text watermark works</span></a></li><li><a href="/news/improving-fable-5-s-biology-safeguards" class="PublicationList-module-scss-module__KxYrHG__listItem"><div class="PublicationList-module-scss-module__KxYrHG__meta"><time class="PublicationList-module-scss-module__KxYrHG__date body-3">Aug 7, 2026</time><span class="PublicationList-module-scss-module__KxYrHG__subject body-3">Product</span></div><span class="PublicationList-module-scss-module__KxYrHG__title body-3">Improving Fable 5&#x27;s biology safeguards</span></a></li><li><a href="/news/tino-cuellar" class="PublicationList-module-scss-module__KxYrHG__listItem"><div class="PublicationList-module-scss-module__KxYrHG__meta"><time class="PublicationList-module-scss-module__KxYrHG__date body-3">Aug 4, 2026</time><span class="PublicationList-module-scss-module__KxYrHG__subject body-3">Announcements</span></div><span class="PublicationList-module-scss-module__KxYrHG__title body-3">Mariano-Florentino (Tino) Cuéllar to join Anthropic as Chief Global Affairs Officer</span></a></li><li><a href="/news/investigating-incidents-cybersecurity-evals" class="PublicationList-module-scss-module__KxYrHG__listItem"><div class="PublicationList-module-scss-module__KxYrHG__meta"><time class="PublicationList-module-scss-module__KxYrHG__date body-3">Jul 30, 2026</time><span class="PublicationList-module-scss-module__KxYrHG__subject body-3">Announcements</span></div><span class="PublicationList-module-scss-module__KxYrHG__title body-3">Investigating three real-world incidents in our cybersecurity evaluations</span></a></li><li><a href="/news/position-open-weights-models" class="PublicationList-module-scss-module__KxYrHG__listItem"><div class="PublicationList-module-scss-module__KxYrHG__meta"><time class="PublicationList-module-scss-module__KxYrHG__date body-3">Jul 27, 2026</time><span class="PublicationList-module-scss-module__KxYrHG__subject body-3">Announcements</span></div><span class="PublicationList-module-scss-module__KxYrHG__title body-3">Our position on open-weights models</span></a></li></ul><a href="#" class="Button-module-scss-module__f9ZZrG__button Button-module-scss-module__f9ZZrG__large Button-module-scss-module__f9ZZrG__tertiary Button-module-scss-module__f9ZZrG__iconRight PublicationList-module-scss-module__KxYrHG__seeMore"><span class="body-3">See more</span><span class="Button-module-scss-module__f9ZZrG__icon"><svg class="Icon-module-scss-module__lqbdHG__icon" width="17" height="16" viewBox="0 0 16 17"><path d="M12.854 9.85375L8.35403 14.3538C8.30759 14.4002 8.25245 14.4371 8.19175 14.4623C8.13105 14.4874 8.06599 14.5004 8.00028 14.5004C7.93457 14.5004 7.86951 14.4874 7.80881 14.4623C7.74811 14.4371 7.69296 14.4002 7.64653 14.3538L3.14653 9.85375C3.05271 9.75993 3 9.63268 3 9.5C3 9.36732 3.05271 9.24007 3.14653 9.14625C3.24035 9.05243 3.3676 8.99972 3.50028 8.99972C3.63296 8.99972 3.76021 9.05243 3.85403 9.14625L7.50028 12.7931V3C7.50028 2.86739 7.55296 2.74021 7.64672 2.64645C7.74049 2.55268 7.86767 2.5 8.00028 2.5C8.13289 2.5 8.26006 2.55268 8.35383 2.64645C8.4476 2.74021 8.50028 2.86739 8.50028 3V12.7931L12.1465 9.14625C12.2403 9.05243 12.3676 8.99972 12.5003 8.99972C12.633 8.99972 12.7602 9.05243 12.854 9.14625C12.9478 9.24007 13.0006 9.36732 13.0006 9.5C13.0006 9.63268 12.9478 9.75993 12.854 9.85375Z" fill="currentColor"></path></svg></span></a></div><aside class="PublicationList-module-scss-module__KxYrHG__aside"><div class="Illustration-module-scss-module__WyGOtq__root Illustration-module-scss-module__WyGOtq__aspect-square Illustration-module-scss-module__WyGOtq__padding-md Illustration-module-scss-module__WyGOtq__radius-md bg-sky PublicationList-module-scss-module__KxYrHG__illustrationContainer"><div class="Illustration-module-scss-module__WyGOtq__inner"><img alt="Developing Enterprise Frontier Safeguards with our customers" loading="lazy" width="1000" height="1000" decoding="async" data-nimg="1" class="" style="color:transparent" src="https://www-cdn.anthropic.com/images/4zrzovbb/website/60d57c0d0bf031e140de678692f7c3ef2d885ce3-1000x1000.svg"/></div></div></aside></div></div></section></article></main><footer id="footer" class="SiteFooter-module-scss-module__JdOqwq__root" role="contentinfo" aria-label="Site footer"><div class="page-wrapper SiteFooter-module-scss-module__JdOqwq__footer"><div class="SiteFooter-module-scss-module__JdOqwq__logoWrapper"><a href="/" aria-label="Return to homepage"><svg class="Icon-module-scss-module__lqbdHG__icon" width="46" height="32" viewBox="0 0 46 32"><path d="M32.73 0h-6.945L38.45 32h6.945L32.73 0ZM12.665 0 0 32h7.082l2.59-6.72h13.25l2.59 6.72h7.082L19.929 0h-7.264Zm-.702 19.337 4.334-11.246 4.334 11.246h-8.668Z" fill="#faf9f5"></path></svg></a></div><nav class="SiteFooter-module-scss-module__JdOqwq__linksWrapper" aria-label="Footer navigation" style="--footer-columns:4"><div class="SiteFooter-module-scss-module__JdOqwq__columnSection"><div class="SiteFooter-module-scss-module__JdOqwq__listSection"><h3 class="body-4 bold">Products</h3><ul class="SiteFooter-module-scss-module__JdOqwq__list"><li><a href="https://claude.com/product/overview" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Claude</a></li><li><a href="https://claude.com/product/claude-code" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Claude Code</a></li><li><a href="https://claude.com/product/claude-code/enterprise" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Claude Code Enterprise</a></li><li><a href="https://claude.com/product/cowork" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Claude Cowork</a></li><li><a href="https://claude.com/product/tag" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">@Claude</a></li><li><a href="https://claude.com/product/design" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Claude Design</a></li><li><a href="https://claude.com/product/claude-science" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Claude Science</a></li><li><a href="https://claude.com/product/claude-security" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Claude Security</a></li><li><a href="https://claude.com/claude-in-chrome" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Claude in Chrome</a></li><li><a href="https://claude.com/claude-for-microsoft-365" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Claude for Microsoft 365</a></li><li><a href="https://www.claude.com/skills" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Skills</a></li><li><a href="https://claude.ai/download" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Download app</a></li><li><a href="https://claude.com/pricing" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Pricing</a></li><li><a href="https://claude.ai/" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Log in to Claude</a></li></ul></div><div class="SiteFooter-module-scss-module__JdOqwq__listSection"><h3 class="body-4 bold">Models</h3><ul class="SiteFooter-module-scss-module__JdOqwq__list"><li><a href="https://www.anthropic.com/claude/mythos" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Mythos</a></li><li><a href="https://www.anthropic.com/claude/fable" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Fable</a></li><li><a href="https://www.anthropic.com/claude/opus" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Opus</a></li><li><a href="https://www.anthropic.com/claude/sonnet" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Sonnet</a></li><li><a href="https://www.anthropic.com/claude/haiku" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Haiku</a></li></ul></div></div><div class="SiteFooter-module-scss-module__JdOqwq__columnSection"><div class="SiteFooter-module-scss-module__JdOqwq__listSection"><h3 class="body-4 bold">Solutions</h3><ul class="SiteFooter-module-scss-module__JdOqwq__list"><li><a href="https://claude.com/solutions/agents" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">AI agents</a></li><li><a href="https://claude.com/solutions/code-modernization" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Code modernization</a></li><li><a href="https://claude.com/solutions/coding" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Coding</a></li><li><a href="https://claude.com/solutions/commerce" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Commerce</a></li><li><a href="https://claude.com/solutions/customer-support" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Customer support</a></li><li><a href="https://claude.com/solutions/cybersecurity" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Cybersecurity</a></li><li><a href="https://claude.com/solutions/enterprise" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Enterprise</a></li><li><a href="https://claude.com/solutions/financial-services" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Financial services</a></li><li><a href="https://claude.com/solutions/government" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Government</a></li><li><a href="https://claude.com/solutions/healthcare" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Healthcare</a></li><li><a href="https://claude.com/solutions/education" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Higher education</a></li><li><a href="https://claude.com/solutions/teachers" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">K-12 teachers</a></li><li><a href="https://claude.com/solutions/legal" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Legal</a></li><li><a href="https://claude.com/solutions/life-sciences" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Life sciences</a></li><li><a href="https://claude.com/solutions/nonprofits" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Nonprofits</a></li><li><a href="https://claude.com/solutions/small-business" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Small business</a></li></ul></div><div class="SiteFooter-module-scss-module__JdOqwq__listSection"><h3 class="body-4 bold">Claude Platform</h3><ul class="SiteFooter-module-scss-module__JdOqwq__list"><li><a href="https://claude.com/platform/api" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Overview</a></li><li><a href="https://platform.claude.com/docs" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Developer docs</a></li><li><a href="https://claude.com/pricing#api" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Pricing</a></li><li><a href="https://claude.com/ecosystem" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Ecosystem</a></li><li><a href="https://claude.com/platform/marketplace" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Marketplace</a></li><li><a href="https://claude.com/regional-compliance" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Regional compliance</a></li><li><a href="https://claude.com/partners/claude-on-aws" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Claude on AWS</a></li><li><a href="https://claude.com/partners/google-cloud-vertex-ai" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Google Cloud</a></li><li><a href="https://claude.com/partners/microsoft-foundry" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Microsoft Foundry</a></li><li><a href="https://platform.claude.com/" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Console login</a></li></ul></div></div><div class="SiteFooter-module-scss-module__JdOqwq__columnSection"><div class="SiteFooter-module-scss-module__JdOqwq__listSection"><h3 class="body-4 bold">Resources</h3><ul class="SiteFooter-module-scss-module__JdOqwq__list"><li><a href="https://claude.com/blog" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Blog</a></li><li><a href="https://claude.com/partners" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Claude partner network</a></li><li><a href="https://claude.com/community" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Community</a></li><li><a href="https://claude.com/connectors" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Connectors</a></li><li><a href="https://academy.claude.com" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Courses</a></li><li><a href="https://claude.com/customers" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Customer stories</a></li><li><a href="/engineering" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Engineering at Anthropic</a></li><li><a href="/events" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Events</a></li><li><a href="https://claude.com/plugins" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Plugins</a></li><li><a href="https://claude.com/partners/powered-by-claude" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Powered by Claude</a></li><li><a href="https://claude.com/partners/services" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Service partners</a></li><li><a href="https://claude.com/resources/tutorials" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Tutorials</a></li><li><a href="https://claude.com/resources/use-cases" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Use cases</a></li></ul></div><div class="SiteFooter-module-scss-module__JdOqwq__listSection"><h3 class="body-4 bold">Programs</h3><ul class="SiteFooter-module-scss-module__JdOqwq__list"><li><a href="https://claude.com/programs/startups" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Startups</a></li><li><a href="https://claude.com/programs/team-plan-for-scientists" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Scientists</a></li></ul></div><div class="SiteFooter-module-scss-module__JdOqwq__listSection"><h3 class="body-4 bold">Help and security</h3><ul class="SiteFooter-module-scss-module__JdOqwq__list"><li><a href="https://www.anthropic.com/supported-countries" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Availability</a></li><li><a href="https://status.anthropic.com/" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Status</a></li><li><a href="https://support.claude.com/en/" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4" target="_blank" rel="noopener noreferrer">Support center</a></li></ul></div></div><div class="SiteFooter-module-scss-module__JdOqwq__columnSection"><div class="SiteFooter-module-scss-module__JdOqwq__listSection"><h3 class="body-4 bold">Company</h3><ul class="SiteFooter-module-scss-module__JdOqwq__list"><li><a href="/company" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Anthropic</a></li><li><a href="/careers" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Careers</a></li><li><a href="/company/leadership" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Leadership</a></li><li><a href="/policy" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Policy</a></li><li><a href="/economic-futures" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Economic Futures</a></li><li><a href="/research" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Research</a></li><li><a href="/news" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">News</a></li><li><a href="/constitution" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Claude’s Constitution</a></li><li><a href="/claude-corps" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Claude Corps</a></li><li><a href="https://www.anthropic.com/path-to-hope" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Keep thinking</a></li><li><a href="/policy-on-the-ai-exponential" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Policy on the AI Exponential</a></li><li><a href="https://www.anthropic.com/news/announcing-our-updated-responsible-scaling-policy" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Responsible Scaling Policy</a></li><li><a href="https://trust.anthropic.com/" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Security and compliance</a></li><li><a href="/transparency" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Transparency</a></li></ul></div><div class="SiteFooter-module-scss-module__JdOqwq__listSection"><h3 class="body-4 bold">Terms and policies</h3><ul class="SiteFooter-module-scss-module__JdOqwq__list"><li><a href="https://www.anthropic.com/legal/privacy" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Privacy policy</a></li><li><a href="https://www.anthropic.com/legal/consumer-health-data-privacy-policy" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Consumer health data privacy policy</a></li><li><a href="https://www.anthropic.com/responsible-disclosure-policy" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Responsible disclosure policy</a></li><li><a href="https://www.anthropic.com/legal/commercial-terms" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Terms of service: Commercial</a></li><li><a href="https://www.anthropic.com/legal/consumer-terms" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Terms of service: Consumer</a></li><li><a href="https://anthropic.com/legal/k12-terms" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Terms of Service: US K-12</a></li><li><a href="https://anthropic.com/legal/k12-dpa" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Data Processing Agreement: US K-12</a></li><li><a href="https://www.anthropic.com/legal/aup" class="SiteFooter-module-scss-module__JdOqwq__listItem body-4">Usage policy</a></li></ul></div></div></nav><div class="SiteFooter-module-scss-module__JdOqwq__socialWrapper"><small class="body-4 SiteFooter-module-scss-module__JdOqwq__copyright" role="contentinfo"><!--$-->© 2026 Anthropic PBC<!--/$--></small><ul class="SiteFooter-module-scss-module__JdOqwq__socialIcons" role="navigation" aria-label="Social media links"><li><a href="https://www.linkedin.com/company/anthropicresearch" aria-label="Visit our LinkedIn page" target="_blank" rel="noopener noreferrer"><svg class="Icon-module-scss-module__lqbdHG__icon" width="24" height="24" viewBox="0 0 32 32"><path d="M25.8182 4H6.18182C4.97636 4 4 4.97636 4 6.18182V25.8182C4 27.0236 4.97636 28 6.18182 28H25.8182C27.0236 28 28 27.0236 28 25.8182V6.18182C28 4.97636 27.0236 4 25.8182 4ZM11.5862 23.6364H8.368V13.2815H11.5862V23.6364ZM9.94436 11.8011C8.90691 11.8011 8.068 10.96 8.068 9.92473C8.068 8.88945 8.908 8.04945 9.94436 8.04945C10.9785 8.04945 11.8196 8.89055 11.8196 9.92473C11.8196 10.96 10.9785 11.8011 9.94436 11.8011ZM23.6407 23.6364H20.4247V18.6007C20.4247 17.3996 20.4029 15.8549 18.7524 15.8549C17.0778 15.8549 16.8204 17.1629 16.8204 18.5135V23.6364H13.6044V13.2815H16.6916V14.6964H16.7353C17.1651 13.8825 18.2145 13.024 19.78 13.024C23.0385 13.024 23.6407 15.1687 23.6407 17.9571V23.6364Z" fill="#b0aea5"></path></svg></a></li><li><a href="https://x.com/AnthropicAI" aria-label="Visit our X (formerly Twitter) profile" target="_blank" rel="noopener noreferrer"><svg class="Icon-module-scss-module__lqbdHG__icon" width="24" height="24" viewBox="0 0 32 32"><path d="M28 28L18.6145 14.0124L18.6305 14.0255L27.0929 4H24.265L17.3713 12.16L11.8968 4H4.48021L13.2425 17.0593L13.2414 17.0582L4 28H6.82792L14.4921 18.9215L20.5834 28H28ZM10.7763 6.18182L23.9449 25.8182H21.7039L8.52468 6.18182H10.7763Z" fill="#b0aea5"></path></svg></a></li><li><a href="https://www.youtube.com/@anthropic-ai" aria-label="Visit our YouTube channel" target="_blank" rel="noopener noreferrer"><svg class="Icon-module-scss-module__lqbdHG__icon" width="24" height="24" viewBox="0 0 32 32"><path d="M29.2184 9.4375C28.9596 8.06299 27.7263 7.06201 26.2951 6.74951C24.1533 6.3125 20.1896 6 15.901 6C11.615 6 7.58782 6.3125 5.44354 6.74951C4.01486 7.06201 2.77905 7.99951 2.52021 9.4375C2.25884 11 2 13.1875 2 16C2 18.8125 2.25884 21 2.58365 22.5625C2.84502 23.937 4.0783 24.938 5.50698 25.2505C7.78068 25.6875 11.6784 26 15.967 26C20.2556 26 24.1533 25.6875 26.427 25.2505C27.8557 24.938 29.089 24.0005 29.3504 22.5625C29.6092 21 29.934 18.749 30 16C29.868 13.1875 29.5432 11 29.2184 9.4375ZM12.3941 20.375V11.625L20.319 16L12.3941 20.375Z" fill="#b0aea5"></path></svg></a></li></ul></div></div></footer><!--$--><!--/$--><script src="/_next/static/chunks/138-1_49eoue5.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n4:I[339756,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\"],\"default\"]\n5:I[837457,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\"],\"default\"]\n7:I[897367,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\"],\"OutletBoundary\"]\n8:\"$Sreact.suspense\"\nb:I[897367,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\"],\"ViewportBoundary\"]\nd:I[897367,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\"],\"MetadataBoundary\"]\nf:I[168027,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\"],\"default\",1]\n11:I[649551,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\"],\"default\"]\n12:I[449637,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\"],\"default\"]\n13:I[96155,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\"],\"default\"]\n14:I[14538,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\"],\"AntTagManager\"]\n15:I[555511,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\"],\"default\"]\n17:I[606617,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"default\"]\n18:I[837061,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"default\"]\n1d:I[307003,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/1-9e3zcgh8gk1.js\",\"/_next/static/chunks/0od98pyc9u2nj.js\",\"/_next/static/chunks/0od08xnx_58ui.js\",\"/_next/static/chunks/0b2dmya4y8ovs.js\"],\"default\"]\n1e:I[474716,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"default\"]\n1f:I[645533,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\""])</script><script>self.__next_f.push([1,"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"IconMailbox\"]\n20:I[645533,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"IconHelp\"]\n21:I[645533,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"IconDownload\"]\n22:I[706586,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"default\"]\n26:I[645533,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"IconLogoMark\"]\n2d:I[670181,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"default\"]\n32:I[168875,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"ConsentContainer\"]\n35:I[855440,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chu"])</script><script>self.__next_f.push([1,"nks/3-fnghd0zoogo.js\"],\"default\"]\n36:I[645533,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"IconLinkedIn\"]\n37:I[645533,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"IconX\"]\n38:I[645533,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"/_next/static/chunks/0e3-jir0v5afw.js\",\"/_next/static/chunks/0ld574-gx-fgb.js\",\"/_next/static/chunks/3k_473ybucr6n.js\",\"/_next/static/chunks/09kr574z319ye.js\",\"/_next/static/chunks/29nzh0illa0z0.js\",\"/_next/static/chunks/3euk033p3vkb6.js\",\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"/_next/static/chunks/1mcakwknehjsg.js\",\"/_next/static/chunks/2142y_r3r849c.js\",\"/_next/static/chunks/3-fnghd0zoogo.js\"],\"IconYoutube\"]\n39:I[27201,[\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"/_next/static/chunks/1ntn7efqc-iiw.js\"],\"IconMark\"]\n:HL[\"/_next/static/chunks/2gepcixj9k_19.css\",\"style\"]\n:HL[\"/_next/static/chunks/2pnrpp88lh_gg.css\",\"style\"]\n:HL[\"/_next/static/media/AnthropicMono_Italic_Web-s.p.0x1wr-4z1xgw3.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/AnthropicMono_Roman_Web-s.p.16xhthj2n-pap.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/AnthropicSans_Italic_Web-s.p.212cqpul8-axk.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/AnthropicSans_Roman_Web-s.p.1e3n6bt4oqimz.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/AnthropicSerif_Italic_Web-s.p.1fjksu1uimpf3.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/AnthropicSerif_Roman_Web-s.p.0twp0vwi-lncj.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/chunks/0jlkzpw9ac_ue.css\",\"style\"]\n:HL[\"/_next/static/chunks/1n17vgd8rsel0.css\",\"style\"]\n:HL[\"/_next/static/chunks/0hpj44a23iwyo.css\",\"style\"]\n:HL[\"/_next/static/chunks/0rgpq5sb7ts3i.css\",\"style\"]\n:HL[\"/_next/static/chunks/1plsl93aq761e.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"news\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"(site)\",{\"children\":[[\"slug\",\"news\",\"oc\",null],{\"children\":[\"__PAGE__\",{}]}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/2gepcixj9k_19.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/2yl1jv4w6po1z.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/1ntn7efqc-iiw.js\",\"async\":true,\"nonce\":\"$undefined\"}]],\"$L2\"]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/2pnrpp88lh_gg.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0e3-jir0v5afw.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/0ld574-gx-fgb.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-2\",{\"src\":\"/_next/static/chunks/3k_473ybucr6n.js\",\"async\":true,\"nonce\":\"$undefined\"}]],\"$L3\"]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[\"$L6\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0jlkzpw9ac_ue.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/1n17vgd8rsel0.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"2\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0hpj44a23iwyo.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"3\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0rgpq5sb7ts3i.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/09kr574z319ye.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/29nzh0illa0z0.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-2\",{\"src\":\"/_next/static/chunks/3euk033p3vkb6.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-3\",{\"src\":\"/_next/static/chunks/1m2tuo2yn9z9q.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-4\",{\"src\":\"/_next/static/chunks/0e3v21lqmnrgx.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-5\",{\"src\":\"/_next/static/chunks/1mcakwknehjsg.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-6\",{\"src\":\"/_next/static/chunks/2142y_r3r849c.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-7\",{\"src\":\"/_next/static/chunks/3-fnghd0zoogo.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L7\",null,{\"children\":[\"$\",\"$8\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@9\"}]}]]}],{},null,false,null]},null,false,\"$@a\"]},null,false,null]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$Lb\",null,{\"children\":\"$Lc\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Ld\",null,{\"children\":[\"$\",\"$8\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Le\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$f\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/2gepcixj9k_19.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":false,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"wP952O_AQuPBXw3S5cptU\"}\n"])</script><script>self.__next_f.push([1,"10:[]\na:\"$W10\"\n"])</script><script>self.__next_f.push([1,"2:[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"anthropicsans_dce02d96-module__tEBbKW__variable anthropicserif_e7e46c4-module__uImRTq__variable anthropicmono_fae19af3-module__c5XAsG__variable copernicus_e225fe92-module__gIXlfG__variable styrenea_ba30709d-module__X1taUa__variable styreneb_ef815608-module__QsOdUa__variable tiempostext_b1e9a056-module__lQ_52W__variable jetbrainsmono_4a81325a-module__1wasHq__variable\",\"children\":[\"$\",\"body\",null,{\"children\":[[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}],false]}]}]\n"])</script><script>self.__next_f.push([1,"3:[\"$\",\"$L11\",null,{\"gpcDetected\":false,\"children\":[\"$\",\"$L12\",null,{\"country\":\"CA\",\"children\":[[\"$\",\"$L13\",null,{}],[\"$\",\"$L14\",null,{}],[\"$\",\"$L15\",null,{}],[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[\"$L16\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0jlkzpw9ac_ue.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/1plsl93aq761e.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}]}]\nc:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"2\",{\"name\":\"theme-color\",\"content\":\"#141413\"}]]\n19:T6a7,"])</script><script>self.__next_f.push([1,"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb/2wBDAFA3PEY8MlBGQUZaVVBfeMiCeG5uePWvuZHI////////////////////////////////////////////////////2wBDAVVaWnhpeOuCguv/////////////////////////////////////////////////////////////////////////wAARCAB4AHgDASIAAhEBAxEB/8QAGQABAQEBAQEAAAAAAAAAAAAAAAEEAwIF/8QAKxAAAgEDAwQBAwQDAAAAAAAAAAECAxExBCFREhMiQWEFUpEUQnGhweHw/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AMQAAAAAAVJt2SuwCTk7JNv4DTTs1Zn0dJS7dK8laTycfqCj4PbqYGMAAAAABRcCAAAAAKk5OyTb+C9ud7dEr8WNn09R6Jv91/6Omsm4UfF2bdgMfZjT3rSs/tju/wDQ7zjtSgoX9rd/k5Ri5yUVu2zfS0kabUm3KSxwBwlOWnh0qT7kt5PgzylKbvJtv5Em3JuTu/ZAAAAAFQBkAAAAAAAPUZyg7xk0/g0+Wp0ts1IP8/8Af4Mh9TS9P6eHTxv/ACB86LdKonbeLwzfT1UKvjHxm8XM+va7sbZtuZcAWScZNSyskN9OnHU0ozqJ9WLr2cNVp1RtKL8Xz6AzgACoBEAAAAAAAAAqTbSW7ZoqzlQhGjCVmleTXJpoaaFNKTV58s4VKdGlUbqzlOT36UBmjGdSXinJnbs06W9ad39kSVNVJrpglTjwjgBtp62C8XBxisW3OOp1HeaUVaK5OAAAAAV5IV5AgAAAAAAANkNdaFpQu1w8mWpN1Juby2eRYAAAAAAAAAXJABWiFuGBAABVkBZHsB6A+AuADAGAFuCFwHyBAAAAAAvohfQEAAAr5IVALi4aIAKmQAeiIgArRC35FgIC2FgIVjBAAAAAAAAAAAAAAAAAFy3AAgAAAAD/2Q=="])</script><script>self.__next_f.push([1,"1a:T6a7,"])</script><script>self.__next_f.push([1,"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb/2wBDAFA3PEY8MlBGQUZaVVBfeMiCeG5uePWvuZHI////////////////////////////////////////////////////2wBDAVVaWnhpeOuCguv/////////////////////////////////////////////////////////////////////////wAARCAB4AHgDASIAAhEBAxEB/8QAGQABAQEBAQEAAAAAAAAAAAAAAAEEAwIF/8QAKxAAAgEDAwQBAwQDAAAAAAAAAAECAxExBCFREhMiQWEFUpEUQnGhweHw/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AMQAAAAAAVJt2SuwCTk7JNv4DTTs1Zn0dJS7dK8laTycfqCj4PbqYGMAAAAABRcCAAAAAKk5OyTb+C9ud7dEr8WNn09R6Jv91/6Omsm4UfF2bdgMfZjT3rSs/tju/wDQ7zjtSgoX9rd/k5Ri5yUVu2zfS0kabUm3KSxwBwlOWnh0qT7kt5PgzylKbvJtv5Em3JuTu/ZAAAAAFQBkAAAAAAAPUZyg7xk0/g0+Wp0ts1IP8/8Af4Mh9TS9P6eHTxv/ACB86LdKonbeLwzfT1UKvjHxm8XM+va7sbZtuZcAWScZNSyskN9OnHU0ozqJ9WLr2cNVp1RtKL8Xz6AzgACoBEAAAAAAAAAqTbSW7ZoqzlQhGjCVmleTXJpoaaFNKTV58s4VKdGlUbqzlOT36UBmjGdSXinJnbs06W9ad39kSVNVJrpglTjwjgBtp62C8XBxisW3OOp1HeaUVaK5OAAAAAV5IV5AgAAAAAAANkNdaFpQu1w8mWpN1Juby2eRYAAAAAAAAAXJABWiFuGBAABVkBZHsB6A+AuADAGAFuCFwHyBAAAAAAvohfQEAAAr5IVALi4aIAKmQAeiIgArRC35FgIC2FgIVjBAAAAAAAAAAAAAAAAAFy3AAgAAAAD/2Q=="])</script><script>self.__next_f.push([1,"6:[\"$\",\"$L17\",null,{\"children\":[null,[\"$\",\"$L18\",null,{\"isMinimalNavigation\":\"$undefined\",\"siteSettings\":{\"_createdAt\":\"2023-11-03T16:49:36Z\",\"_id\":\"13c6e1a1-6f38-400c-ae18-89d73b6ba991\",\"_rev\":\"XQe4R6LiqiY3ST7NppsXi8\",\"_system\":{\"base\":{\"id\":\"13c6e1a1-6f38-400c-ae18-89d73b6ba991\",\"rev\":\"dmV1nc4vpFyNxsAbKRJhjH\"}},\"_type\":\"siteSettings\",\"_updatedAt\":\"2026-09-11T15:26:27Z\",\"announcement\":null,\"claudeCta\":{\"desktopCtas\":null,\"mobileCtas\":[{\"title\":\"Log in to Claude\",\"url\":\"https://claude.ai/login\"},{\"title\":\"Download app\",\"url\":\"https://claude.ai/download\"}],\"sections\":[{\"category\":\"About Claude\",\"links\":[{\"title\":\"Overview\",\"url\":\"https://claude.com/product/overview\"},{\"title\":\"Pricing\",\"url\":\"https://claude.com/pricing\"},{\"title\":\"Contact sales\",\"url\":\"https://claude.com/contact-sales\"}]},{\"category\":\"Models\",\"links\":[{\"title\":\"Mythos\",\"url\":\"/claude/mythos\"},{\"title\":\"Fable\",\"url\":\"/claude/fable\"},{\"title\":\"Opus\",\"url\":\"/claude/opus\"},{\"title\":\"Sonnet\",\"url\":\"/claude/sonnet\"},{\"title\":\"Haiku\",\"url\":\"/claude/haiku\"}]},{\"category\":\"Log in\",\"links\":[{\"title\":\"Claude.ai\",\"url\":\"https://claude.ai\"},{\"title\":\"Claude Console\",\"url\":\"https://platform.claude.com/\"}]}],\"title\":\"Try Claude\",\"url\":\"https://claude.ai/\"},\"copyright\":\"© 2026 Anthropic PBC\",\"copyrightEu\":\"© 2026 Anthropic PBC. Services in the EU are provided by Anthropic Ireland Limited.\",\"footer\":{\"items\":[{\"_key\":\"84532931ef2c\",\"_type\":\"item\",\"content\":[{\"_key\":\"9b0c0eb1f85d\",\"_type\":\"block\",\"children\":[{\"_key\":\"8272ab6d0eb4\",\"_type\":\"span\",\"marks\":[],\"text\":\"Anthropic exists to ensure the world safely makes the transition through transformative AI. We are a public benefit corporation dedicated to building frontier AI systems that are reliable, interpretable, and trustworthy.\"}],\"markDefs\":[],\"style\":\"normal\"}],\"title\":\"Our mission\"},{\"_key\":\"9abb17c23057\",\"_type\":\"links\",\"category\":\"Log in\",\"links\":[{\"_key\":\"1a42aa0d0289\",\"_ref\":\"1f59436a-2330-4e42-a46e-386e058f8c5d\",\"_type\":\"reference\"},{\"_key\":\"fc4c7c24a145\",\"_ref\":\"5516a01a-276b-41c2-9ac3-87afe2c15ee3\",\"_type\":\"reference\"}]}],\"links\":[{\"_key\":\"a37fc8514b0e\",\"_type\":\"links\",\"category\":\"Research\",\"links\":[{\"_key\":\"425b3b6b7a4d\",\"_ref\":\"48d94ab5-7352-44e3-8f17-4d875b60e187\",\"_type\":\"reference\"},{\"_key\":\"056e2f3f972f\",\"_ref\":\"1aece7e6-62d6-4852-8fdf-ef019fd0c9fa\",\"_type\":\"reference\"},{\"_key\":\"5b1394beb0ce\",\"_ref\":\"bd42abcb-a6af-4a45-981f-db622b38099f\",\"_type\":\"reference\"},{\"_key\":\"3d652fadc860\",\"_ref\":\"c9825846-5e78-4e23-81b8-6383998995fd\",\"_type\":\"reference\"},{\"_key\":\"73e7067ea96a\",\"_ref\":\"3a82f6ce-ffd6-4bb9-8b79-4ce145deb525\",\"_type\":\"reference\"},{\"_key\":\"84ff13e8bf8f\",\"_ref\":\"a23d27ca-8747-44e6-bb5d-85420fca5e4a\",\"_type\":\"reference\"},{\"_key\":\"7d5bf81ce1d7\",\"_ref\":\"00090d65-a984-4a6a-9ab0-0d1f28ab4a3d\",\"_type\":\"reference\"},{\"_key\":\"e644a30fcede\",\"_ref\":\"5c868a2a-18ae-4989-84c0-070e77c8192b\",\"_type\":\"reference\"}]},{\"_key\":\"36c16b825f48\",\"_type\":\"links\",\"category\":\"Company\",\"links\":[{\"_key\":\"ddda2c0403e9\",\"_ref\":\"bff5e01a-fc87-4866-8cbf-7c5d776ec041\",\"_type\":\"reference\"},{\"_key\":\"ada58b947b0b\",\"_ref\":\"8c1ba848-8290-442b-a7bb-306958e605d5\",\"_type\":\"reference\"},{\"_key\":\"95499f2cdee3\",\"_ref\":\"a891556e-6bc1-4219-a774-5a321e8fd959\",\"_type\":\"reference\"},{\"_key\":\"ccd7bae80fd0\",\"_ref\":\"9c3b7958-615f-4732-8607-489d88857b08\",\"_type\":\"reference\"},{\"_key\":\"24b9d842852b\",\"_ref\":\"f41cda79-ae9c-4b89-a34b-0b02a083e61c\",\"_type\":\"reference\"},{\"_key\":\"7b06f76b370f\",\"_ref\":\"27b23089-5dd9-4c69-bea1-01e811584807\",\"_type\":\"reference\"},{\"_key\":\"a9644ed69d5c\",\"_ref\":\"500e9c73-aa2b-4b65-bd29-4e4587f76cb1\",\"_type\":\"reference\"},{\"_key\":\"8a28cdfd8572\",\"_ref\":\"b03848c9-1ace-4d5a-9afd-bda105832b62\",\"_type\":\"reference\"},{\"_key\":\"a0ac6f7a195a\",\"_ref\":\"24b8f488-80e3-4a61-8616-fa82c091e836\",\"_type\":\"reference\"},{\"_key\":\"94afa9832188\",\"_ref\":\"73a59169-4f0f-47ce-ad13-72356dc026e5\",\"_type\":\"reference\"},{\"_key\":\"4517a7394a42\",\"_ref\":\"856229e6-c91d-4a3b-9cf6-77fe5f6fe2be\",\"_type\":\"reference\"}]},{\"_key\":\"034e9f715467\",\"_type\":\"linkGroup\",\"links\":[{\"_key\":\"3e5cfd347238\",\"_ref\":\"992d1e7f-eecd-4288-b39a-844867946f79\",\"_type\":\"reference\"},{\"_key\":\"f974656ac4f7\",\"_ref\":\"5c4cd3b6-6038-4e1b-a0b7-a3a31f349272\",\"_type\":\"reference\"},{\"_key\":\"df79b690d14f\",\"_ref\":\"92507305-15ac-43eb-a026-22f8f1e3d661\",\"_type\":\"reference\"},{\"_key\":\"61d66bad1e87\",\"_ref\":\"da2ecb16-93d4-4759-9908-51fa41cfc114\",\"_type\":\"reference\"}],\"title\":\"Programs\"},{\"_key\":\"7ea0130887a6\",\"_type\":\"links\",\"category\":\"Models\",\"links\":[{\"_key\":\"3047d6078aa3\",\"_ref\":\"8119058e-9287-40d5-8e5a-06eec2450306\",\"_type\":\"reference\"},{\"_key\":\"59be6b557375\",\"_ref\":\"81c67ac5-0093-47d4-904c-d0f0ceb60c1d\",\"_type\":\"reference\"},{\"_key\":\"7943ec60c5fa\",\"_ref\":\"6fed18e6-19f4-4d94-a13f-f54bb80b9043\",\"_type\":\"reference\"},{\"_key\":\"d4b6b7eea2d7\",\"_ref\":\"726b0909-ee85-4129-ae6d-53bf8381f1df\",\"_type\":\"reference\"},{\"_key\":\"0e330b84e1fb\",\"_ref\":\"4c8ae521-3fe6-4500-9b0a-69ae3c705423\",\"_type\":\"reference\"}]},{\"_key\":\"3828e0ead99f\",\"_type\":\"links\",\"category\":\"Product\",\"links\":[{\"_key\":\"2eb3c8bff3c0\",\"_ref\":\"871fb3f9-af66-429f-8285-971fc2e2e995\",\"_type\":\"reference\"},{\"_key\":\"019896bf84f4\",\"_ref\":\"0266dfc7-1049-45c4-9abc-5956b6b9869d\",\"_type\":\"reference\"},{\"_key\":\"f03782aa7af4\",\"_ref\":\"a9c57922-da84-4f7f-abfd-914294aa344a\",\"_type\":\"reference\"},{\"_key\":\"c2dba8b47e18\",\"_ref\":\"9500e82c-2f57-4291-8db2-8033eade237d\",\"_type\":\"reference\"},{\"_key\":\"03ab6cc00817\",\"_ref\":\"14b64039-a1cc-443c-8214-a1619362ecfe\",\"_type\":\"reference\"},{\"_key\":\"ea2dd9f1ed33\",\"_ref\":\"18319b35-2c75-4821-8b1c-c18599553f8d\",\"_type\":\"reference\"},{\"_key\":\"c7cf1f44f95e\",\"_ref\":\"62e2517f-5e80-4172-a26d-94af45f264d4\",\"_type\":\"reference\"},{\"_key\":\"fd4360d2b525\",\"_ref\":\"186bb63f-2d7a-4cb1-b492-a468ec36bf72\",\"_type\":\"reference\"},{\"_key\":\"6acfa36e7a07\",\"_ref\":\"e710ac33-2048-43a9-a081-a9a70aeb327c\",\"_type\":\"reference\"},{\"_key\":\"1646ee221928\",\"_ref\":\"52fb0953-4eec-4845-9a36-a689d724022b\",\"_type\":\"reference\"},{\"_key\":\"543d57485889\",\"_ref\":\"a096d397-41cf-4b99-86e4-17761fa1a985\",\"_type\":\"reference\"},{\"_key\":\"da6d1cadaf30\",\"_ref\":\"97adc62e-06d9-489f-b957-6fd670da4cc8\",\"_type\":\"reference\"},{\"_key\":\"62f0bc80e275\",\"_ref\":\"bd190763-f34a-4ba6-9848-f35991239b77\",\"_type\":\"reference\"},{\"_key\":\"9b273e667a91\",\"_ref\":\"f77f9fb1-350f-4383-9205-5e72408121d0\",\"_type\":\"reference\"},{\"_key\":\"daca903791f4\",\"_ref\":\"1ae847b6-2fad-4ed5-ac53-3af1394b381b\",\"_type\":\"reference\"}]},{\"_key\":\"3eb15f18fc50\",\"_type\":\"links\",\"category\":\"Resources\",\"links\":[{\"_key\":\"4c2e2c3f4f4c\",\"_ref\":\"22ba8fcf-12ed-4858-b162-ca8cb047ca1e\",\"_type\":\"reference\"},{\"_key\":\"5a267656a40d\",\"_ref\":\"7ad029d2-5a93-41a1-ace7-dd1e0e2f0a1b\",\"_type\":\"reference\"},{\"_key\":\"bb052051a44a\",\"_ref\":\"53c31bcb-e9d4-4cd1-92dd-0231b153fc01\",\"_type\":\"reference\"},{\"_key\":\"4cac470753d8\",\"_ref\":\"dce06d65-2107-407e-87a4-f08fd0cfb955\",\"_type\":\"reference\"},{\"_key\":\"8750d5263533\",\"_ref\":\"679500a5-eeb6-41a6-a619-7db2f3d5efd1\",\"_type\":\"reference\"},{\"_key\":\"b5e0bf97ef95\",\"_ref\":\"613a6fec-0d63-4008-a6b2-f5016cfea657\",\"_type\":\"reference\"},{\"_key\":\"789c3eb8736d\",\"_ref\":\"aa6b1be3-0483-408a-b1dd-960c0adc3516\",\"_type\":\"reference\"},{\"_key\":\"6bfc2d016516\",\"_ref\":\"3dcaaf36-d5f4-494e-b165-2139174f9bd3\",\"_type\":\"reference\"},{\"_key\":\"2f5847c020ed\",\"_ref\":\"8bfb6928-304a-42e0-a2c9-904b264c33ba\",\"_type\":\"reference\"},{\"_key\":\"45bb5747ef83\",\"_ref\":\"1a343724-b052-47f1-9362-388391fc42be\",\"_type\":\"reference\"},{\"_key\":\"8146509aea24\",\"_ref\":\"0281537d-d8e6-4748-a6db-ab77d468baea\",\"_type\":\"reference\"},{\"_key\":\"c79d07ca4ca7\",\"_ref\":\"b73a3a2c-9171-4d39-88c8-e986195ab0c2\",\"_type\":\"reference\"},{\"_key\":\"5443c6992ca1\",\"_ref\":\"34dfe604-dcd2-45b4-89e8-123f70a9c39a\",\"_type\":\"reference\"},{\"_key\":\"bbddce176e46\",\"_ref\":\"9f08c7d6-f2ba-4e88-94ef-7b2f0d9264a9\",\"_type\":\"reference\"},{\"_key\":\"7ae37e5e6d51\",\"_ref\":\"8d2d4f24-c4c7-45bb-9c8d-13a2ef233ba1\",\"_type\":\"reference\"}]},{\"_key\":\"a1d6f557384d\",\"_type\":\"links\",\"category\":\"Solutions\",\"links\":[{\"_key\":\"69ed8fd67e49\",\"_ref\":\"4b79685e-d504-4e0e-a4b2-14f23e04e6bc\",\"_type\":\"reference\"},{\"_key\":\"47e081170c43\",\"_ref\":\"5359f2ce-1fd8-4279-86ba-a4d5253b70d6\",\"_type\":\"reference\"},{\"_key\":\"84c155cbe14e\",\"_ref\":\"6760c56c-eb85-4d48-9cb1-7a6f41174d40\",\"_type\":\"reference\"},{\"_key\":\"768e6bc8fbbe\",\"_ref\":\"6fed0b2f-d33c-4c8b-9cee-947025748c22\",\"_type\":\"reference\"},{\"_key\":\"e1c25a67608b\",\"_ref\":\"527f5f68-8c55-440b-8783-8429afb36661\",\"_type\":\"reference\"},{\"_key\":\"47730ecff611\",\"_ref\":\"d1ca7928-dd04-4696-87d0-9b8c82781e95\",\"_type\":\"reference\"},{\"_key\":\"913adecdaa9a\",\"_ref\":\"63d361c3-8d4e-4d36-9d53-a1581ec68ffd\",\"_type\":\"reference\"},{\"_key\":\"4e8e983019cd\",\"_ref\":\"732ad03e-d598-45c2-b696-862a4b453903\",\"_type\":\"reference\"},{\"_key\":\"37b07476da3e\",\"_ref\":\"8e7028f9-d78a-47a9-8fa6-245d1c406d29\",\"_type\":\"reference\"},{\"_key\":\"521b84bce9ac\",\"_ref\":\"ad23dd8b-83fb-4e51-8e65-f124b0f1d909\",\"_type\":\"reference\"},{\"_key\":\"3011ece54768\",\"_ref\":\"af757441-c063-4708-a942-626bf70a93a9\",\"_type\":\"reference\"},{\"_key\":\"73c1729b7d79\",\"_ref\":\"109858a2-45a8-4875-a7c8-2af42ae07da9\",\"_type\":\"reference\"},{\"_key\":\"27936d225265\",\"_ref\":\"ba7aaae0-5fd5-4aad-b07e-ef61908581a5\",\"_type\":\"reference\"},{\"_key\":\"e79ec921f93c\",\"_ref\":\"efec0cd1-c133-4206-b841-2652114bd0fd\",\"_type\":\"reference\"}]},{\"_key\":\"6d4642d726ed\",\"_type\":\"links\",\"category\":\"Help and security\",\"links\":[{\"_key\":\"898762dec5fb\",\"_ref\":\"7a809c60-b80c-4202-b7e9-0a3b31540be5\",\"_type\":\"reference\"},{\"_key\":\"46d072d2229e\",\"_ref\":\"f44e9c1c-db21-4ba2-998f-5919d74a08e8\",\"_type\":\"reference\"},{\"_key\":\"2d4b4b27c7b0\",\"_ref\":\"2f6d0c79-6fa6-43a4-a0da-7846f57ae878\",\"_type\":\"reference\"}]},{\"_key\":\"caee0266e006\",\"_type\":\"links\",\"category\":\"Terms and policies\",\"links\":[{\"_key\":\"ba212a88c5a1\",\"_ref\":\"a431289f-5882-42c7-8eb7-cb78dd35b342\",\"_type\":\"reference\"},{\"_key\":\"4087cb77ed91\",\"_ref\":\"4c2802e1-5e06-41fa-b17b-24228606f6b1\",\"_type\":\"reference\"},{\"_key\":\"f59a3c39b233\",\"_ref\":\"5f540a50-d93d-4b70-b65d-2cf050e43005\",\"_type\":\"reference\"},{\"_key\":\"84fea21b620c\",\"_ref\":\"1b96f86a-f30a-42cd-be3c-476d209cfe1f\",\"_type\":\"reference\"},{\"_key\":\"803424ed1062\",\"_ref\":\"b1560401-d6fb-41a2-bbf0-dc40414fbf31\",\"_type\":\"reference\"},{\"_key\":\"5fab7abf28a8\",\"_ref\":\"f5ec5068-4eb0-4c07-895e-8c66bcb04740\",\"_type\":\"reference\"},{\"_key\":\"fac7a0e29730\",\"_ref\":\"72252247-e536-490d-9f8b-5eef43e91549\",\"_type\":\"reference\"},{\"_key\":\"71b3e8629514\",\"_ref\":\"2fc03128-78c8-4173-adc9-8926dfdf6bd5\",\"_type\":\"reference\"}]}]},\"footerNavigation\":[{\"_key\":\"716b96b62292\",\"links\":[{\"title\":\"Claude\",\"url\":\"https://claude.com/product/overview\"},{\"title\":\"Claude Code\",\"url\":\"https://claude.com/product/claude-code\"},{\"title\":\"Claude Code Enterprise\",\"url\":\"https://claude.com/product/claude-code/enterprise\"},{\"title\":\"Claude Cowork\",\"url\":\"https://claude.com/product/cowork\"},{\"title\":\"@Claude\",\"url\":\"https://claude.com/product/tag\"},{\"title\":\"Claude Design\",\"url\":\"https://claude.com/product/design\"},{\"title\":\"Claude Science\",\"url\":\"https://claude.com/product/claude-science\"},{\"title\":\"Claude Security\",\"url\":\"https://claude.com/product/claude-security\"},{\"title\":\"Claude in Chrome\",\"url\":\"https://claude.com/claude-in-chrome\"},{\"title\":\"Claude for Microsoft 365\",\"url\":\"https://claude.com/claude-for-microsoft-365\"},{\"title\":\"Skills\",\"url\":\"https://www.claude.com/skills\"},{\"title\":\"Download app\",\"url\":\"https://claude.ai/download\"},{\"title\":\"Pricing\",\"url\":\"https://claude.com/pricing\"},{\"title\":\"Log in to Claude\",\"url\":\"https://claude.ai/\"}],\"title\":\"Products\"},{\"_key\":\"0229138ff25d\",\"links\":[{\"title\":\"Mythos\",\"url\":\"https://www.anthropic.com/claude/mythos\"},{\"title\":\"Fable\",\"url\":\"https://www.anthropic.com/claude/fable\"},{\"title\":\"Opus\",\"url\":\"https://www.anthropic.com/claude/opus\"},{\"title\":\"Sonnet\",\"url\":\"https://www.anthropic.com/claude/sonnet\"},{\"title\":\"Haiku\",\"url\":\"https://www.anthropic.com/claude/haiku\"}],\"title\":\"Models\"},{\"_key\":\"df2df9219e3abce95d6d83387e2d9bd6\",\"links\":[{\"title\":\"AI agents\",\"url\":\"https://claude.com/solutions/agents\"},{\"title\":\"Code modernization\",\"url\":\"https://claude.com/solutions/code-modernization\"},{\"title\":\"Coding\",\"url\":\"https://claude.com/solutions/coding\"},{\"title\":\"Commerce\",\"url\":\"https://claude.com/solutions/commerce\"},{\"title\":\"Customer support\",\"url\":\"https://claude.com/solutions/customer-support\"},{\"title\":\"Cybersecurity\",\"url\":\"https://claude.com/solutions/cybersecurity\"},{\"title\":\"Enterprise\",\"url\":\"https://claude.com/solutions/enterprise\"},{\"title\":\"Financial services\",\"url\":\"https://claude.com/solutions/financial-services\"},{\"title\":\"Government\",\"url\":\"https://claude.com/solutions/government\"},{\"title\":\"Healthcare\",\"url\":\"https://claude.com/solutions/healthcare\"},{\"title\":\"Higher education\",\"url\":\"https://claude.com/solutions/education\"},{\"title\":\"K-12 teachers\",\"url\":\"https://claude.com/solutions/teachers\"},{\"title\":\"Legal\",\"url\":\"https://claude.com/solutions/legal\"},{\"title\":\"Life sciences\",\"url\":\"https://claude.com/solutions/life-sciences\"},{\"title\":\"Nonprofits\",\"url\":\"https://claude.com/solutions/nonprofits\"},{\"title\":\"Small business\",\"url\":\"https://claude.com/solutions/small-business\"}],\"startNewColumn\":true,\"title\":\"Solutions\"},{\"_key\":\"f286ca01fc7aaabd131f347b711a971b\",\"links\":[{\"title\":\"Overview\",\"url\":\"https://claude.com/platform/api\"},{\"title\":\"Developer docs\",\"url\":\"https://platform.claude.com/docs\"},{\"title\":\"Pricing\",\"url\":\"https://claude.com/pricing#api\"},{\"title\":\"Ecosystem\",\"url\":\"https://claude.com/ecosystem\"},{\"title\":\"Marketplace\",\"url\":\"https://claude.com/platform/marketplace\"},{\"title\":\"Regional compliance\",\"url\":\"https://claude.com/regional-compliance\"},{\"title\":\"Claude on AWS\",\"url\":\"https://claude.com/partners/claude-on-aws\"},{\"title\":\"Google Cloud\",\"url\":\"https://claude.com/partners/google-cloud-vertex-ai\"},{\"title\":\"Microsoft Foundry\",\"url\":\"https://claude.com/partners/microsoft-foundry\"},{\"title\":\"Console login\",\"url\":\"https://platform.claude.com/\"}],\"title\":\"Claude Platform\"},{\"_key\":\"4b255e67f68c270e0072c7564e084e24\",\"links\":[{\"title\":\"Blog\",\"url\":\"https://claude.com/blog\"},{\"title\":\"Claude partner network\",\"url\":\"https://claude.com/partners\"},{\"title\":\"Community\",\"url\":\"https://claude.com/community\"},{\"title\":\"Connectors\",\"url\":\"https://claude.com/connectors\"},{\"title\":\"Courses\",\"url\":\"https://academy.claude.com\"},{\"title\":\"Customer stories\",\"url\":\"https://claude.com/customers\"},{\"title\":\"Engineering at Anthropic\",\"url\":\"/engineering\"},{\"title\":\"Events\",\"url\":\"/events\"},{\"title\":\"Plugins\",\"url\":\"https://claude.com/plugins\"},{\"title\":\"Powered by Claude\",\"url\":\"https://claude.com/partners/powered-by-claude\"},{\"title\":\"Service partners\",\"url\":\"https://claude.com/partners/services\"},{\"title\":\"Tutorials\",\"url\":\"https://claude.com/resources/tutorials\"},{\"title\":\"Use cases\",\"url\":\"https://claude.com/resources/use-cases\"}],\"startNewColumn\":true,\"title\":\"Resources\"},{\"_key\":\"a886dd1838335844d635f2857b25d66a\",\"links\":[{\"title\":\"Startups\",\"url\":\"https://claude.com/programs/startups\"},{\"title\":\"Scientists\",\"url\":\"https://claude.com/programs/team-plan-for-scientists\"}],\"title\":\"Programs\"},{\"_key\":\"cc0d73a7bca1d5af6c3c71c833c468be\",\"links\":[{\"title\":\"Availability\",\"url\":\"https://www.anthropic.com/supported-countries\"},{\"title\":\"Status\",\"url\":\"https://status.anthropic.com/\"},{\"title\":\"Support center\",\"url\":\"https://support.claude.com/en/\"}],\"title\":\"Help and security\"},{\"_key\":\"4f2729951e15b0b870897e0444f5f3e1\",\"links\":[{\"title\":\"Anthropic\",\"url\":\"/company\"},{\"title\":\"Careers\",\"url\":\"/careers\"},{\"title\":\"Leadership\",\"url\":\"/company/leadership\"},{\"title\":\"Policy\",\"url\":\"/policy\"},{\"title\":\"Economic Futures\",\"url\":\"/economic-futures\"},{\"title\":\"Research\",\"url\":\"/research\"},{\"title\":\"News\",\"url\":\"/news\"},{\"title\":\"Claude’s Constitution\",\"url\":\"/constitution\"},{\"title\":\"Claude Corps\",\"url\":\"/claude-corps\"},{\"title\":\"Keep thinking\",\"url\":\"https://www.anthropic.com/path-to-hope\"},{\"title\":\"Policy on the AI Exponential\",\"url\":\"/policy-on-the-ai-exponential\"},{\"title\":\"Responsible Scaling Policy\",\"url\":\"https://www.anthropic.com/news/announcing-our-updated-responsible-scaling-policy\"},{\"title\":\"Security and compliance\",\"url\":\"https://trust.anthropic.com/\"},{\"title\":\"Transparency\",\"url\":\"/transparency\"}],\"startNewColumn\":true,\"title\":\"Company\"},{\"_key\":\"3c3b033c11fa832a35d43b87d55a5364\",\"links\":[{\"title\":\"Privacy choices\",\"url\":\"#\"},{\"title\":\"Privacy policy\",\"url\":\"https://www.anthropic.com/legal/privacy\"},{\"title\":\"Consumer health data privacy policy\",\"url\":\"https://www.anthropic.com/legal/consumer-health-data-privacy-policy\"},{\"title\":\"Responsible disclosure policy\",\"url\":\"https://www.anthropic.com/responsible-disclosure-policy\"},{\"title\":\"Terms of service: Commercial\",\"url\":\"https://www.anthropic.com/legal/commercial-terms\"},{\"title\":\"Terms of service: Consumer\",\"url\":\"https://www.anthropic.com/legal/consumer-terms\"},{\"title\":\"Terms of Service: US K-12\",\"url\":\"https://anthropic.com/legal/k12-terms\"},{\"title\":\"Data Processing Agreement: US K-12\",\"url\":\"https://anthropic.com/legal/k12-dpa\"},{\"title\":\"Usage policy\",\"url\":\"https://www.anthropic.com/legal/aup\"}],\"title\":\"Terms and policies\"}],\"headerNavigation\":[{\"_key\":\"7445283cdc57\",\"category\":\"Research\",\"displayType\":\"sections\",\"sections\":[{\"_key\":\"51b9b388785c\",\"links\":[{\"title\":\"Overview\",\"url\":\"/research\"},{\"title\":\"Alignment\",\"url\":\"/research/team/alignment\"},{\"title\":\"Economics\",\"url\":\"/research/team/economics\"},{\"title\":\"Engineering\",\"url\":\"/engineering\"},{\"title\":\"Frontier Red Team\",\"url\":\"/research/team/frontier-red-team\"},{\"title\":\"Interpretability\",\"url\":\"/research/team/interpretability\"},{\"title\":\"Science\",\"url\":\"/science\"},{\"title\":\"Societal Impacts\",\"url\":\"/research/team/societal-impacts\"}]}]},{\"_key\":\"a483c7dfd38a\",\"category\":\"Policy\",\"displayType\":\"singleLink\",\"sections\":null,\"url\":\"/policy\"},{\"_key\":\"82c471bd311d\",\"category\":\"Commitments\",\"displayType\":\"sections\",\"sections\":[{\"_key\":\"675871636e4d\",\"links\":[{\"title\":\"Claude’s Constitution\",\"url\":\"/constitution\"},{\"title\":\"Claude Corps\",\"url\":\"/claude-corps\"},{\"title\":\"Policy on the AI Exponential\",\"url\":\"/policy-on-the-ai-exponential\"},{\"title\":\" Transparency\",\"url\":\"/transparency\"},{\"title\":\"Responsible Scaling Policy\",\"url\":\"/responsible-scaling-policy\"},{\"title\":\"Beneficial Deployments\",\"url\":\"/beneficial-deployments\"}],\"title\":\"Initiatives\"},{\"_key\":\"16af50a6e2dd\",\"links\":[{\"title\":\"Security and compliance\",\"url\":\"https://trust.anthropic.com/\"}],\"title\":\"Trust center\"}]},{\"_key\":\"861a11ed9931\",\"category\":\"Learn\",\"displayType\":\"sections\",\"sections\":[{\"_key\":\"9f9f720a8793\",\"links\":[{\"title\":\"Anthropic Academy\",\"url\":\"https://academy.claude.com\"},{\"title\":\"Tutorials\",\"url\":\"https://claude.com/resources/tutorials\"},{\"title\":\"Use cases\",\"url\":\"https://claude.com/resources/use-cases\"},{\"title\":\"Developer docs\",\"url\":\"https://platform.claude.com/docs\"}],\"title\":\"Learn\"},{\"_key\":\"6bd061c46b10\",\"links\":[{\"title\":\"About\",\"url\":\"/company\"},{\"title\":\"Leadership\",\"url\":\"/company/leadership\"},{\"title\":\"Careers\",\"url\":\"/careers\"},{\"title\":\"Events\",\"url\":\"/events\"}],\"title\":\"Company\"}]},{\"_key\":\"22e8d8d2923d\",\"category\":\"News\",\"displayType\":\"singleLink\",\"sections\":null,\"url\":\"/news\"}],\"internalName\":\"anthropic.com Site Settings\",\"linkedInUsername\":\"anthropicresearch\",\"menu\":{\"_type\":\"object\",\"articles\":[{\"_key\":\"1df2dd62018a\",\"_ref\":\"article-f35fc46a-6984-4475-83a2-7eaf0afd213f\",\"_type\":\"item\"},{\"_key\":\"4ca6b16e9978\",\"_ref\":\"article-1183df10-e027-40c3-bd80-3353ce4d87bb\",\"_type\":\"item\"},{\"_key\":\"6a4e35bdbabb\",\"_ref\":\"article-craft-import-7578\",\"_type\":\"item\"},{\"_key\":\"4fbb5d0e5d27\",\"_ref\":\"article-0793419f-f68a-4bcc-afee-e47fc878548b\",\"_type\":\"item\"}],\"displayType\":\"articles\",\"featuredPost\":{\"_ref\":\"e8acef4b-c95d-4884-9722-fb4697f8887e\",\"_type\":\"reference\"},\"footer\":[{\"_key\":\"79308ad338ee\",\"_type\":\"links\",\"category\":\"Try Claude\",\"links\":[{\"_key\":\"774ea1c1376a\",\"_ref\":\"8f778086-f081-4b3f-913f-1223c58a7923\",\"_type\":\"reference\"},{\"_key\":\"f48e6cb02435\",\"_ref\":\"00b9c65d-5de0-4ff7-b953-bfbb4595b866\",\"_type\":\"reference\"}]},{\"_key\":\"4258d2fcc5bc\",\"_ref\":\"cbb013fc-e097-4c6f-8040-7df8ce4167a0\",\"_type\":\"reference\"},{\"_key\":\"bb491561d51a\",\"_ref\":\"0f3fc856-dbfd-4eda-85a7-e9cfc14b4c96\",\"_type\":\"reference\"}],\"items\":[{\"_key\":\"2ade1bfd307e\",\"_type\":\"item\",\"icon\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-19588d2d29cee76507fa40c928b15263107ce0b5-20x20-svg\",\"_type\":\"reference\"}},\"link\":{\"_ref\":\"76ffe28c-7723-4922-83a6-e7bb00cea2b5\",\"_type\":\"reference\"},\"title\":\"Press\"},{\"_key\":\"4bea026ddbb4\",\"_type\":\"item\",\"icon\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6f6321bfa64df4e8a0bd1b2ed1b703b4a864e0e9-20x20-svg\",\"_type\":\"reference\"}},\"link\":{\"_ref\":\"4f8c909c-6f7b-4c39-96cd-22f0b2999a57\",\"_type\":\"reference\"},\"title\":\"Support\"},{\"_key\":\"b18fe23bfe33\",\"_type\":\"item\",\"icon\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-86777042ed2af185b46341d07b04b86351489844-20x20-svg\",\"_type\":\"reference\"}},\"link\":{\"_ref\":\"060658f1-3f28-4348-9ccd-e55c25c2bb2b\",\"_type\":\"reference\"},\"title\":\"Media assets\"}],\"primary\":[{\"_key\":\"5d2606644dd8\",\"_ref\":\"09546340-742c-403e-926d-5c389c2f17ef\",\"_type\":\"reference\"},{\"_key\":\"e8f57a66bb04\",\"_ref\":\"a891556e-6bc1-4219-a774-5a321e8fd959\",\"_type\":\"reference\"},{\"_key\":\"f0a668d00890\",\"_type\":\"links\",\"category\":\"Research\",\"links\":[{\"_key\":\"be258e4804cc\",\"_ref\":\"1a943bdb-5cd1-463c-a982-a0b55242e12b\",\"_type\":\"reference\"},{\"_key\":\"1ef6db4373e8\",\"_ref\":\"4c5b7791-2d95-468c-ab98-d6b93371a145\",\"_type\":\"reference\"},{\"_key\":\"b4226a2b6169\",\"_ref\":\"bd42abcb-a6af-4a45-981f-db622b38099f\",\"_type\":\"reference\"},{\"_key\":\"207f5782e1527aa61626f2433ad7162d\",\"_ref\":\"c9825846-5e78-4e23-81b8-6383998995fd\",\"_type\":\"reference\"},{\"_key\":\"0f29ab91123b\",\"_ref\":\"3a82f6ce-ffd6-4bb9-8b79-4ce145deb525\",\"_type\":\"reference\"},{\"_key\":\"29b02fd2a1a6\",\"_ref\":\"a23d27ca-8747-44e6-bb5d-85420fca5e4a\",\"_type\":\"reference\"},{\"_key\":\"b298222ca021\",\"_ref\":\"5e3c3851-3583-42eb-9f4c-939c3b2a5168\",\"_type\":\"reference\"},{\"_key\":\"8327d9038174\",\"_ref\":\"1679fb78-630e-452c-a012-0483d909d9a5\",\"_type\":\"reference\"}]},{\"_key\":\"1a6ee7c0acbd\",\"_type\":\"linkGroup\",\"links\":[{\"_key\":\"f915fbe50774\",\"_ref\":\"992d1e7f-eecd-4288-b39a-844867946f79\",\"_type\":\"reference\"},{\"_key\":\"192ad7fb2c39\",\"_ref\":\"5c4cd3b6-6038-4e1b-a0b7-a3a31f349272\",\"_type\":\"reference\"},{\"_key\":\"53fb8c2d6741\",\"_ref\":\"92507305-15ac-43eb-a026-22f8f1e3d661\",\"_type\":\"reference\"},{\"_key\":\"1dd4c7661e4b\",\"_ref\":\"da2ecb16-93d4-4759-9908-51fa41cfc114\",\"_type\":\"reference\"}],\"title\":\"Programs\"},{\"_key\":\"967edcaf4b90\",\"_type\":\"links\",\"category\":\"Company\",\"links\":[{\"_key\":\"47f11712ac6b\",\"_ref\":\"bff5e01a-fc87-4866-8cbf-7c5d776ec041\",\"_type\":\"reference\"},{\"_key\":\"f1f41edfbc73\",\"_ref\":\"8c1ba848-8290-442b-a7bb-306958e605d5\",\"_type\":\"reference\"},{\"_key\":\"f03c48d6e109\",\"_ref\":\"bb6de845-c927-47b0-bd7b-d536724eac9d\",\"_type\":\"reference\"},{\"_key\":\"52bc1c89f6b5\",\"_ref\":\"f41cda79-ae9c-4b89-a34b-0b02a083e61c\",\"_type\":\"reference\"},{\"_key\":\"1cb07bb647d2\",\"_ref\":\"27b23089-5dd9-4c69-bea1-01e811584807\",\"_type\":\"reference\"},{\"_key\":\"a2f2ffd92dbe\",\"_ref\":\"500e9c73-aa2b-4b65-bd29-4e4587f76cb1\",\"_type\":\"reference\"},{\"_key\":\"fdaa4efcd0cb\",\"_ref\":\"b03848c9-1ace-4d5a-9afd-bda105832b62\",\"_type\":\"reference\"},{\"_key\":\"f746d6f53de0\",\"_ref\":\"24b8f488-80e3-4a61-8616-fa82c091e836\",\"_type\":\"reference\"},{\"_key\":\"f2ac6f37474f\",\"_ref\":\"73a59169-4f0f-47ce-ad13-72356dc026e5\",\"_type\":\"reference\"},{\"_key\":\"ee434a1ea245\",\"_ref\":\"856229e6-c91d-4a3b-9cf6-77fe5f6fe2be\",\"_type\":\"reference\"}]},{\"_key\":\"25ce9b972312\",\"_type\":\"links\",\"category\":\"Resources\",\"links\":[{\"_key\":\"7b018820e1f9\",\"_ref\":\"dabe9191-89d3-4407-8fdf-5d95e6a19370\",\"_type\":\"reference\"},{\"_key\":\"8791fe9c02f9\",\"_ref\":\"7ad029d2-5a93-41a1-ace7-dd1e0e2f0a1b\",\"_type\":\"reference\"},{\"_key\":\"443f1006d13a\",\"_ref\":\"53c31bcb-e9d4-4cd1-92dd-0231b153fc01\",\"_type\":\"reference\"},{\"_key\":\"87a2bca2d772\",\"_ref\":\"dce06d65-2107-407e-87a4-f08fd0cfb955\",\"_type\":\"reference\"},{\"_key\":\"6f54158f0ff6\",\"_ref\":\"c4077b20-e76e-4ce4-82b5-c04363a3d487\",\"_type\":\"reference\"},{\"_key\":\"e00fb2ecffbd\",\"_ref\":\"613a6fec-0d63-4008-a6b2-f5016cfea657\",\"_type\":\"reference\"},{\"_key\":\"652011174853\",\"_ref\":\"aa6b1be3-0483-408a-b1dd-960c0adc3516\",\"_type\":\"reference\"},{\"_key\":\"c3dab82a7efb\",\"_ref\":\"3dcaaf36-d5f4-494e-b165-2139174f9bd3\",\"_type\":\"reference\"},{\"_key\":\"b6af913745e3\",\"_ref\":\"8bfb6928-304a-42e0-a2c9-904b264c33ba\",\"_type\":\"reference\"},{\"_key\":\"fe9642decf9b\",\"_ref\":\"1a343724-b052-47f1-9362-388391fc42be\",\"_type\":\"reference\"},{\"_key\":\"efd594f6e668\",\"_ref\":\"9622e2a4-a246-473f-9310-6fcd83988305\",\"_type\":\"reference\"},{\"_key\":\"0bc7f3284842\",\"_ref\":\"b73a3a2c-9171-4d39-88c8-e986195ab0c2\",\"_type\":\"reference\"},{\"_key\":\"eb029df28af8\",\"_ref\":\"5b86b428-a083-4b2f-8b65-115ddddd1ffe\",\"_type\":\"reference\"},{\"_key\":\"51c06fa5a6a1\",\"_ref\":\"9f08c7d6-f2ba-4e88-94ef-7b2f0d9264a9\",\"_type\":\"reference\"},{\"_key\":\"287b12c71349\",\"_ref\":\"8d2d4f24-c4c7-45bb-9c8d-13a2ef233ba1\",\"_type\":\"reference\"}]}],\"secondary\":[{\"_key\":\"c37b72734301\",\"_type\":\"links\",\"category\":\"Products\",\"links\":[{\"_key\":\"70c51ab3cc3e\",\"_ref\":\"6eb64aef-ce55-4a03-8394-5d35429a49aa\",\"_type\":\"reference\"},{\"_key\":\"00551d23b658\",\"_ref\":\"df457120-8495-403a-b9d1-b7b993ad4f64\",\"_type\":\"reference\"},{\"_key\":\"11e55cd1b145\",\"_ref\":\"a9c57922-da84-4f7f-abfd-914294aa344a\",\"_type\":\"reference\"},{\"_key\":\"f490baaebccb\",\"_ref\":\"9500e82c-2f57-4291-8db2-8033eade237d\",\"_type\":\"reference\"},{\"_key\":\"2491be677d05\",\"_ref\":\"18319b35-2c75-4821-8b1c-c18599553f8d\",\"_type\":\"reference\"},{\"_key\":\"07718883b1cc\",\"_ref\":\"62e2517f-5e80-4172-a26d-94af45f264d4\",\"_type\":\"reference\"},{\"_key\":\"7a03c7566a4f\",\"_ref\":\"186bb63f-2d7a-4cb1-b492-a468ec36bf72\",\"_type\":\"reference\"},{\"_key\":\"a7c075b27776\",\"_ref\":\"14b64039-a1cc-443c-8214-a1619362ecfe\",\"_type\":\"reference\"},{\"_key\":\"eef129ff3d67\",\"_ref\":\"52fb0953-4eec-4845-9a36-a689d724022b\",\"_type\":\"reference\"},{\"_key\":\"438031d7bfed\",\"_ref\":\"a096d397-41cf-4b99-86e4-17761fa1a985\",\"_type\":\"reference\"},{\"_key\":\"2ade0602a6e6\",\"_ref\":\"3d2e3ba0-f5ed-4f33-9455-9e5300af132a\",\"_type\":\"reference\"},{\"_key\":\"1d487d0acad8\",\"_ref\":\"0209bfdb-2755-45a2-8471-c261947e3dad\",\"_type\":\"reference\"},{\"_key\":\"2b38473d1d47\",\"_ref\":\"1ae847b6-2fad-4ed5-ac53-3af1394b381b\",\"_type\":\"reference\"}]},{\"_key\":\"b99635b22466\",\"_type\":\"links\",\"category\":\"Models\",\"links\":[{\"_key\":\"3df5e53b6d87\",\"_ref\":\"d43cbf7b-282f-4f63-a2c8-d8d2200517c9\",\"_type\":\"reference\"},{\"_key\":\"7c701c7db2bd\",\"_ref\":\"81c67ac5-0093-47d4-904c-d0f0ceb60c1d\",\"_type\":\"reference\"},{\"_key\":\"046fb7550831\",\"_ref\":\"fb9b25ac-ff23-49fd-b906-bae5a79194cc\",\"_type\":\"reference\"},{\"_key\":\"9b4373cb740d\",\"_ref\":\"131dd426-2d9f-4b81-a870-a235e0ccebc0\",\"_type\":\"reference\"},{\"_key\":\"75ccb16926a0\",\"_ref\":\"49279c3f-20f5-4d90-9e1d-35a62795893d\",\"_type\":\"reference\"}]},{\"_key\":\"7631456e6641\",\"_type\":\"links\",\"category\":\"Solutions\",\"links\":[{\"_key\":\"73dc1fb397db\",\"_ref\":\"5774ee2d-3fc2-4a52-8bb8-0ebc98688d4c\",\"_type\":\"reference\"},{\"_key\":\"0c1dabbe6f52\",\"_ref\":\"12b563d4-7093-4454-a3df-1878c13b478a\",\"_type\":\"reference\"},{\"_key\":\"2e1f60629d5b\",\"_ref\":\"1e1c9133-8505-4de9-81cf-646ef2f3d4f9\",\"_type\":\"reference\"},{\"_key\":\"01adf36780b8\",\"_ref\":\"b94ba8a6-140b-479c-8e2f-0607297c0a44\",\"_type\":\"reference\"},{\"_key\":\"80a1c3a1ecc3\",\"_ref\":\"71e58c94-b1a9-47ef-b249-f0f7d29549c9\",\"_type\":\"reference\"},{\"_key\":\"cfa6e45af421\",\"_ref\":\"d1ca7928-dd04-4696-87d0-9b8c82781e95\",\"_type\":\"reference\"},{\"_key\":\"be4c01a9e542\",\"_ref\":\"ea8cd4fd-07e3-49c8-b9e2-b524419dd9dd\",\"_type\":\"reference\"},{\"_key\":\"c03fab6279f3\",\"_ref\":\"c34a64c9-22ef-4f34-ae67-eb7bfb8b41ae\",\"_type\":\"reference\"},{\"_key\":\"9b23ba0dd937\",\"_ref\":\"a5fd7e73-5b5f-4a89-9f47-522ddf1ca3e0\",\"_type\":\"reference\"},{\"_key\":\"9ef39192fcfb\",\"_ref\":\"ad23dd8b-83fb-4e51-8e65-f124b0f1d909\",\"_type\":\"reference\"},{\"_key\":\"6d92612c6f0f\",\"_ref\":\"cd7a1e0a-267b-43db-bf4e-ac2aba743faf\",\"_type\":\"reference\"},{\"_key\":\"079a16a9b7bc\",\"_ref\":\"fa4317a3-2071-446b-a509-d53659c40fe3\",\"_type\":\"reference\"},{\"_key\":\"1eefd3ea1403\",\"_ref\":\"ba7aaae0-5fd5-4aad-b07e-ef61908581a5\",\"_type\":\"reference\"},{\"_key\":\"9fa3b3ba7a02\",\"_ref\":\"efec0cd1-c133-4206-b841-2652114bd0fd\",\"_type\":\"reference\"}]},{\"_key\":\"f48f6b982b22\",\"_type\":\"links\",\"category\":\"Help and security\",\"links\":[{\"_key\":\"9f35e49cfc41\",\"_ref\":\"7a809c60-b80c-4202-b7e9-0a3b31540be5\",\"_type\":\"reference\"},{\"_key\":\"60740cd03edd\",\"_ref\":\"116f59c3-dae0-4460-aba3-77cd389deae9\",\"_type\":\"reference\"},{\"_key\":\"9d1ff10bfb94\",\"_ref\":\"c9c149bd-f4fb-4039-af8a-463f0b6fffdb\",\"_type\":\"reference\"}]},{\"_key\":\"7e78e84713d8\",\"_type\":\"links\",\"category\":\"Terms and policies\",\"links\":[{\"_key\":\"d501eb9aaca4\",\"_ref\":\"64e45a46-d067-4ca1-9d5d-bf64960accaa\",\"_type\":\"reference\"},{\"_key\":\"7dc5fb2ff23d\",\"_ref\":\"4c2802e1-5e06-41fa-b17b-24228606f6b1\",\"_type\":\"reference\"},{\"_key\":\"ac3d27dad26e\",\"_ref\":\"b8fd7afc-542b-45b1-a2d8-38b4b727a367\",\"_type\":\"reference\"},{\"_key\":\"0579b9827eab\",\"_ref\":\"3a07985b-538b-46bf-aa5a-9a6e268cd661\",\"_type\":\"reference\"},{\"_key\":\"ad1a1fcfb4a4\",\"_ref\":\"37c68a43-e52b-4e84-9f06-af522140f04b\",\"_type\":\"reference\"},{\"_key\":\"831293db9343\",\"_ref\":\"f5b0d8e2-6bc9-4923-9e24-77e0b4744e61\",\"_type\":\"reference\"},{\"_key\":\"0eea3d1a56d6\",\"_ref\":\"f131796a-c022-4365-b7b1-b7b283a50987\",\"_type\":\"reference\"},{\"_key\":\"2ff96e38c66d\",\"_ref\":\"f72a1541-7f03-4866-93eb-4abb9c146957\",\"_type\":\"reference\"}]}]},\"meta\":{\"_createdAt\":\"2023-11-20T21:56:31Z\",\"_id\":\"0f6290ad-6d21-407d-8deb-ce02815d1383\",\"_rev\":\"NyW74GU9ZzyWgAYa8qUSlF\",\"_type\":\"metadata\",\"_updatedAt\":\"2023-11-20T23:54:09Z\",\"robotsIndexable\":true,\"seoDescription\":\"Anthropic is an AI safety and research company that's working to build reliable, interpretable, and steerable AI systems.\",\"seoTitle\":\"Anthropic\",\"socialImage\":{\"_type\":\"image\",\"asset\":{\"_createdAt\":\"2026-04-09T19:48:51Z\",\"_id\":\"image-6d4a0d28992ade92d6fa63646fd9c9d318245c6c-2400x1260-jpg\",\"_rev\":\"jDodSjFd3gutFoWBkcepoA\",\"_type\":\"sanity.imageAsset\",\"_updatedAt\":\"2026-04-09T19:48:51Z\",\"assetId\":\"6d4a0d28992ade92d6fa63646fd9c9d318245c6c\",\"extension\":\"jpg\",\"metadata\":{\"_type\":\"sanity.imageMetadata\",\"blurHash\":\"MBR{rhxu?H%Lt7-;j[j[j[fQ~pj[9ZayRj\",\"dimensions\":{\"_type\":\"sanity.imageDimensions\",\"aspectRatio\":1.9047619047619047,\"height\":1260,\"width\":2400},\"hasAlpha\":false,\"isOpaque\":true,\"lqip\":\"data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAKABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAEEBQj/xAAfEAABAwQDAQAAAAAAAAAAAAAAAQQRAgMFMRITFCL/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A0g+vOLPDzN+6d/UQRaHuRW5FWO40zvsQtQM1EmkkBgIP/9k=\",\"palette\":{\"_type\":\"sanity.imagePalette\",\"darkMuted\":{\"_type\":\"sanity.imagePaletteSwatch\",\"background\":\"#44443e\",\"foreground\":\"#fff\",\"population\":0.06,\"title\":\"#fff\"},\"darkVibrant\":{\"_type\":\"sanity.imagePaletteSwatch\",\"background\":\"#6e4216\",\"foreground\":\"#fff\",\"population\":0,\"title\":\"#fff\"},\"dominant\":{\"_type\":\"sanity.imagePaletteSwatch\",\"background\":\"#f4f4eb\",\"foreground\":\"#000\",\"population\":89.85,\"title\":\"#000\"},\"lightMuted\":{\"_type\":\"sanity.imagePaletteSwatch\",\"background\":\"#f4f4eb\",\"foreground\":\"#000\",\"population\":89.85,\"title\":\"#000\"},\"lightVibrant\":{\"_type\":\"sanity.imagePaletteSwatch\",\"background\":\"#fcf6f0\",\"foreground\":\"#000\",\"population\":3.26,\"title\":\"#000\"},\"muted\":{\"_type\":\"sanity.imagePaletteSwatch\",\"background\":\"#7c7c74\",\"foreground\":\"#fff\",\"population\":0.04,\"title\":\"#fff\"},\"vibrant\":{\"_type\":\"sanity.imagePaletteSwatch\",\"background\":\"#d47f2a\",\"foreground\":\"#fff\",\"population\":0,\"title\":\"#fff\"}},\"thumbHash\":\"eggGBIDHh3iHeHePc3jHiH+M9w==\"},\"mimeType\":\"image/jpeg\",\"originalFilename\":\"og_anthropic-generic.jpg\",\"path\":\"images/4zrzovbb/website/6d4a0d28992ade92d6fa63646fd9c9d318245c6c-2400x1260.jpg\",\"sha1hash\":\"6d4a0d28992ade92d6fa63646fd9c9d318245c6c\",\"size\":30702,\"uploadId\":\"a6wFtR7ARlnZvD6y9KDgxpiPpcfS1ctP\",\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6d4a0d28992ade92d6fa63646fd9c9d318245c6c-2400x1260.jpg\"},\"description\":\"Anthropic logo\"}},\"navigation\":[{\"_key\":\"efd4c3443340\",\"_ref\":\"a891556e-6bc1-4219-a774-5a321e8fd959\",\"_type\":\"reference\"},{\"_key\":\"49fa2a29c062\",\"_type\":\"links\",\"category\":\"Research\",\"links\":[{\"_key\":\"bdd1dd5db506\",\"_ref\":\"474d93ab-4c9b-4e9f-9e3b-db34237ba87c\",\"_type\":\"reference\"},{\"_key\":\"a01311ea1e90\",\"_ref\":\"1aece7e6-62d6-4852-8fdf-ef019fd0c9fa\",\"_type\":\"reference\"},{\"_key\":\"203305b8c322\",\"_ref\":\"bd42abcb-a6af-4a45-981f-db622b38099f\",\"_type\":\"reference\"},{\"_key\":\"ff43f9710a8f\",\"_ref\":\"c9825846-5e78-4e23-81b8-6383998995fd\",\"_type\":\"reference\"},{\"_key\":\"37007eecc07f\",\"_ref\":\"3a82f6ce-ffd6-4bb9-8b79-4ce145deb525\",\"_type\":\"reference\"},{\"_key\":\"f67d189923c4\",\"_ref\":\"a23d27ca-8747-44e6-bb5d-85420fca5e4a\",\"_type\":\"reference\"},{\"_key\":\"8c625ef740a3\",\"_ref\":\"1679fb78-630e-452c-a012-0483d909d9a5\",\"_type\":\"reference\"},{\"_key\":\"1f08bdfdc6f1\",\"_ref\":\"5c868a2a-18ae-4989-84c0-070e77c8192b\",\"_type\":\"reference\"}]},{\"_key\":\"2e3e9a249c53\",\"_type\":\"linkGroup\",\"links\":[{\"_key\":\"7f3a0a0a31c4\",\"_ref\":\"992d1e7f-eecd-4288-b39a-844867946f79\",\"_type\":\"reference\"},{\"_key\":\"df101b7685ee\",\"_ref\":\"5c4cd3b6-6038-4e1b-a0b7-a3a31f349272\",\"_type\":\"reference\"}],\"title\":\"Programs\"},{\"_key\":\"d6d728461653\",\"_type\":\"links\",\"category\":\"Company\",\"links\":[{\"_key\":\"25d553bb29b1\",\"_type\":\"links\",\"category\":\"Anthropic\",\"links\":[{\"_key\":\"0a09772ba25a\",\"_ref\":\"f058004f-bb9e-4cf5-a979-4d48a50ef67b\",\"_type\":\"reference\"},{\"_key\":\"fcfecbc015b3\",\"_ref\":\"8c1ba848-8290-442b-a7bb-306958e605d5\",\"_type\":\"reference\"},{\"_key\":\"c1a74b28efec\",\"_ref\":\"bb6de845-c927-47b0-bd7b-d536724eac9d\",\"_type\":\"reference\"}]},{\"_key\":\"615a54f2d838\",\"_type\":\"links\",\"category\":\"Our Commitments\",\"links\":[{\"_key\":\"c651e04237dc\",\"_ref\":\"287c8a1c-3f83-4b0e-ba15-8c7afd8a9606\",\"_type\":\"reference\"},{\"_key\":\"f243e1bb3c8c\",\"_ref\":\"797e91ff-6d4c-4233-bb48-5c4a16ea78ee\",\"_type\":\"reference\"},{\"_key\":\"899146a1d5f4\",\"_ref\":\"3195ac77-751e-455f-a3fc-d5e3476784a0\",\"_type\":\"reference\"},{\"_key\":\"087f7095d649\",\"_ref\":\"856229e6-c91d-4a3b-9cf6-77fe5f6fe2be\",\"_type\":\"reference\"},{\"_key\":\"2b6c9d362ca5\",\"_ref\":\"f41cda79-ae9c-4b89-a34b-0b02a083e61c\",\"_type\":\"reference\"}]}]},{\"_key\":\"5f833a6012c4\",\"_type\":\"links\",\"category\":\"Try Claude\",\"links\":[{\"_key\":\"84e440c34ba9\",\"_type\":\"links\",\"category\":\"Products\",\"links\":[{\"_key\":\"9cb0c0af6e8e\",\"_ref\":\"1f59436a-2330-4e42-a46e-386e058f8c5d\",\"_type\":\"reference\"},{\"_key\":\"c9315d2b21ed\",\"_ref\":\"fb0a7193-b264-4161-ab25-60c5a7e3c4fd\",\"_type\":\"reference\"},{\"_key\":\"b63a9b3e5a5b\",\"_ref\":\"0f2f1053-3610-4dbb-90e3-e6ba7faf82c8\",\"_type\":\"reference\"},{\"_key\":\"d3a56a654a58\",\"_ref\":\"7813ff4e-9e4d-4abc-aba8-ce8632683ba5\",\"_type\":\"reference\"}]},{\"_key\":\"1afc7f36a528\",\"_type\":\"links\",\"category\":\"For business\",\"links\":[{\"_key\":\"2341510792d6\",\"_ref\":\"7a282220-2540-4c12-ae78-2ab834b2e052\",\"_type\":\"reference\"},{\"_key\":\"9a94c3f2af43\",\"_ref\":\"c8d07a04-75aa-434c-a220-73cebd6356f2\",\"_type\":\"reference\"},{\"_key\":\"3339ac637158\",\"_ref\":\"3471fc3b-4b3b-4c8f-969c-3dd65e92b582\",\"_type\":\"reference\"}]},{\"_key\":\"c195a9483a93\",\"_type\":\"links\",\"category\":\"Resources\",\"links\":[{\"_key\":\"9bda300d371e\",\"_ref\":\"87b28304-1124-4daf-a94e-4659078f9462\",\"_type\":\"reference\"},{\"_key\":\"7a923a0b45b4\",\"_ref\":\"9421fcf3-99ee-4899-aa7c-9bae75b90d51\",\"_type\":\"reference\"},{\"_key\":\"b0670e689512\",\"_ref\":\"47469844-336f-4bc8-96a3-69c974661d83\",\"_type\":\"reference\"}]},{\"_key\":\"be8a4dbb2712\",\"_type\":\"links\",\"category\":\"Login\",\"links\":[{\"_key\":\"402b10e02dd4\",\"_ref\":\"1f59436a-2330-4e42-a46e-386e058f8c5d\",\"_type\":\"reference\"},{\"_key\":\"ced3a0c9a9f4\",\"_ref\":\"00b9c65d-5de0-4ff7-b953-bfbb4595b866\",\"_type\":\"reference\"}]}]}],\"search\":{\"searchBoxPlaceholder\":\"Enter search...\",\"searches\":[\"Claude\",\"Governance\",\"Policy\",\"Models\",\"Reasoning\",\"Nonprofit\"],\"tags\":[{\"_key\":\"5613d0c704eb\",\"_ref\":\"058e47b5-fac5-4996-831f-a40aedf5bcd7\",\"_type\":\"reference\"},{\"_key\":\"645606651b29\",\"_ref\":\"379880f6-77c4-43ea-a654-746623609bf8\",\"_type\":\"reference\"},{\"_key\":\"0c852ab1d653\",\"_ref\":\"f1a91146-0e43-44d3-9922-d6b53d1a08ce\",\"_type\":\"reference\"},{\"_key\":\"d2c395462872\",\"_ref\":\"0b40c7c6-9aa9-4f7e-be31-42d35839705f\",\"_type\":\"reference\"},{\"_key\":\"ab31673a9364\",\"_ref\":\"14208d64-4ee4-46b1-8723-8efb19365f2e\",\"_type\":\"reference\"},{\"_key\":\"42e16ee084a6\",\"_ref\":\"2fc18360-5f84-4f95-99f8-81c7a6e35d65\",\"_type\":\"reference\"},{\"_key\":\"a40c2abbfb31\",\"_ref\":\"36fc8828-854d-4597-9c83-ef499b76cbea\",\"_type\":\"reference\"}]},\"siteName\":\"Anthropic\",\"sitemapUrls\":[\"/\",\"/constitution\",\"/events\",\"/events/aws-summit-dc\",\"/events/aws-summit-nyc\",\"/events/aws-summit-london\",\"/events/aws-summit-tokyo\",\"/events/claude-for-finance\",\"/events/google-cloud-next-2025\",\"/events/paris-builder-summit\",\"/events/seoul-builder-summit\",\"/features/81k-interviews\",\"/features/claude-on-mars\",\"/features/making-of-claude-code\",\"/features/project-deal\",\"/glasswing\",\"/learn\",\"/economic-index\",\"/careers/jobs\",\"/responsible-scaling-policy/roadmap\",\"/institute\",\"/institute/recursive-self-improvement\",\"/policy-on-the-ai-exponential\",\"/claude-corps\",\"/beneficial-deployments\",\"/claude-fable-and-mythos-5-1\",\"/threat-intelligence\"],\"twitterUsername\":\"AnthropicAI\",\"youtubeUsername\":\"anthropic-ai\"},\"page\":{\"_createdAt\":\"2024-06-01T05:13:58Z\",\"_id\":\"65ed983f-1db1-4655-b662-8c7169802ac8\",\"_rev\":\"PZ1Um97JHxu3mqLpc3wVKc\",\"_system\":{\"base\":{\"id\":\"65ed983f-1db1-4655-b662-8c7169802ac8\",\"rev\":\"aLJWpLS1Zv36ohV3WT7skN\"}},\"_type\":\"page\",\"_updatedAt\":\"2026-08-04T17:13:49Z\",\"backgroundColor\":null,\"meta\":null,\"sections\":[{\"_createdAt\":\"2025-10-23T15:23:22Z\",\"_id\":\"e17ad3e5-6c45-4159-8a19-fddd57dd9fe8\",\"_rev\":\"PZ1Um97JHxu3mqLpc3wUvS\",\"_system\":{\"base\":{\"id\":\"e17ad3e5-6c45-4159-8a19-fddd57dd9fe8\",\"rev\":\"mDym9IFV4bppKzH8GUXWsr\"}},\"_type\":\"heroTwoColumn\",\"_updatedAt\":\"2026-08-04T17:13:13Z\",\"backgroundColor\":\"default\",\"borderTop\":false,\"ctaVariant\":\"list\",\"ctas\":[{\"_key\":\"07a5b76c21ca\",\"iconType\":\"email\",\"label\":\"Press inquiries\",\"title\":\"press@anthropic.com\",\"url\":\"mailto:press@anthropic.com\"},{\"_key\":\"9b634f2d7de7\",\"iconType\":\"information\",\"label\":\"Non-media inquiries\",\"title\":\"How to get support\",\"url\":\"https://support.claude.com/en/articles/9015913-how-to-get-support\"},{\"_key\":\"4281e62a97a2\",\"iconType\":\"download\",\"label\":\"Media assets\",\"title\":\"Download press kit\",\"url\":\"https://anthropic.com/press-kit\"}],\"flushBottom\":false,\"flushTop\":false,\"fullWidth\":false,\"title\":\"Newsroom\"},{\"_createdAt\":\"2025-10-23T20:26:59Z\",\"_id\":\"79c6b095-dee8-4d0a-bd68-df974114c2f9\",\"_rev\":\"RSyRWr0u1Rsacs9Du5Cjic\",\"_system\":{\"base\":{\"id\":\"79c6b095-dee8-4d0a-bd68-df974114c2f9\",\"rev\":\"Fg0Fxr3NV6NfBOFEkcC5fF\"}},\"_type\":\"featuredGrid\",\"_updatedAt\":\"2026-09-10T17:10:19Z\",\"backgroundColor\":\"default\",\"borderTop\":true,\"flushBottom\":false,\"flushTop\":true,\"fullWidth\":false,\"image\":{\"_type\":\"imageWithCaption\",\"caption\":[],\"height\":null,\"url\":null,\"width\":null},\"internalName\":\"Newsroom Featured Grid\",\"items\":[{\"_key\":\"73aded5a605c\",\"_type\":\"featuredGridLink\",\"date\":\"2026-09-01\",\"subject\":\"Announcements\",\"summary\":\"Our most advanced models for coding and knowledge work. Their research capabilities also offer an early glimpse of how AI models will contribute to scientific progress.\",\"title\":\"Introducing Claude Fable 5.1 and Claude Mythos 5.1\",\"url\":\"/claude-fable-and-mythos-5-1\"},{\"_key\":\"abd66cc77488\",\"_type\":\"featuredGridLink\",\"date\":\"2026-09-10\",\"subject\":\"Announcements\",\"summary\":\"Over the past eight months, our Threat Intelligence team identified and disrupted operations in which threat actors tried to use Claude for malicious activity. In this report, we share case studies from those operations and describe how malicious use of Claude has evolved since our previous threat reports in 2025.\",\"title\":\"Detecting and countering misuse of AI: September 2026\",\"url\":\"https://www.anthropic.com/threat-intelligence-report-september-2026\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:23Z\",\"_id\":\"Z7bXjXUrfbilTWp6Llz4FF\",\"_rev\":\"CIQMb8zr2hKNcFuuO2JBUf\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:20Z\",\"description\":\"Hand with geometric shapes constructing a complex abstract form on white background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6905c83d0735e1bc430025fdd1748d1406079036-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6905c83d0735e1bc430025fdd1748d1406079036-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, shape, build, construction, creating, forming, shaping, molding, crafting, building, assembly, development, formation, creative construction, hands-on building, collaboration, teamwork, collaborative building, artifacts, interactive creation, AI-assisted building, collaborative development, working together\",\"name\":\"Hand ShapeBuild\",\"type\":\"hero\"}},\"publishedOn\":\"2026-08-31T15:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"improving-alignment-security-efforts\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"On July 30, we reported three incidents in which Claude models gained unauthorized access to real computer systems. We are conducting an in-depth analysis of both incidents, and planning to work with METR for an independent review. In the meantime, we’re sharing some of the changes we’ve made over the past month.\",\"title\":\"Improving our alignment and security efforts\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":720,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5008271abbababe59f4fbb01998697f7dd0b5b60-1280x720.jpg\",\"width\":1280},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2026-08-27T18:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"model-hardware-standard-research-preview\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":\"We’re opening a research preview of the Model Hardware Standard (MHS), a shared specification for AI agents to safely operate physical devices, to a first group of scientific research labs and advanced manufacturers. \",\"title\":\"Previewing the Model Hardware Standard\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1620,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/54b7ab1d2c2521f83ae5d2da5f9d99321c370d24-2880x1620.png\",\"width\":2880},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-07-24T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-opus-5\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"},{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Opus 5 is a step change improvement for the Opus tier powering long-running agents while delivering improvements in coding and professional work.\",\"title\":\"Introducing Claude Opus 5\"}],\"video\":{\"_type\":\"video\",\"autoplay\":false,\"embedUrl\":\"https://www.youtube.com/watch?v=ROF2Nv_KjOM\",\"loop\":false,\"muted\":false,\"showControls\":true,\"thumbnail\":{\"height\":1620,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/d337d7c546fdeabce5d41ecd2b96ea385bb5f223-2880x1620.jpg\",\"width\":2880},\"url\":null}},{\"_createdAt\":\"2025-10-23T19:45:38Z\",\"_id\":\"fa4d54c7-ab7e-4461-96e7-9cd8b7dfaadd\",\"_rev\":\"kG12fknjLbGGavyRrOrDdp\",\"_type\":\"publicationList\",\"_updatedAt\":\"2025-11-16T19:17:09Z\",\"backgroundColor\":\"default\",\"borderTop\":true,\"directory\":{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"},\"flushBottom\":false,\"flushTop\":true,\"fullWidth\":false,\"postSubjects\":null,\"posts\":[{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:32:49Z\",\"_id\":\"Z7bXjXUrfbilTWp6Llx9XF\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IM4d\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:57:01Z\",\"description\":\"Hand with urban skyline and corporate buildings, representing business growth and enterprise development\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-60d57c0d0bf031e140de678692f7c3ef2d885ce3-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/60d57c0d0bf031e140de678692f7c3ef2d885ce3-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, city, enterprise, business growth, corporate development, scaling, expansion, enterprise solutions, business ecosystem, corporate skyline, organizational growth, market expansion, enterprise services, business infrastructure, corporate strategy, scaling up, business development\",\"name\":\"Hand City\",\"type\":\"hero\"}},\"publishedOn\":\"2026-09-01T23:31:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"enterprise-frontier-safeguards\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Developing Enterprise Frontier Safeguards with our customers\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:23Z\",\"_id\":\"Z7bXjXUrfbilTWp6Llz4FF\",\"_rev\":\"CIQMb8zr2hKNcFuuO2JBUf\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:20Z\",\"description\":\"Hand with geometric shapes constructing a complex abstract form on white background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6905c83d0735e1bc430025fdd1748d1406079036-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6905c83d0735e1bc430025fdd1748d1406079036-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, shape, build, construction, creating, forming, shaping, molding, crafting, building, assembly, development, formation, creative construction, hands-on building, collaboration, teamwork, collaborative building, artifacts, interactive creation, AI-assisted building, collaborative development, working together\",\"name\":\"Hand ShapeBuild\",\"type\":\"hero\"}},\"publishedOn\":\"2026-08-31T15:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"improving-alignment-security-efforts\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"On July 30, we reported three incidents in which Claude models gained unauthorized access to real computer systems. We are conducting an in-depth analysis of both incidents, and planning to work with METR for an independent review. In the meantime, we’re sharing some of the changes we’ve made over the past month.\",\"title\":\"Improving our alignment and security efforts\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":720,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5008271abbababe59f4fbb01998697f7dd0b5b60-1280x720.jpg\",\"width\":1280},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2026-08-27T18:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"model-hardware-standard-research-preview\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":\"We’re opening a research preview of the Model Hardware Standard (MHS), a shared specification for AI agents to safely operate physical devices, to a first group of scientific research labs and advanced manufacturers. \",\"title\":\"Previewing the Model Hardware Standard\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:15Z\",\"_id\":\"L5WZ73ZndVNkcSTU1XoHWy\",\"_rev\":\"znUZZ0fmIk1XIVDY2KCgRv\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:05Z\",\"description\":\"Stylized hand and head silhouette with interconnected node and abstract geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-46e4aa7ea208ed440d5bd9e9e3a0ee66bc336ff1-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/46e4aa7ea208ed440d5bd9e9e3a0ee66bc336ff1-1000x1000.svg\",\"width\":1000},\"keywords\":\"Hero illustration: Hand HeadNodeThink\",\"name\":\"Hand HeadNodeThink\",\"type\":\"hero\"}},\"publishedOn\":\"2026-08-27T17:03:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"expanding-support-for-scientists\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Starting today, 10,000 scientists around the world can get Claude at no cost to start. Verified principal investigators qualify for a Claude Team subscription plan and then add their research team to Standard seats for free, or Premium seats for $15 per month, for up to a year.\",\"title\":\" Expanding our support for scientists\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:34:41Z\",\"_id\":\"Z7bXjXUrfbilTWp6Llye9k\",\"_rev\":\"L1sWYwVuS7u8WeTHm66zoR\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:59:53Z\",\"description\":\"Hand with flower elements and head outline in stylized profile design\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-f6a742f45bdb584cdffd3f00d54751b12bbee2ba-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/f6a742f45bdb584cdffd3f00d54751b12bbee2ba-1000x1000.svg\",\"width\":1000},\"keywords\":\"Hero illustration: Hand HeadFlower\",\"name\":\"Hand HeadFlower\",\"type\":\"hero\"}},\"publishedOn\":\"2026-08-25T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"wellbeing-research-grants\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’re launching a $5 million grant program to fund independent research into how AI impacts users’ wellbeing.\",\"title\":\"Funding better evaluations of AI’s impact on wellbeing\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:35Z\",\"_id\":\"DElaXo1A74rjItEmVahiln\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IdYy\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:21Z\",\"description\":\"Ornate quill pen resting on a detailed hand, positioned against a textured background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, quill, writing, pen, authoring, documentation, content creation, writing tools, literary work, composition, manuscript, creative writing, text creation\",\"name\":\"Hand Quill\",\"type\":\"hero\"}},\"publishedOn\":\"2026-08-14T19:16:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-text-watermark\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"In this article, we share answers to some of the questions we’ve received about how our chosen watermarking method works, whether it affects Claude’s outputs, and why we’re making this change.\",\"title\":\"How Claude’s text watermark works\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T17:09:09Z\",\"_id\":\"Z7bXjXUrfbilTWp6LkjtoF\",\"_rev\":\"znUZZ0fmIk1XIVDY2KG9h3\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:01:50Z\",\"description\":\"Stylized bird with curved wings and intricate body lines against abstract background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-e253e6c4926deb09baf67f41e4e24e8028ea5f36-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/e253e6c4926deb09baf67f41e4e24e8028ea5f36-1000x1000.svg\",\"width\":1000},\"keywords\":\"bird, flight, flying, wings, freedom, movement, speed, agility, swift, quick, nimble, graceful, soaring, elevated, rising, upward motion, liberation, peace\",\"name\":\"Node Bird\",\"type\":\"hero\"}},\"publishedOn\":\"2026-08-07T01:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"improving-fable-5-s-biology-safeguards\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"},{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’re making updates to Claude Fable 5’s biology safeguards in a way that substantially reduces false positives. Fable 5 users will now experience many fewer “fallbacks”—where the system switches to a less capable model after they make a biology-related query.\",\"title\":\"Improving Fable 5's biology safeguards\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-08-04T17:02:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"tino-cuellar\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Mariano-Florentino (Tino) Cuéllar will join Anthropic as its first Chief Global Affairs Officer.\",\"title\":\"Mariano-Florentino (Tino) Cuéllar to join Anthropic as Chief Global Affairs Officer\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T17:22:56Z\",\"_id\":\"fYxjGGEIxl5FrJqEfAZWoz\",\"_rev\":\"L1sWYwVuS7u8WeTHm64FmP\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:13Z\",\"description\":\"Hand with padlock and key on detailed security graphic\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-d3dd09ad16c68461dc3fb01df5e84cf7ccafda6c-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/d3dd09ad16c68461dc3fb01df5e84cf7ccafda6c-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, lock, security, protection, key, safety, padlock, privacy, access control, confidentiality, security features, privacy protection, safety measures, confidential information\",\"name\":\"Hand Lock\",\"type\":\"hero\"}},\"publishedOn\":\"2026-07-30T15:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"investigating-incidents-cybersecurity-evals\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Investigating three real-world incidents in our cybersecurity evaluations\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-07-27T18:36:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"position-open-weights-models\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Our position on open-weights models\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-07-27T15:32:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"cognizant-anthropic\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Cognizant and Anthropic expand their partnership to bring Claude to enterprise clients\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1620,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/54b7ab1d2c2521f83ae5d2da5f9d99321c370d24-2880x1620.png\",\"width\":2880},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-07-24T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-opus-5\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"},{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Opus 5 is a step change improvement for the Opus tier powering long-running agents while delivering improvements in coding and professional work.\",\"title\":\"Introducing Claude Opus 5\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":2000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5f8644ad8a7fb9053f991843f0a93d41f2d5acf9-2000x2000.jpg\",\"width\":2000},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2026-07-22T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"economic-futures-research-fund-agenda\"},\"subjects\":[{\"_key\":\"economic-research\",\"_type\":\"tag\",\"label\":\"Economics\",\"value\":\"economic-research\"}],\"summary\":\"We’re sharing the research agenda for the Anthropic Economic Futures Research Fund.\",\"title\":\"A research agenda for the Economic Futures Research Fund\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":2160,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/86d58406a0e3649c5558039f8bf92d54dda1de33-3840x2160.png\",\"width\":3840},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"coral\",\"illustration\":{\"_createdAt\":\"2025-07-17T18:57:10Z\",\"_id\":\"Z7bXjXUrfbilTWp6LleIIk\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IluI\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:59:01Z\",\"description\":\"Hand holding an open book with network nodes and connection lines emanating from its pages\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-1c3d1af62032009538b8bf5864139ca124b06741-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1c3d1af62032009538b8bf5864139ca124b06741-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, book, node, network, knowledge, learning, documentation, AI, intelligence, information network, educational content, smart learning, knowledge sharing, intelligent documentation, connected learning\",\"name\":\"Hand NodeBook\",\"type\":\"hero\"}},\"publishedOn\":\"2026-07-22T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-economic-index-connector\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"},{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"economic-research\",\"_type\":\"tag\",\"label\":\"Economics\",\"value\":\"economic-research\"}],\"summary\":\"We're launching the Anthropic Economic Index connector for Claude, which lets anyone explore real data about AI and work.\",\"title\":\"Ask Claude about the Anthropic Economic Index\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:02Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIw7Nd\",\"_rev\":\"znUZZ0fmIk1XIVDY2KAU4T\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:57:26Z\",\"description\":\"Stacked hands on building blocks forming a collaborative construction scene\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6d914851a169b4ff77e5de4a30c91f5a51520871-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6d914851a169b4ff77e5de4a30c91f5a51520871-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, stack, pile, building, construction, collaboration, teamwork, building together, cooperative building, team effort, collective work, assembling, constructing, building blocks, collaborative construction, working together, team building\",\"name\":\"Hand Stack\",\"type\":\"hero\"}},\"publishedOn\":\"2026-07-21T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"donation-public-first-action\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Anthropic is contributing an additional $20 million to Public First Action, bringing our total support to $40 million.\",\"title\":\"Anthropic is donating another $20 million to Public First Action\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:34:28Z\",\"_id\":\"Z7bXjXUrfbilTWp6LlyZCF\",\"_rev\":\"L1sWYwVuS7u8WeTHm66qkR\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:59:35Z\",\"description\":\"Hand with protective shield and network node in cybersecurity symbol design\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-b1ce510c468b2920d4f8f61c17a50906801f939a-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b1ce510c468b2920d4f8f61c17a50906801f939a-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, shield, node, protection, security, network security, protected network, cybersecurity, secure connections, data protection, network safety, security measures\",\"name\":\"Hand NodeShield\",\"type\":\"hero\"}},\"publishedOn\":\"2026-07-20T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"rare-disease-research-grants\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Anthropic is sharing a focused call for AI for Science applications centered specifically on rare genetic diseases. Accepted applicants will receive up to $50,000 in Claude credits over six months, with the goal of building a community of researchers looking into how AI can reshape our understanding of rare disease. \",\"title\":\"Apply for Anthropic’s AI for Science rare disease research grants\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":630,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/c39f489c0763bac41638f8ea29a0ae1335c3ecb2-1200x630.jpg\",\"width\":1200},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2026-07-14T15:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-for-teachers\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":null,\"title\":\"Introducing Claude for Teachers\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T15:25:22Z\",\"_id\":\"Xjt2eTPpfxUE2CfkIxE28E\",\"_rev\":\"znUZZ0fmIk1XIVDY2KEw1j\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:53Z\",\"description\":\"Interconnected globe with network nodes and global connection lines\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-5f455d24ea80569b34eb4347f06152d8a5508722-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5f455d24ea80569b34eb4347f06152d8a5508722-1000x1000.svg\",\"width\":1000},\"keywords\":\"globe, world, global, international, worldwide, planet, earth, sphere, universal, global reach\",\"name\":\"Node Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2026-07-14T13:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"canadian-ai-research\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic commits $10 million to Canadian AI research\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"coral\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:06Z\",\"_id\":\"Z7bXjXUrfbilTWp6LlxblF\",\"_rev\":\"L1sWYwVuS7u8WeTHm65aSO\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:57:36Z\",\"description\":\"Stylized hand constructing architectural structure with geometric building elements and foundational components\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-cd4fd51deacd067d4e30aee4f4b149f6cba1b97b-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/cd4fd51deacd067d4e30aee4f4b149f6cba1b97b-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, build, construction, create, develop, assembly, crafting, making, manufacturing, production, engineering, architecture, foundation, structure, progress, work in progress, development, creation\",\"name\":\"Hand Build\",\"type\":\"hero\"}},\"publishedOn\":\"2026-07-09T23:55:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"ust-claude\"},\"subjects\":[{\"_key\":\"case-study\",\"_type\":\"tag\",\"label\":\"Case Study\",\"value\":\"case-study\"}],\"summary\":null,\"title\":\"UST is bringing Claude to physical AI\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1125,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/3fe58a56e696628496e95871e00b8287035ea645-2000x1125.jpg\",\"width\":2000},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-07-09T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"hard-questions\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’re asking the public for their hardest questions about AI, and committing to show our work as we address them.\",\"title\":\"Inviting hard questions\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-07-09T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"ben-bernanke\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Ben Bernanke appointed to Anthropic’s Long-Term Benefit Trust \"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:35Z\",\"_id\":\"DElaXo1A74rjItEmVahiln\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IdYy\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:21Z\",\"description\":\"Ornate quill pen resting on a detailed hand, positioned against a textured background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, quill, writing, pen, authoring, documentation, content creation, writing tools, literary work, composition, manuscript, creative writing, text creation\",\"name\":\"Hand Quill\",\"type\":\"hero\"}},\"publishedOn\":\"2026-07-09T13:20:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"reflect-with-claude\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Introducing a new way to reflect on and refine how you use Claude. It lets you easily track and visualize how you use Claude, and decide whether that time aligns with your goals. \",\"title\":\"Introducing a way to reflect on how you use Claude\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2026-02-20T14:56:42Z\",\"_id\":\"be10271f-1b3a-415a-8c7b-de3270ecca4a\",\"_rev\":\"qY14ovG70H1L8z3NicQiuU\",\"_type\":\"illustration\",\"_updatedAt\":\"2026-02-20T15:03:04Z\",\"description\":\"Open laptop with lock iconography showing on its inner screen\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-802260d34a0653f23fd4944fae43064df367aa44-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/802260d34a0653f23fd4944fae43064df367aa44-1000x1000.svg\",\"width\":1000},\"keywords\":\"security, laptop, laptopsecure, cyber, cybersecurity, secure, laptop\",\"name\":\"Object-LaptopSecure\",\"type\":\"hero\"}},\"publishedOn\":\"2026-07-06T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"alberta-government-claude-cybersecurity\"},\"subjects\":[{\"_key\":\"case-study\",\"_type\":\"tag\",\"label\":\"Case Study\",\"value\":\"case-study\"}],\"summary\":\"Since 2025, the Government of Alberta has been using Claude Code with both Opus and Sonnet models to review its systems, find vulnerabilities, and fix them.\",\"title\":\"Government of Alberta uses Claude to find and fix cybersecurity vulnerabilities across government systems\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T17:22:56Z\",\"_id\":\"fYxjGGEIxl5FrJqEfAZWoz\",\"_rev\":\"L1sWYwVuS7u8WeTHm64FmP\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:13Z\",\"description\":\"Hand with padlock and key on detailed security graphic\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-d3dd09ad16c68461dc3fb01df5e84cf7ccafda6c-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/d3dd09ad16c68461dc3fb01df5e84cf7ccafda6c-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, lock, security, protection, key, safety, padlock, privacy, access control, confidentiality, security features, privacy protection, safety measures, confidential information\",\"name\":\"Hand Lock\",\"type\":\"hero\"}},\"publishedOn\":\"2026-07-02T21:07:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"fable-safeguards-jailbreak-framework\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"More details on Fable 5’s cyber safeguards and our jailbreak framework\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1620,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/2039cc549c023bc855671308211d20d3382828a9-2880x1620.jpg\",\"width\":2880},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-06-30T18:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-sonnet-5\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":\"Sonnet 5 delivers frontier performance across coding, agents, and professional work at scale.\",\"title\":\"Introducing Claude Sonnet 5\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1620,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b7055119423427c40a0e4d84054aed17682b50a2-2880x1620.png\",\"width\":2880},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-06-30T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"redeploying-fable-5\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Fable 5 returns globally July 1. We're also proposing an industry-wide framework for scoring jailbreak severity, together with Amazon, Microsoft, Google, and other Glasswing partners. \",\"title\":\"Redeploying Fable 5\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"a node in a desktop\",\"height\":1620,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/0c547c61b24e6ad4985c64f04f212c7411609bfa-2880x1620.png\",\"width\":2880},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-06-30T15:07:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-science-ai-workbench\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":\"Claude Science is a customizable app that integrates the tools and packages researchers most often use, produces auditable artifacts, and provides flexible access to computing resources.\",\"title\":\"Claude Science, an AI workbench for scientists, is now available\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b9ba85fd4d8beaf4efe04a4cf6cec14761e52c78-2400x1260.jpg\",\"width\":2400},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2026-06-23T14:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"introducing-claude-tag\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":\"Claude Tag is a new way for teams to work with Claude.\",\"title\":\"Introducing Claude Tag\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:30Z\",\"_id\":\"Z7bXjXUrfbilTWp6Lm0RMk\",\"_rev\":\"znUZZ0fmIk1XIVDY2KGkIb\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:24Z\",\"description\":\"Globe with detailed world map and textured landmasses on a spherical surface\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-ffc0d7957a232518519f13c0d64896921ea215e2-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ffc0d7957a232518519f13c0d64896921ea215e2-1000x1000.svg\",\"width\":1000},\"keywords\":\"globe, world, earth, planet, global, worldwide, international, universal, global reach, world map, international scope, planetary, worldwide network, global connections\",\"name\":\"Object Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2026-06-17T19:34:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"seoul-office-partnerships-korean-ai-ecosystem\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic opens Seoul office and announces new partnerships across the Korean AI ecosystem\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b296093596b38f0a5fb56b85760baed37ea6798b-2400x1260.png\",\"width\":2400},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-06-12T23:38:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"fable-mythos-access\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"The US government has issued an export control directive to suspend all access to Fable 5 and Mythos 5.\",\"title\":\"Statement on the US government directive to suspend access to Fable 5 and Mythos 5\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-hands-globe\",\"_rev\":\"Z7bXjXUrfbilTWp6Ln6egF\",\"_system\":{\"base\":{\"id\":\"illustration-hero-hands-globe\",\"rev\":\"ywswJJUxLstmcebkfFkPnG\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-17T21:41:13Z\",\"description\":\" \",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-b68cbb43d7c8f56f0b14cc867e8d4d74445f78b0-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b68cbb43d7c8f56f0b14cc867e8d4d74445f78b0-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, globe, planet, world, earth, sphere, global, grid, global reach, worldwide, international, environmental, universal, global business, international services, worldwide reach, internet, web, world wide web, online, connectivity, global network, web services, international connectivity, global internet\",\"name\":\"Hand Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2026-06-12T21:51:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-public-record\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Results from the first Anthropic Public Record\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:32:35Z\",\"_id\":\"DElaXo1A74rjItEmVagig7\",\"_rev\":\"L1sWYwVuS7u8WeTHm64qP4\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:37Z\",\"description\":\"Hand with connecting network nodes and lines on abstract background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, line, node, connection, network, collaboration, teamwork, working together, cooperative work, team connection, collaborative effort, partnership, joint work, team communication, collaborative network\",\"name\":\"Hand NodeLine\",\"type\":\"hero\"}},\"publishedOn\":\"2026-06-12T18:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"tcs-anthropic-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’re announcing a partnership with Tata Consultancy Services (TCS). TCS will provide Claude to 50,000 of its own employees across 56 countries; build Claude-powered products for clients in financial services, healthcare, the public sector, and other regulated industries; and join the Claude Partner Network.\",\"title\":\"TCS and Anthropic partner to bring Claude to regulated industries\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"coral\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:49Z\",\"_id\":\"L5WZ73ZndVNkcSTU1XnMQV\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Ifrg\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:35Z\",\"description\":\"Hand holding large megaphone with detailed graphic elements and silhouette design\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-60d39963d844bc1104a780c762c540c9ba1baefe-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/60d39963d844bc1104a780c762c540c9ba1baefe-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, megaphone, announcement, broadcasting, communication, amplification, public speaking, marketing, promotion, voice, outreach, messaging, advertising, campaign, loud, attention\",\"name\":\"Hand Megaphone\",\"type\":\"hero\"}},\"publishedOn\":\"2026-06-11T18:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"dxc-anthropic-alliance\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’re announcing a multi-year global alliance with DXC Technology, one of the world’s largest IT services companies.\",\"title\":\"DXC will integrate Claude into the systems banks, airlines, and other regulated industries rely on\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2026-06-11T13:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-corps\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":\"We’re launching Claude Corps, a national fellowship program for people early in their careers who are passionate about extending the benefits of AI to communities across America.\",\"title\":\"Introducing Claude Corps\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"The number five composed of several butterflies\",\"height\":1620,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b7055119423427c40a0e4d84054aed17682b50a2-2880x1620.png\",\"width\":2880},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-06-09T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-fable-5-mythos-5\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Our next generation of intelligence for the hardest knowledge work and coding problems.\",\"title\":\"Claude Fable 5 and Claude Mythos 5\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:23Z\",\"_id\":\"Z7bXjXUrfbilTWp6Llz4FF\",\"_rev\":\"CIQMb8zr2hKNcFuuO2JBUf\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:20Z\",\"description\":\"Hand with geometric shapes constructing a complex abstract form on white background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6905c83d0735e1bc430025fdd1748d1406079036-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6905c83d0735e1bc430025fdd1748d1406079036-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, shape, build, construction, creating, forming, shaping, molding, crafting, building, assembly, development, formation, creative construction, hands-on building, collaboration, teamwork, collaborative building, artifacts, interactive creation, AI-assisted building, collaborative development, working together\",\"name\":\"Hand ShapeBuild\",\"type\":\"hero\"}},\"publishedOn\":\"2026-06-03T13:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"services-track-partner-hub\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Introducing the Services Track and Partner Hub of the Claude Partner Network\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"},{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2026-02-20T14:56:42Z\",\"_id\":\"be10271f-1b3a-415a-8c7b-de3270ecca4a\",\"_rev\":\"qY14ovG70H1L8z3NicQiuU\",\"_type\":\"illustration\",\"_updatedAt\":\"2026-02-20T15:03:04Z\",\"description\":\"Open laptop with lock iconography showing on its inner screen\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-802260d34a0653f23fd4944fae43064df367aa44-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/802260d34a0653f23fd4944fae43064df367aa44-1000x1000.svg\",\"width\":1000},\"keywords\":\"security, laptop, laptopsecure, cyber, cybersecurity, secure, laptop\",\"name\":\"Object-LaptopSecure\",\"type\":\"hero\"}},\"publishedOn\":\"2026-06-03T10:55:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"AI-enabled-cyber-threats-mitre-attack\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"},{\"_key\":\"frontier-red-team\",\"_type\":\"tag\",\"label\":\"Frontier Red Team\",\"value\":\"frontier-red-team\"}],\"summary\":\"As AI changes how cyberattacks happen, how well do the security community's frameworks hold up? A new report maps attacks onto MITRE ATT\u0026CK.\",\"title\":\"What we learned mapping a year’s worth of AI-enabled cyber threats\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-06-02T11:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"expanding-project-glasswing\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’re extending Project Glasswing to approximately 150 new organizations in more than fifteen countries. \",\"title\":\"Expanding Project Glasswing\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-06-01T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"confidential-draft-s1-sec\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Anthropic has confidentially submitted a draft S-1 registration statement to the Securities and Exchange Commission\",\"title\":\"Anthropic confidentially submits draft S-1 to the SEC\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"coral\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-objects-growth\",\"_rev\":\"YCJsOBtfHCRsnR2sTmNfaV\",\"_system\":{\"base\":{\"id\":\"illustration-hero-objects-growth\",\"rev\":\"fiXPOAGczSPPY2Y6NiKfFe\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-17T12:47:22Z\",\"description\":\"Curved upward growth line\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-c0af2a56f56cf298ce5904f2901e9a36facd0dbe-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/c0af2a56f56cf298ce5904f2901e9a36facd0dbe-1000x1000.svg\",\"width\":1000},\"name\":\"Object Growth\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-28T17:13:20.706Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"series-h\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Anthropic has raised $65 billion in Series H funding led by Altimeter Capital, Dragoneer, Greenoaks, and Sequoia Capital.\",\"title\":\"Anthropic raises $65B in Series H funding at $965B post-money valuation\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-05-28T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-opus-4-8\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"},{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"An upgrade to our Opus class of models, with stronger performance across coding, agentic tasks, and professional work, and the consistency to handle long-running work.\",\"title\":\"Introducing Claude Opus 4.8\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:32:49Z\",\"_id\":\"Z7bXjXUrfbilTWp6Llx9XF\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IM4d\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:57:01Z\",\"description\":\"Hand with urban skyline and corporate buildings, representing business growth and enterprise development\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-60d57c0d0bf031e140de678692f7c3ef2d885ce3-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/60d57c0d0bf031e140de678692f7c3ef2d885ce3-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, city, enterprise, business growth, corporate development, scaling, expansion, enterprise solutions, business ecosystem, corporate skyline, organizational growth, market expansion, enterprise services, business infrastructure, corporate strategy, scaling up, business development\",\"name\":\"Hand City\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-27T21:16:00.842Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"milan-office-opening\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We're opening a new office in Milan, our sixth in Europe.\",\"title\":\"Anthropic opens Milan office to support Italian enterprise, research, and developers\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:30Z\",\"_id\":\"Z7bXjXUrfbilTWp6Lm0RMk\",\"_rev\":\"znUZZ0fmIk1XIVDY2KGkIb\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:24Z\",\"description\":\"Globe with detailed world map and textured landmasses on a spherical surface\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-ffc0d7957a232518519f13c0d64896921ea215e2-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ffc0d7957a232518519f13c0d64896921ea215e2-1000x1000.svg\",\"width\":1000},\"keywords\":\"globe, world, earth, planet, global, worldwide, international, universal, global reach, world map, international scope, planetary, worldwide network, global connections\",\"name\":\"Object Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-26T23:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"kiyoung-choi-representative-director-anthropic-korea\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic appoints KiYoung Choi as Representative Director of Korea ahead of Seoul office opening\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:35Z\",\"_id\":\"DElaXo1A74rjItEmVahiln\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IdYy\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:21Z\",\"description\":\"Ornate quill pen resting on a detailed hand, positioned against a textured background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, quill, writing, pen, authoring, documentation, content creation, writing tools, literary work, composition, manuscript, creative writing, text creation\",\"name\":\"Hand Quill\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-25T17:10:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"chris-olah-pope-leo-encyclical\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"The full text of Chris Olah's remarks on the Pope's encyclical on AI.\",\"title\":\"Anthropic co-founder Chris Olah's remarks on Pope Leo XIV's encyclical \\\"Magnifica humanitas\\\"\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1080,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/9f76163fe710723283a55b9f60d5caca6697dffd-1920x1080.jpg\",\"width\":1920},\"directories\":[{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"},{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-05-22T18:00:12.585Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"glasswing-initial-update\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"An early update on what we've learned from Project Glasswing. \",\"title\":\"Project Glasswing: An initial update\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:34Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIxKbf\",\"_rev\":\"MSyv171NSvWZvUt9ouJx8y\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:16Z\",\"description\":\"Speech bubble with detailed conversation graphic on textured background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-8d339ae8ecedecc1409db8f5bbb99c958db56946-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/8d339ae8ecedecc1409db8f5bbb99c958db56946-1000x1000.svg\",\"width\":1000},\"keywords\":\"chat, speech bubble, conversation, communication, dialogue, messaging, discussion, talk, speaking, conversation bubble, communication tool, dialogue box, messaging interface\",\"name\":\"Object Chat\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-19T21:55:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"widening-conversation-ai\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Over the past several months, we’ve been organizing dialogues with groups whose work and traditions bear on the questions raised by AI. \",\"title\":\"Widening the conversation on frontier AI\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:23Z\",\"_id\":\"Z7bXjXUrfbilTWp6Llz4FF\",\"_rev\":\"CIQMb8zr2hKNcFuuO2JBUf\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:20Z\",\"description\":\"Hand with geometric shapes constructing a complex abstract form on white background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6905c83d0735e1bc430025fdd1748d1406079036-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6905c83d0735e1bc430025fdd1748d1406079036-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, shape, build, construction, creating, forming, shaping, molding, crafting, building, assembly, development, formation, creative construction, hands-on building, collaboration, teamwork, collaborative building, artifacts, interactive creation, AI-assisted building, collaborative development, working together\",\"name\":\"Hand ShapeBuild\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-19T12:30:10.501Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-kpmg\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"KPMG and Anthropic announce a global alliance, with Claude integrated into KPMG's Digital Gateway platform and available to all 276,000+ employees.\",\"title\":\"KPMG integrates Claude across its core business and workforce of more than 276,000 in strategic alliance\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"coral\",\"illustration\":{\"_createdAt\":\"2025-07-17T17:08:54Z\",\"_id\":\"Z7bXjXUrfbilTWp6LkjlDk\",\"_rev\":\"L1sWYwVuS7u8WeTHm68nwv\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:01:32Z\",\"description\":\"Geometric node shapes with interconnected abstract forms and structural elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-d4b15045df86e43e5b5dc7b25784321ce8b5dd88-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/d4b15045df86e43e5b5dc7b25784321ce8b5dd88-1000x1000.svg\",\"width\":1000},\"keywords\":\"shapes, geometric, forms, structure, building blocks, elements, components, design elements, geometric patterns, structural elements, modular, composition, simple\",\"name\":\"Node Shapes\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-18T17:02:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-acquires-stainless\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Anthropic is acquiring Stainless, a leader in SDKs and MCP server tooling. \",\"title\":\"Anthropic acquires Stainless\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:36Z\",\"_id\":\"Z7bXjXUrfbilTWp6LlzB1F\",\"_rev\":\"znUZZ0fmIk1XIVDY2KIj8V\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:04:33Z\",\"description\":\"Stylized globe with programming code elements and technical design details\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-b5c98d26c46edc43193e7f7e28a00633a538bb9c-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b5c98d26c46edc43193e7f7e28a00633a538bb9c-1000x1000.svg\",\"width\":1000},\"keywords\":\"code, globe, world, global, programming, worldwide development, international coding, global software, web development, worldwide programming, international development, coding worldwide\",\"name\":\"Object CodeGlobe\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-14T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"pwc-expanded-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"PwC will roll out Claude Code and Cowork starting with U.S. teams and expanding toward a global workforce of hundreds of thousands of professionals, establish a joint Center of Excellence, and train and certify 30,000 PwC professionals on Claude.\",\"title\":\"PwC is deploying Claude to build technology, execute deals, and reinvent enterprise functions for clients\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"coral\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:23Z\",\"_id\":\"Z7bXjXUrfbilTWp6Llz4FF\",\"_rev\":\"CIQMb8zr2hKNcFuuO2JBUf\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:20Z\",\"description\":\"Hand with geometric shapes constructing a complex abstract form on white background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6905c83d0735e1bc430025fdd1748d1406079036-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6905c83d0735e1bc430025fdd1748d1406079036-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, shape, build, construction, creating, forming, shaping, molding, crafting, building, assembly, development, formation, creative construction, hands-on building, collaboration, teamwork, collaborative building, artifacts, interactive creation, AI-assisted building, collaborative development, working together\",\"name\":\"Hand ShapeBuild\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-14T14:45:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"gates-foundation-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":\"We’re partnering with the Gates Foundation to commit $200 million in grant funding, Claude usage credits, and technical support for programs in global health, life sciences, education, and economic mobility over the next four years.\",\"title\":\"Anthropic forms $200 million partnership with the Gates Foundation\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2026-05-13T12:15:59Z\",\"_id\":\"2b4f7790-3e43-4fd5-ae59-185c2590e8a6\",\"_rev\":\"8qLNchI39XSox8iDcva6RC\",\"_type\":\"illustration\",\"_updatedAt\":\"2026-05-13T12:18:06Z\",\"description\":\"A hand-drawn storefront, scalloped awning over a simple building with an open doorway.\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-8b8b97e4751b8167a04ce6c7fb7ad8d240c44ccf-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/8b8b97e4751b8167a04ce6c7fb7ad8d240c44ccf-1000x1000.svg\",\"width\":1000},\"name\":\"Object Store\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-13T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-for-small-business\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":\"We're launching Claude for Small Business, a package of connectors and ready-to-run workflows that put Claude inside the tools small businesses use every day.\\n\",\"title\":\"Introducing Claude for Small Business\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-07-17T15:25:22Z\",\"_id\":\"Xjt2eTPpfxUE2CfkIxE28E\",\"_rev\":\"znUZZ0fmIk1XIVDY2KEw1j\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:53Z\",\"description\":\"Interconnected globe with network nodes and global connection lines\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-5f455d24ea80569b34eb4347f06152d8a5508722-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5f455d24ea80569b34eb4347f06152d8a5508722-1000x1000.svg\",\"width\":1000},\"keywords\":\"globe, world, global, international, worldwide, planet, earth, sphere, universal, global reach\",\"name\":\"Node Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-06T14:36:27.834Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"higher-limits-spacex\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’ve raised Claude's usage limits and agreed a new compute partnership with SpaceX that will substantially increase our capacity in the near term. \",\"title\":\"Higher usage limits for Claude and a compute deal with SpaceX\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2026-05-04T17:18:23Z\",\"_id\":\"945a2158-2912-4a2b-b858-1aa5b29c2e9e\",\"_rev\":\"02XSrm4cN5LQfUsPZezVpd\",\"_type\":\"illustration\",\"_updatedAt\":\"2026-05-04T17:19:54Z\",\"description\":\"Increasing bar chart with node lines and arrow tracing the bars\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-b9dd79810f74fbcc763cc89643d86cdea1439a26-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b9dd79810f74fbcc763cc89643d86cdea1439a26-1000x1000.svg\",\"width\":1000},\"keywords\":\"chart, bar chart, graph, data, statistics, analytics, metrics, performance, growth, visualization, business intelligence, reporting, analysis, trends, measurement, dashboard, KPIs\",\"name\":\"Node-GraphChart\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-05T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"finance-agents\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We're releasing ten new Cowork and Claude Code plugins, integrations with the Microsoft 365 suite, new connectors, and an MCP app for financial services and insurance organizations.\",\"title\":\"Agents for financial services\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:32:35Z\",\"_id\":\"DElaXo1A74rjItEmVagig7\",\"_rev\":\"L1sWYwVuS7u8WeTHm64qP4\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:37Z\",\"description\":\"Hand with connecting network nodes and lines on abstract background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, line, node, connection, network, collaboration, teamwork, working together, cooperative work, team connection, collaborative effort, partnership, joint work, team communication, collaborative network\",\"name\":\"Hand NodeLine\",\"type\":\"hero\"}},\"publishedOn\":\"2026-05-04T15:42:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"enterprise-ai-services-company\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Building a new enterprise AI services company with Blackstone, Hellman \u0026 Friedman, and Goldman Sachs \"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T20:06:33Z\",\"_id\":\"DElaXo1A74rjItEmVb2CPT\",\"_rev\":\"L1sWYwVuS7u8WeTHm67aDV\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:27Z\",\"description\":\"Hand with pointing arrow on abstract geometric background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-a62b6eb169818f14c35b7a192af269e283f8fa93-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/a62b6eb169818f14c35b7a192af269e283f8fa93-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, arrow, shape, direction, pointing, guidance, navigation, flow, movement, directional, routing, pathways, directional flow, guiding, steering, async tasks, asynchronous, background processes, queued tasks, task flow, process flow, workflow\",\"name\":\"Hand ShapeArrow\",\"type\":\"hero\"}},\"publishedOn\":\"2026-04-28T19:22:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-for-creative-work\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude for Creative Work\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-04-27T21:53:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"theo-hourmouzis-general-manager-australia-new-zealand\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic names Theo Hourmouzis General Manager of Australia \u0026 New Zealand and officially opens Sydney office\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:31Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIwKbJ\",\"_rev\":\"znUZZ0fmIk1XIVDY2KBEUv\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:14Z\",\"description\":\"Hand casting vote into ballot box with detailed silhouette and voting process elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-b985f463a13a1910397e012c153a01de33cf999b-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b985f463a13a1910397e012c153a01de33cf999b-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, vote, ballot, election, democracy, choice, selection, voting, civic engagement, democratic process, electoral participation, political choice, ballot box\",\"name\":\"Hand Vote\",\"type\":\"hero\"}},\"publishedOn\":\"2026-04-24T09:47:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"election-safeguards-update\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We explain what we’re doing to ensure Claude plays a positive role in the US midterms and other major elections around the world this year.\",\"title\":\"An update on our election safeguards\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-12-01T19:47:36Z\",\"_id\":\"c8ef25cb-13c5-4cac-a1c3-d4789f7f57e2\",\"_rev\":\"ia64CYLPlfSseOjkrzjANj\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-12-01T20:05:45Z\",\"description\":\"Stylized hands holding interconnected globe made of network nodes and global connection lines\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-4df0ff37e58fe70b216d31d8fcf6f0045a4d5694-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/4df0ff37e58fe70b216d31d8fcf6f0045a4d5694-1000x1000.svg\",\"width\":1000},\"name\":\"Hand NodeGlobe\",\"type\":\"hero\"}},\"publishedOn\":\"2026-04-24T03:52:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-nec\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic and NEC collaborate to build Japan’s largest AI engineering workforce\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:36:49Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIxDT5\",\"_rev\":\"MSyv171NSvWZvUt9ouLB5i\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:03:26Z\",\"description\":\"Geometric staircase steps ascending vertically with incremental progression\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-ddad92700787ec1bf1d80359c0c5e6ca305682b0-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ddad92700787ec1bf1d80359c0c5e6ca305682b0-1000x1000.svg\",\"width\":1000},\"keywords\":\"stairs, steps, staircase, ascending, climbing, progress, advancement, step by step, upward movement, progression, gradual improvement, levels, incremental progress, growth, momentum, building momentum, steady growth, upward trajectory, continuous improvement, scaling up\",\"name\":\"Object Stairs\",\"type\":\"hero\"}},\"publishedOn\":\"2026-04-20T15:50:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-amazon-compute\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic and Amazon expand collaboration for up to 5 gigawatts of new compute\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:35Z\",\"_id\":\"DElaXo1A74rjItEmVahiln\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IdYy\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:21Z\",\"description\":\"Ornate quill pen resting on a detailed hand, positioned against a textured background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, quill, writing, pen, authoring, documentation, content creation, writing tools, literary work, composition, manuscript, creative writing, text creation\",\"name\":\"Hand Quill\",\"type\":\"hero\"}},\"publishedOn\":\"2026-04-17T14:32:27.021Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-design-anthropic-labs\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"},{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Today, we’re launching Claude Design, a new Anthropic Labs product that lets you collaborate with Claude to create polished visual work like designs, prototypes, slides, one-pagers, and more.\",\"title\":\"Introducing Claude Design by Anthropic Labs\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-04-16T14:30:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-opus-4-7\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"},{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Our latest Opus model brings stronger performance across coding, agents, vision, and multi-step tasks, with greater thoroughness and consistency on the work that matters most.\",\"title\":\"Introducing Claude Opus 4.7\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2026-04-14T23:34:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"narasimhan-board\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\" Anthropic’s Long-Term Benefit Trust appoints Vas Narasimhan to Board of Directors\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-objects-growth\",\"_rev\":\"YCJsOBtfHCRsnR2sTmNfaV\",\"_system\":{\"base\":{\"id\":\"illustration-hero-objects-growth\",\"rev\":\"fiXPOAGczSPPY2Y6NiKfFe\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-17T12:47:22Z\",\"description\":\"Curved upward growth line\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-c0af2a56f56cf298ce5904f2901e9a36facd0dbe-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/c0af2a56f56cf298ce5904f2901e9a36facd0dbe-1000x1000.svg\",\"width\":1000},\"name\":\"Object Growth\",\"type\":\"hero\"}},\"publishedOn\":\"2026-04-06T21:16:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"google-broadcom-partnership-compute\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic expands partnership with Google and Broadcom for multiple gigawatts of next-generation compute\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T15:25:22Z\",\"_id\":\"Xjt2eTPpfxUE2CfkIxE28E\",\"_rev\":\"znUZZ0fmIk1XIVDY2KEw1j\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:53Z\",\"description\":\"Interconnected globe with network nodes and global connection lines\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-5f455d24ea80569b34eb4347f06152d8a5508722-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5f455d24ea80569b34eb4347f06152d8a5508722-1000x1000.svg\",\"width\":1000},\"keywords\":\"globe, world, global, international, worldwide, planet, earth, sphere, universal, global reach\",\"name\":\"Node Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2026-03-31T21:36:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"australia-MOU\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Australian government and Anthropic sign MOU for AI safety and research \"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:23Z\",\"_id\":\"Z7bXjXUrfbilTWp6Llz4FF\",\"_rev\":\"CIQMb8zr2hKNcFuuO2JBUf\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:20Z\",\"description\":\"Hand with geometric shapes constructing a complex abstract form on white background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6905c83d0735e1bc430025fdd1748d1406079036-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6905c83d0735e1bc430025fdd1748d1406079036-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, shape, build, construction, creating, forming, shaping, molding, crafting, building, assembly, development, formation, creative construction, hands-on building, collaboration, teamwork, collaborative building, artifacts, interactive creation, AI-assisted building, collaborative development, working together\",\"name\":\"Hand ShapeBuild\",\"type\":\"hero\"}},\"publishedOn\":\"2026-03-12T14:39:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-partner-network\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’re launching the Claude Partner Network, a program for partner organizations helping enterprises adopt Claude.\",\"title\":\"Anthropic invests $100 million into the Claude Partner Network\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-objects-book\",\"_rev\":\"8HPy2aUcIlj1EexSnH63wi\",\"_system\":{\"base\":{\"id\":\"illustration-hero-objects-book\",\"rev\":\"ywswJJUxLstmcebkfFmTh4\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-17T12:47:26Z\",\"description\":\"Spiral-bound notebook with page\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-9dc697ebe294bef5961c93928128a9b561fc1f66-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/9dc697ebe294bef5961c93928128a9b561fc1f66-1000x1000.svg\",\"width\":1000},\"name\":\"Object Book\",\"type\":\"hero\"}},\"publishedOn\":\"2026-03-11T10:45:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"the-anthropic-institute\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’re launching The Anthropic Institute, a new effort to confront the most significant challenges that powerful AI will pose to our societies.\",\"title\":\"Introducing The Anthropic Institute\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-hands-globe\",\"_rev\":\"Z7bXjXUrfbilTWp6Ln6egF\",\"_system\":{\"base\":{\"id\":\"illustration-hero-hands-globe\",\"rev\":\"ywswJJUxLstmcebkfFkPnG\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-17T21:41:13Z\",\"description\":\" \",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-b68cbb43d7c8f56f0b14cc867e8d4d74445f78b0-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b68cbb43d7c8f56f0b14cc867e8d4d74445f78b0-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, globe, planet, world, earth, sphere, global, grid, global reach, worldwide, international, environmental, universal, global business, international services, worldwide reach, internet, web, world wide web, online, connectivity, global network, web services, international connectivity, global internet\",\"name\":\"Hand Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2026-03-10T18:22:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"sydney-fourth-office-asia-pacific\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Sydney will become Anthropic’s fourth office in Asia-Pacific \"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"},{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"}],\"illustration\":{\"backgroundColor\":\"coral\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:36:59Z\",\"_id\":\"DElaXo1A74rjItEmVajwhL\",\"_rev\":\"L1sWYwVuS7u8WeTHm6AQyV\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:03:20Z\",\"description\":\"Balance scale with weighing platform, symbolic of legal justice and fairness\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-589b94b913c4cee1c3c1ce2cb04f638d09c465b1-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/589b94b913c4cee1c3c1ce2cb04f638d09c465b1-1000x1000.svg\",\"width\":1000},\"keywords\":\"desktop, computer, monitor, screen, display, workstation, computer screen, digital workspace, computing, technology, work computer, office setup, computer interface\",\"name\":\"Object Desktop\",\"type\":\"hero\"}},\"publishedOn\":\"2026-03-06T10:30:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"mozilla-firefox-security\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"},{\"_key\":\"frontier-red-team\",\"_type\":\"tag\",\"label\":\"Frontier Red Team\",\"value\":\"frontier-red-team\"}],\"summary\":null,\"title\":\"Partnering with Mozilla to improve Firefox’s security\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-03-05T21:43:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"where-stand-department-war\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":\"A statement from Dario Amodei.\",\"title\":\"Where things stand with the Department of War\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-02-27T23:38:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"statement-comments-secretary-war\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":\"Anthropic's response to the Secretary of War and advice to customers.\",\"title\":\"Statement on the comments from Secretary of War Pete Hegseth\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-02-26T21:55:36.531Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"statement-department-of-war\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":\"A statement from our CEO on national security uses of AI.\",\"title\":\"Statement from Dario Amodei on our discussions with the Department of War \"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"coral\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-nodes-cursor\",\"_rev\":\"OZufsS7Dki5clSQyDb39sP\",\"_system\":{\"base\":{\"id\":\"illustration-hero-nodes-cursor\",\"rev\":\"ywswJJUxLstmcebkfFluvi\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-21T14:08:05Z\",\"description\":\"Computer cursor pointer with intricate detailed design and curved outline on white background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-8925ac952fa2cb8eb5e845b2e44f3e71b33fd695-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/8925ac952fa2cb8eb5e845b2e44f3e71b33fd695-1000x1000.svg\",\"width\":1000},\"keywords\":\"cursor, click, computer, cursor, pointer, arrow, direction, selection, targeting, pointing, navigation, interface, user interaction, digital interface, click, select, navigation tool\",\"name\":\"Node Cursor\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-25T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"acquires-vercept\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic acquires Vercept to advance Claude's computer use capabilities\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:35Z\",\"_id\":\"DElaXo1A74rjItEmVahiln\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IdYy\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:21Z\",\"description\":\"Ornate quill pen resting on a detailed hand, positioned against a textured background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, quill, writing, pen, authoring, documentation, content creation, writing tools, literary work, composition, manuscript, creative writing, text creation\",\"name\":\"Hand Quill\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-24T14:59:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"responsible-scaling-policy-v3\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"},{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic’s Responsible Scaling Policy: Version 3.0\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:14Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIxHdd\",\"_rev\":\"CIQMb8zr2hKNcFuuO2JwGj\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:50Z\",\"description\":\"Large padlock with intricate design against minimalist background, showing security and protection mechanism\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-e029027e0b3beeb5b629bd4a26143597e7775b38-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/e029027e0b3beeb5b629bd4a26143597e7775b38-1000x1000.svg\",\"width\":1000},\"keywords\":\"lock, security, protection, privacy, safety, secure, locked, access control, security measure, protection system, safeguarding, confidential, restricted access\",\"name\":\"Object Lock\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-23T18:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"detecting-and-preventing-distillation-attacks\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":\"We have identified industrial-scale campaigns by three AI laboratories—DeepSeek, Moonshot, and MiniMax—to illicitly extract Claude’s capabilities to improve their own models.\",\"title\":\"Detecting and preventing distillation attacks \"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2026-02-20T14:56:42Z\",\"_id\":\"be10271f-1b3a-415a-8c7b-de3270ecca4a\",\"_rev\":\"qY14ovG70H1L8z3NicQiuU\",\"_type\":\"illustration\",\"_updatedAt\":\"2026-02-20T15:03:04Z\",\"description\":\"Open laptop with lock iconography showing on its inner screen\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-802260d34a0653f23fd4944fae43064df367aa44-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/802260d34a0653f23fd4944fae43064df367aa44-1000x1000.svg\",\"width\":1000},\"keywords\":\"security, laptop, laptopsecure, cyber, cybersecurity, secure, laptop\",\"name\":\"Object-LaptopSecure\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-20T17:59:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-code-security\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Claude Code Security, a new capability built into Claude Code on the web, is now available in a limited research preview. It scans codebases for security vulnerabilities and suggests targeted software patches for human review, allowing teams to find and fix security issues that traditional methods often miss.\",\"title\":\"Making frontier cybersecurity capabilities available to defenders\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-17T20:37:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-rwanda-mou\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":null,\"title\":\"Anthropic and the Government of Rwanda sign MOU for AI in health and education\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2026-02-05T04:24:06Z\",\"_id\":\"1c7675fe-be95-4e27-8d64-75241b7d65a4\",\"_rev\":\"aLJWpLS1Zv36ohV3WU10uP\",\"_type\":\"illustration\",\"_updatedAt\":\"2026-02-05T04:26:07Z\",\"description\":\"Outline of head with nodes floating around\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-60a35c504cedb3e3f581b211e4b8aef372ffe031-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/60a35c504cedb3e3f581b211e4b8aef372ffe031-1000x1000.svg\",\"width\":1000},\"keywords\":\"Head, nodes\",\"name\":\"Node-Head-Constellation\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-17T18:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-sonnet-4-6\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":\"Sonnet 4.6 delivers frontier performance across coding, agents, and professional work at scale.\\n\",\"title\":\"Introducing Claude Sonnet 4.6\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:32:45Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIw0mv\",\"_rev\":\"L1sWYwVuS7u8WeTHm657Vc\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:55Z\",\"description\":\"Two stylized hands reaching toward each other with connecting node points\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-9f6a378a1e3592cf8d27447457409ba12284faef-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/9f6a378a1e3592cf8d27447457409ba12284faef-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, pair, node, two, connection, partnership, collaboration, direct communication, teamwork, working together, direct\",\"name\":\"Hand NodePair\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-17T06:19:07.669Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-infosys\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic and Infosys collaborate to build AI agents for telecommunications and other regulated industries\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:30Z\",\"_id\":\"Z7bXjXUrfbilTWp6Lm0RMk\",\"_rev\":\"znUZZ0fmIk1XIVDY2KGkIb\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:24Z\",\"description\":\"Globe with detailed world map and textured landmasses on a spherical surface\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-ffc0d7957a232518519f13c0d64896921ea215e2-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ffc0d7957a232518519f13c0d64896921ea215e2-1000x1000.svg\",\"width\":1000},\"keywords\":\"globe, world, earth, planet, global, worldwide, international, universal, global reach, world map, international scope, planetary, worldwide network, global connections\",\"name\":\"Object Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-16T13:49:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"bengaluru-office-partnerships-across-india\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic opens Bengaluru office and announces new partnerships across India \"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-07-17T20:06:33Z\",\"_id\":\"DElaXo1A74rjItEmVb2CPT\",\"_rev\":\"L1sWYwVuS7u8WeTHm67aDV\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:27Z\",\"description\":\"Hand with pointing arrow on abstract geometric background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-a62b6eb169818f14c35b7a192af269e283f8fa93-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/a62b6eb169818f14c35b7a192af269e283f8fa93-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, arrow, shape, direction, pointing, guidance, navigation, flow, movement, directional, routing, pathways, directional flow, guiding, steering, async tasks, asynchronous, background processes, queued tasks, task flow, process flow, workflow\",\"name\":\"Hand ShapeArrow\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-13T20:47:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-codepath-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":null,\"title\":\"Anthropic partners with CodePath to bring Claude to the US’s largest collegiate computer science program\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2026-02-13T14:57:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"chris-liddell-appointed-anthropic-board\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Chris Liddell appointed to Anthropic’s board of directors\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T17:19:26Z\",\"_id\":\"DElaXo1A74rjItEmVZA4O7\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Hwkp\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:55:37Z\",\"description\":\"hand, chart, bar chart, graph, data, statistics, analytics, metrics, performance, growth, visualization, business intelligence, reporting, analysis, trends, measurement, dashboard, KPIs\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-e44a6b53398f189b9fd0d4f70516db614ac84db3-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/e44a6b53398f189b9fd0d4f70516db614ac84db3-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, chart, bar chart, graph, data, statistics, analytics, metrics, performance, growth, visualization, business intelligence, reporting, analysis, trends, measurement, dashboard, KPIs\",\"name\":\"Hand BarChart\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-12T19:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-raises-30-billion-series-g-funding-380-billion-post-money-valuation\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We have raised $30 billion in Series G funding led by GIC and Coatue, valuing Anthropic at $380 billion post-money.\",\"title\":\"Anthropic raises $30 billion in Series G funding at $380 billion post-money valuation\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-12T11:45:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"donate-public-first-action\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Anthropic is donating $20 million to Public First Action\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-10-14T22:45:34Z\",\"_id\":\"c6fb26ef-1cb6-4d82-9abe-e8d2ca4938b7\",\"_rev\":\"gGgNEK99fop1JfPvFUiqP3\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-10-15T00:02:12Z\",\"description\":\"Hand with lightning bolt and head outline in stylized profile design\",\"image\":{\"_type\":\"image\",\"_upload\":{\"createdAt\":\"2025-10-14T22:46:27.737Z\",\"file\":{\"name\":\"Hand-HeadBolt.svg\",\"type\":\"image/svg+xml\"},\"previewImage\":\"$19\",\"progress\":100,\"updatedAt\":\"2025-10-14T22:46:30.292Z\"},\"asset\":{\"_ref\":\"image-6457c34fbcb012acf0f27f15a6006f700d0f50de-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6457c34fbcb012acf0f27f15a6006f700d0f50de-1000x1000.svg\",\"width\":1000},\"keywords\":\"abstract, head, hand, bolt, lightning, lightning bolt, silhouette, geometric, molecular, minimalist, science, technology, human, interaction, profile, gesture, network\",\"name\":\"Hand HeadBolt\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-11T20:23:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"covering-electricity-price-increases\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Covering electricity price increases from our data centers\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2026-02-05T18:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-opus-4-6\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’re upgrading our smartest model. Across agentic coding, computer use, tool use, search, and finance, Opus 4.6 is an industry-leading model, often by wide margin. \",\"title\":\"Introducing Claude Opus 4.6\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T20:06:25Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKJ3yC3\",\"_rev\":\"766umayZSiZvQu52Fnum7j\",\"_system\":{\"base\":{\"id\":\"uWx6ePFJ4MmdfRYgKJ3yC3\",\"rev\":\"CIQMb8zr2hKNcFuuO2JIEb\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-08-12T15:31:06Z\",\"description\":\"Hand-shaped house with financial symbols and economic details\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-cd9cf56a7f049285b7c1c8786c0a600cf3d7f317-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/cd9cf56a7f049285b7c1c8786c0a600cf3d7f317-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, money, coin, currency, finance, payment, financial, cash, economic, monetary, funding, budget, cost, pricing, financial transactions, money management, economics\",\"name\":\"Hand House\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-04T18:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-is-a-space-to-think\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’ve made a choice: Claude will remain ad-free. We explain why advertising incentives are incompatible with a genuinely helpful AI assistant, and how we plan to expand access without compromising user trust.\",\"title\":\"Claude is a space to think\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:19Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIwqLD\",\"_rev\":\"CIQMb8zr2hKNcFuuO2J6fE\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:11Z\",\"description\":\"Hand and human head profile with network nodes and connection lines\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-f8f4644253bde2f901550431b871b6dcf91e5d9d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/f8f4644253bde2f901550431b871b6dcf91e5d9d-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, head, profile, connection, node, network, person, human connections, networking, personal relationships, social networks, human nodes, social networking, relationship building, people connections, AI, artificial intelligence, intelligence network, AI nodes, machine learning, neural network, intelligent systems, cognitive network\",\"name\":\"Hand HeadNode\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-03T18:03:29.760Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"apple-xcode-claude-agent-sdk\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Apple’s Xcode now supports the Claude Agent SDK\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-12-02T23:18:03Z\",\"_id\":\"8825c1e0-5f2f-4136-a0d1-6ee3deb42e1d\",\"_rev\":\"CrTtH2diRSq0YnQ0IiOrjb\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-12-02T23:19:12Z\",\"description\":\"Stylized double helix representing the intersection of science and human potential\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-d6058e0db8e477dc782dacae46e2ec6663d165d9-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/d6058e0db8e477dc782dacae46e2ec6663d165d9-1000x1000.svg\",\"width\":1000},\"keywords\":\"object, double helix, dna, science, research\",\"name\":\"Object DoubleHelix\",\"type\":\"hero\"}},\"publishedOn\":\"2026-02-02T14:02:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-partners-with-allen-institute-and-howard-hughes-medical-institute\"},\"subjects\":[{\"_key\":\"societal-impacts\",\"_type\":\"tag\",\"label\":\"Societal Impacts\",\"value\":\"societal-impacts\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":null,\"title\":\"Anthropic partners with Allen Institute and Howard Hughes Medical Institute to accelerate scientific discovery\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:19Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIwqLD\",\"_rev\":\"CIQMb8zr2hKNcFuuO2J6fE\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:11Z\",\"description\":\"Hand and human head profile with network nodes and connection lines\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-f8f4644253bde2f901550431b871b6dcf91e5d9d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/f8f4644253bde2f901550431b871b6dcf91e5d9d-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, head, profile, connection, node, network, person, human connections, networking, personal relationships, social networks, human nodes, social networking, relationship building, people connections, AI, artificial intelligence, intelligence network, AI nodes, machine learning, neural network, intelligent systems, cognitive network\",\"name\":\"Hand HeadNode\",\"type\":\"hero\"}},\"publishedOn\":\"2026-01-28T21:15:36.668Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"servicenow-anthropic-claude\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"ServiceNow chooses Claude to power customer apps and increase internal productivity\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2026-01-27T08:01:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"gov-UK-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic partners with the UK Government to bring AI assistance to GOV.UK services\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"},{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2026-01-16T17:51:01Z\",\"_id\":\"e3f269a6-6dab-4d35-b13b-381a28e61b4b\",\"_rev\":\"hL5komDLAXVfAiuM5IZsvT\",\"_type\":\"illustration\",\"_updatedAt\":\"2026-01-16T17:53:11Z\",\"description\":\"A curled scroll or parchment with a branching node diagram on its surface, accompanied by a feather quill resting at the bottom right corner.\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-e69f9d8245799a0c2688d72e997f708475233d6b-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/e69f9d8245799a0c2688d72e997f708475233d6b-1000x1000.svg\",\"width\":1000},\"keywords\":\"constitution, document, governance, rules, guidelines, policy, founding, charter, agreement, principles, quill, scroll, write\",\"name\":\"Node-Constitution\",\"type\":\"hero\"}},\"publishedOn\":\"2026-01-22T04:15:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-new-constitution\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude's new constitution\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:30Z\",\"_id\":\"Z7bXjXUrfbilTWp6Lm0RMk\",\"_rev\":\"znUZZ0fmIk1XIVDY2KGkIb\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:24Z\",\"description\":\"Globe with detailed world map and textured landmasses on a spherical surface\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-ffc0d7957a232518519f13c0d64896921ea215e2-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ffc0d7957a232518519f13c0d64896921ea215e2-1000x1000.svg\",\"width\":1000},\"keywords\":\"globe, world, earth, planet, global, worldwide, international, universal, global reach, world map, international scope, planetary, worldwide network, global connections\",\"name\":\"Object Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2026-01-21T05:28:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"mariano-florentino-long-term-benefit-trust\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Mariano-Florentino Cuéllar appointed to Anthropic’s Long-Term Benefit Trust\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:36:37Z\",\"_id\":\"Z7bXjXUrfbilTWp6Lm02bk\",\"_rev\":\"MSyv171NSvWZvUt9ouLOYI\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:03:40Z\",\"description\":\"Desk lamp illuminating documents and paper on work surface with writing materials\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-77dd9077412abc790bf2bc6fa3383b37724d6305-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/77dd9077412abc790bf2bc6fa3383b37724d6305-1000x1000.svg\",\"width\":1000},\"keywords\":\"lamp, paper, document, writing, work, studying, paperwork, documentation, writing work, desk work, office work, document preparation, written materials, reveal, revealing, uncovering, discovery, illumination, bringing to light, exposing, showing, unveiling\",\"name\":\"Object LampPaper\",\"type\":\"hero\"}},\"publishedOn\":\"2026-01-21T00:20:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-teach-for-all\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":null,\"title\":\"Anthropic and Teach For All launch global AI training initiative for educators\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2026-01-16T00:09:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-appoints-irina-ghose-as-managing-director-of-india\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic appoints Irina Ghose as Managing Director of India ahead of Bengaluru office opening\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T18:56:58Z\",\"_id\":\"Z7bXjXUrfbilTWp6LleCrF\",\"_rev\":\"znUZZ0fmIk1XIVDY2KBckj\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:47Z\",\"description\":\"Open book with detailed hand holding pages against textured background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-423062049d4676b41d52b16068cbb5e21603190e-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/423062049d4676b41d52b16068cbb5e21603190e-1000x1000.svg\",\"width\":1000},\"keywords\":\"book, pages, hand, reading, holding, open book, literature, knowledge, learning, education, study, information, wisdom, research, documentation, knowledge sharing, libraries\",\"name\":\"Hand Book\",\"type\":\"hero\"}},\"publishedOn\":\"2026-01-15T20:46:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"accelerating-scientific-research\"},\"subjects\":[{\"_key\":\"case-study\",\"_type\":\"tag\",\"label\":\"Case Study\",\"value\":\"case-study\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":null,\"title\":\"How scientists are using Claude to accelerate research and discovery\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":2000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b302589799164630e6b9407f46a44cfbbb473340-2000x2000.jpg\",\"width\":2000},\"directories\":[{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"},{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2026-01-15T10:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-economic-index-january-2026-report\"},\"subjects\":[{\"_key\":\"economic-research\",\"_type\":\"tag\",\"label\":\"Economics\",\"value\":\"economic-research\"}],\"summary\":\"This report introduces new metrics of AI usage to provide a rich portrait of interactions with Claude in November 2025, just prior to the release of Opus 4.5.\",\"title\":\"Anthropic Economic Index report: Economic primitives\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:34:11Z\",\"_id\":\"Z7bXjXUrfbilTWp6LlyQHk\",\"_rev\":\"znUZZ0fmIk1XIVDY2KC9Pn\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:59:22Z\",\"description\":\"Hand with code brackets and programming symbols on technical background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-0df729ce74e4c9dd62c3342c9549ce6c7cef1202-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/0df729ce74e4c9dd62c3342c9549ce6c7cef1202-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, puzzle, piece, solution, problem solving, fitting together, completion, assembly, matching, solving, integration, piece fitting, problem resolution\",\"name\":\"Hand Puzzle\",\"type\":\"hero\"}},\"publishedOn\":\"2026-01-13T19:05:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"introducing-anthropic-labs\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Introducing Labs\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-12-02T23:21:46Z\",\"_id\":\"da1ee72c-8982-4365-aaa0-1beded68cb5a\",\"_rev\":\"6tcqshdRtUsTOrvEwUFFcI\",\"_system\":{\"base\":{\"id\":\"da1ee72c-8982-4365-aaa0-1beded68cb5a\",\"rev\":\"S2OGbGOiEjROzjd6GGVv34\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-12-02T23:24:53Z\",\"description\":\"Heartbeat waveform representing the vital pulse of human-AI collaboration\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-a5be087781bd5c60788beba7d8148d147bc4d0ed-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/a5be087781bd5c60788beba7d8148d147bc4d0ed-1000x1000.svg\",\"width\":1000},\"keywords\":\"object, heartbeat, pulse, health, vitals, waveform\",\"name\":\"Object Heartbeat\",\"type\":\"hero\"}},\"publishedOn\":\"2026-01-11T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"healthcare-life-sciences\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":\"Claude for Healthcare introduces HIPAA-ready infrastructure for providers and payers, while expanded Life Sciences capabilities add connectors to Medidata and ClinicalTrials.gov for clinical trial operations and regulatory work.\",\"title\":\"Advancing Claude in healthcare and the life sciences\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-12-19T20:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"compliance-framework-SB53\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Sharing our compliance framework for California's Transparency in Frontier AI Act\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:18Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIwGgZ\",\"_rev\":\"znUZZ0fmIk1XIVDY2KAtjv\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:57:51Z\",\"description\":\"Hand telescope with detailed mechanical features and intricate silhouette design\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-c9d8dd2af6d065e1ace8bd4bb29c716eb53ffffb-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/c9d8dd2af6d065e1ace8bd4bb29c716eb53ffffb-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, telescope, observation, looking, viewing, seeing, vision, exploration, discovery, magnification, scope, future vision, prediction, forward thinking, foresight, future planning, strategic vision, anticipating, looking ahead\",\"name\":\"Hand Telescope\",\"type\":\"hero\"}},\"publishedOn\":\"2025-12-18T19:30:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"genesis-mission-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Working with the US Department of Energy to unlock the next era of scientific discovery\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"coral\",\"illustration\":{\"_createdAt\":\"2025-07-17T20:06:25Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKJ3yC3\",\"_rev\":\"766umayZSiZvQu52Fnum7j\",\"_system\":{\"base\":{\"id\":\"uWx6ePFJ4MmdfRYgKJ3yC3\",\"rev\":\"CIQMb8zr2hKNcFuuO2JIEb\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-08-12T15:31:06Z\",\"description\":\"Hand-shaped house with financial symbols and economic details\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-cd9cf56a7f049285b7c1c8786c0a600cf3d7f317-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/cd9cf56a7f049285b7c1c8786c0a600cf3d7f317-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, money, coin, currency, finance, payment, financial, cash, economic, monetary, funding, budget, cost, pricing, financial transactions, money management, economics\",\"name\":\"Hand House\",\"type\":\"hero\"}},\"publishedOn\":\"2025-12-18T19:05:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"protecting-well-being-of-users\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Protecting the wellbeing of our users\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:32:45Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIw0mv\",\"_rev\":\"L1sWYwVuS7u8WeTHm657Vc\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:55Z\",\"description\":\"Two stylized hands reaching toward each other with connecting node points\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-9f6a378a1e3592cf8d27447457409ba12284faef-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/9f6a378a1e3592cf8d27447457409ba12284faef-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, pair, node, two, connection, partnership, collaboration, direct communication, teamwork, working together, direct\",\"name\":\"Hand NodePair\",\"type\":\"hero\"}},\"publishedOn\":\"2025-12-09T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"donating-the-model-context-protocol-and-establishing-of-the-agentic-ai-foundation\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Donating the Model Context Protocol and establishing the Agentic AI Foundation\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-12-02T23:38:29Z\",\"_id\":\"2d7f48dc-ec18-4178-9d23-b1a0345ea8b6\",\"_rev\":\"CrTtH2diRSq0YnQ0IiSPUH\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-12-02T23:40:52Z\",\"description\":\"Chat bubble containing code\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-225a673c4c38ae4b0d89639836c93b27e363f185-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/225a673c4c38ae4b0d89639836c93b27e363f185-1000x1000.svg\",\"width\":1000},\"keywords\":\"Chat, code, conversation, dialogue, programming, technical assistance, collaboration, developer tools, code review, communication, text interface, messaging, AI assistant, debugging, problem-solving\",\"name\":\"Object CodeChatCode\",\"type\":\"hero\"}},\"publishedOn\":\"2025-12-09T12:34:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-accenture-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Accenture and Anthropic launch multi-year partnership to move enterprises from AI pilots to production\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:32:35Z\",\"_id\":\"DElaXo1A74rjItEmVagig7\",\"_rev\":\"L1sWYwVuS7u8WeTHm64qP4\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:37Z\",\"description\":\"Hand with connecting network nodes and lines on abstract background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, line, node, connection, network, collaboration, teamwork, working together, cooperative work, team connection, collaborative effort, partnership, joint work, team communication, collaborative network\",\"name\":\"Hand NodeLine\",\"type\":\"hero\"}},\"publishedOn\":\"2025-12-03T21:10:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"snowflake-anthropic-expanded-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Snowflake and Anthropic announce $200 million partnership to bring agentic AI to global enterprises\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-objects-puzzle\",\"_rev\":\"MSyv171NSvWZvUt9ouKnbw\",\"_system\":{\"base\":{\"id\":\"illustration-hero-objects-puzzle\",\"rev\":\"ywswJJUxLstmcebkfFoJyU\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:03:02Z\",\"description\":\"Interlocking puzzle piece with complex geometric shape and detailed surface texture\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-43abe7e54b56a891e74a8542944dfbd33f07f49c-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/43abe7e54b56a891e74a8542944dfbd33f07f49c-1000x1000.svg\",\"width\":1000},\"keywords\":\"puzzle, piece, solution, problem solving, fitting together, completion, assembly, matching, solving, integration, piece fitting, problem resolution, challenge\",\"name\":\"Object Puzzle\",\"type\":\"hero\"}},\"publishedOn\":\"2025-12-03T04:10:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-acquires-bun-as-claude-code-reaches-usd1b-milestone\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic acquires Bun as Claude Code reaches $1B milestone\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-12-01T19:47:36Z\",\"_id\":\"c8ef25cb-13c5-4cac-a1c3-d4789f7f57e2\",\"_rev\":\"ia64CYLPlfSseOjkrzjANj\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-12-01T20:05:45Z\",\"description\":\"Stylized hands holding interconnected globe made of network nodes and global connection lines\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-4df0ff37e58fe70b216d31d8fcf6f0045a4d5694-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/4df0ff37e58fe70b216d31d8fcf6f0045a4d5694-1000x1000.svg\",\"width\":1000},\"name\":\"Hand NodeGlobe\",\"type\":\"hero\"}},\"publishedOn\":\"2025-12-02T10:57:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-for-nonprofits\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Anthropic launches Claude for Nonprofits to help organizations maximize their impact, featuring free AI training and discounted rates.\",\"title\":\"Claude for Nonprofits\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-11-24T15:23:59Z\",\"_id\":\"eWLIqdlh0nWvJOX2EPCobt\",\"_rev\":\"eWLIqdlh0nWvJOX2EPCobJ\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-11-24T15:23:59Z\",\"description\":\"Hand with orbiting head silhouette in abstract geometric design\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-f79e976ee66724dffd7cb9d44f0d66223c8a112c-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/f79e976ee66724dffd7cb9d44f0d66223c8a112c-1000x1000.svg\",\"width\":1000},\"keywords\":\"Hero illustration: Hand HeadOrbit\",\"name\":\"Hand HeadOrbit\",\"type\":\"hero\"}},\"publishedOn\":\"2025-11-24T19:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-opus-4-5\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"The best model in the world for coding, agents, and computer use, with meaningful improvements to everyday tasks like slides and spreadsheets. Claude Opus 4.5 delivers frontier performance and dramatically improved token efficiency.\",\"title\":\"Introducing Claude Opus 4.5\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-22T17:14:59Z\",\"_id\":\"1I6qCutD7PCoAidr1qeQre\",\"_rev\":\"1I6qCutD7PCoAidr1qeQq2\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-22T17:14:59Z\",\"description\":\"Hand with flower-like petals emerging from palm, organic growth metaphor\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-a7b8978859371a024139418f3366bb0600ee1675-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/a7b8978859371a024139418f3366bb0600ee1675-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, flower, plant, nature, growth, organic, bloom, nurturing, care, development, blooming, organic growth, environmental topics, nurturing, development\",\"name\":\"Hand Flower\",\"type\":\"hero\"}},\"publishedOn\":\"2025-11-18T15:00:39.676Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-in-microsoft-foundry\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Claude now available in Microsoft Foundry and Microsoft 365 Copilot\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:32:35Z\",\"_id\":\"DElaXo1A74rjItEmVagig7\",\"_rev\":\"L1sWYwVuS7u8WeTHm64qP4\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:37Z\",\"description\":\"Hand with connecting network nodes and lines on abstract background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, line, node, connection, network, collaboration, teamwork, working together, cooperative work, team connection, collaborative effort, partnership, joint work, team communication, collaborative network\",\"name\":\"Hand NodeLine\",\"type\":\"hero\"}},\"publishedOn\":\"2025-11-18T15:00:24.254Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"microsoft-nvidia-anthropic-announce-strategic-partnerships\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Microsoft, NVIDIA and Anthropic announced new strategic partnerships. Anthropic is scaling its rapidly-growing Claude AI model on Microsoft Azure, powered by NVIDIA, which will broaden access to Claude and provide Azure enterprise customers with expanded model choice and new capabilities. Anthropic has committed to purchase $30 billion of Azure compute capacity and to contract additional compute capacity up to one gigawatt.\",\"title\":\"Microsoft, NVIDIA, and Anthropic announce strategic partnerships\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"coral\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-11-18T01:40:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"rwandan-government-partnership-ai-education\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":\"Anthropic is announcing a new partnership with the Government of Rwanda and African tech training provider ALX to bring Chidi—a learning companion built on Claude—to hundreds of thousands of learners across Africa.\",\"title\":\"Anthropic partners with Rwandan Government and ALX to bring AI education to hundreds of thousands of learners across Africa\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:14Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIxHdd\",\"_rev\":\"CIQMb8zr2hKNcFuuO2JwGj\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:50Z\",\"description\":\"Large padlock with intricate design against minimalist background, showing security and protection mechanism\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-e029027e0b3beeb5b629bd4a26143597e7775b38-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/e029027e0b3beeb5b629bd4a26143597e7775b38-1000x1000.svg\",\"width\":1000},\"keywords\":\"lock, security, protection, privacy, safety, secure, locked, access control, security measure, protection system, safeguarding, confidential, restricted access\",\"name\":\"Object Lock\",\"type\":\"hero\"}},\"publishedOn\":\"2025-11-13T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"disrupting-AI-espionage\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":\"In September 2025, we detected and disrupted a highly sophisticated cyber espionage campaign. We’re sharing this case publicly to help others strengthen their own defenses. \",\"title\":\"Disrupting the first reported AI-orchestrated cyber espionage campaign\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"coral\",\"illustration\":{\"_createdAt\":\"2025-07-17T17:09:04Z\",\"_id\":\"Z7bXjXUrfbilTWp6LkjoZF\",\"_rev\":\"Oe5qGRtmI2tA8S7mxF7kA7\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-22T20:28:22Z\",\"description\":\"Organic node plant with branching growth stages and interconnected developmental elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-2174acb37a84767550abfe2588eb5648f941a897-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/2174acb37a84767550abfe2588eb5648f941a897-1000x1000.svg\",\"width\":1000},\"keywords\":\"plant, growth, nature, organic, development, flourishing, natural growth, cultivation, nurturing, environmental, green, sustainability, life, growing, growth process, stages of growth, development, progression, evolving, maturing, gradual development\",\"name\":\"Node Plant\",\"type\":\"hero\"}},\"publishedOn\":\"2025-11-13T12:30:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"maryland-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"The state of Maryland partners with Anthropic to better serve residents\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:44Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIxMSp\",\"_rev\":\"CIQMb8zr2hKNcFuuO2JkdX\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:03Z\",\"description\":\"Geometric scale balancing abstract shapes with intricate weighing mechanism and balanced forms\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-97cf99624aa60f59b75f9e08cdf0f00d33c34804-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/97cf99624aa60f59b75f9e08cdf0f00d33c34804-1000x1000.svg\",\"width\":1000},\"keywords\":\"scale, shapes, balance, geometric, measurement, comparison, weighing shapes, balanced forms, geometric comparison, shape measurement, balanced geometry\",\"name\":\"Object ScaleShapes\",\"type\":\"hero\"}},\"publishedOn\":\"2025-11-13T07:09:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"political-even-handedness\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"},{\"_key\":\"societal-impacts\",\"_type\":\"tag\",\"label\":\"Societal Impacts\",\"value\":\"societal-impacts\"}],\"summary\":null,\"title\":\"Measuring political bias in Claude\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-objects-growth\",\"_rev\":\"YCJsOBtfHCRsnR2sTmNfaV\",\"_system\":{\"base\":{\"id\":\"illustration-hero-objects-growth\",\"rev\":\"fiXPOAGczSPPY2Y6NiKfFe\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-17T12:47:22Z\",\"description\":\"Curved upward growth line\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-c0af2a56f56cf298ce5904f2901e9a36facd0dbe-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/c0af2a56f56cf298ce5904f2901e9a36facd0dbe-1000x1000.svg\",\"width\":1000},\"name\":\"Object Growth\",\"type\":\"hero\"}},\"publishedOn\":\"2025-11-12T03:14:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-invests-50-billion-in-american-ai-infrastructure\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic invests $50 billion in American AI infrastructure\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:30Z\",\"_id\":\"Z7bXjXUrfbilTWp6Lm0RMk\",\"_rev\":\"znUZZ0fmIk1XIVDY2KGkIb\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:24Z\",\"description\":\"Globe with detailed world map and textured landmasses on a spherical surface\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-ffc0d7957a232518519f13c0d64896921ea215e2-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ffc0d7957a232518519f13c0d64896921ea215e2-1000x1000.svg\",\"width\":1000},\"keywords\":\"globe, world, earth, planet, global, worldwide, international, universal, global reach, world map, international scope, planetary, worldwide network, global connections\",\"name\":\"Object Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2025-11-07T20:49:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"new-offices-in-paris-and-munich-expand-european-presence\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"New offices in Paris and Munich expand Anthropic’s European presence\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T17:19:26Z\",\"_id\":\"DElaXo1A74rjItEmVZA4O7\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Hwkp\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:55:37Z\",\"description\":\"hand, chart, bar chart, graph, data, statistics, analytics, metrics, performance, growth, visualization, business intelligence, reporting, analysis, trends, measurement, dashboard, KPIs\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-e44a6b53398f189b9fd0d4f70516db614ac84db3-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/e44a6b53398f189b9fd0d4f70516db614ac84db3-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, chart, bar chart, graph, data, statistics, analytics, metrics, performance, growth, visualization, business intelligence, reporting, analysis, trends, measurement, dashboard, KPIs\",\"name\":\"Hand BarChart\",\"type\":\"hero\"}},\"publishedOn\":\"2025-11-05T07:48:51.082Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"economic-futures-uk-europe\"},\"subjects\":[{\"_key\":\"economic-research\",\"_type\":\"tag\",\"label\":\"Economics\",\"value\":\"economic-research\"}],\"summary\":null,\"title\":\"Launching the Anthropic Economic Futures Programme in the UK and Europe\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-11-04T15:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-and-iceland-announce-one-of-the-world-s-first-national-ai-education-pilots\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":null,\"title\":\"Anthropic and Iceland announce one of the world’s first national AI education pilots\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:32:35Z\",\"_id\":\"DElaXo1A74rjItEmVagig7\",\"_rev\":\"L1sWYwVuS7u8WeTHm64qP4\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:37Z\",\"description\":\"Hand with connecting network nodes and lines on abstract background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, line, node, connection, network, collaboration, teamwork, working together, cooperative work, team connection, collaborative effort, partnership, joint work, team communication, collaborative network\",\"name\":\"Hand NodeLine\",\"type\":\"hero\"}},\"publishedOn\":\"2025-11-04T13:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"cognizant-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Cognizant will make Claude available to 350,000 employees, accelerating enterprise AI adoption and internal transformation\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-hands-globe\",\"_rev\":\"Z7bXjXUrfbilTWp6Ln6egF\",\"_system\":{\"base\":{\"id\":\"illustration-hero-hands-globe\",\"rev\":\"ywswJJUxLstmcebkfFkPnG\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-17T21:41:13Z\",\"description\":\" \",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-b68cbb43d7c8f56f0b14cc867e8d4d74445f78b0-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b68cbb43d7c8f56f0b14cc867e8d4d74445f78b0-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, globe, planet, world, earth, sphere, global, grid, global reach, worldwide, international, environmental, universal, global business, international services, worldwide reach, internet, web, world wide web, online, connectivity, global network, web services, international connectivity, global internet\",\"name\":\"Hand Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2025-10-29T14:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"opening-our-tokyo-office\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic officially opens Tokyo office, signs Memorandum of Cooperation with the Japan AI Safety Institute\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:36:49Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIxDT5\",\"_rev\":\"MSyv171NSvWZvUt9ouLB5i\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:03:26Z\",\"description\":\"Geometric staircase steps ascending vertically with incremental progression\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-ddad92700787ec1bf1d80359c0c5e6ca305682b0-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ddad92700787ec1bf1d80359c0c5e6ca305682b0-1000x1000.svg\",\"width\":1000},\"keywords\":\"stairs, steps, staircase, ascending, climbing, progress, advancement, step by step, upward movement, progression, gradual improvement, levels, incremental progress, growth, momentum, building momentum, steady growth, upward trajectory, continuous improvement, scaling up\",\"name\":\"Object Stairs\",\"type\":\"hero\"}},\"publishedOn\":\"2025-10-27T19:24:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"advancing-claude-for-financial-services\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Claude for Financial Services now supports a native Excel plug-in, new connectors to real-time market, and pre-built skills for modeling, comp analysis, and earnings reports.\",\"title\":\"Advancing Claude for Financial Services\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:36Z\",\"_id\":\"Z7bXjXUrfbilTWp6LlzB1F\",\"_rev\":\"znUZZ0fmIk1XIVDY2KIj8V\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:04:33Z\",\"description\":\"Stylized globe with programming code elements and technical design details\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-b5c98d26c46edc43193e7f7e28a00633a538bb9c-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b5c98d26c46edc43193e7f7e28a00633a538bb9c-1000x1000.svg\",\"width\":1000},\"keywords\":\"code, globe, world, global, programming, worldwide development, international coding, global software, web development, worldwide programming, international development, coding worldwide\",\"name\":\"Object CodeGlobe\",\"type\":\"hero\"}},\"publishedOn\":\"2025-10-23T22:17:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"seoul-becomes-third-anthropic-office-in-asia-pacific\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Seoul becomes Anthropic’s third office in Asia-Pacific as we continue our international growth\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"fig\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:36:49Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIxDT5\",\"_rev\":\"MSyv171NSvWZvUt9ouLB5i\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:03:26Z\",\"description\":\"Geometric staircase steps ascending vertically with incremental progression\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-ddad92700787ec1bf1d80359c0c5e6ca305682b0-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ddad92700787ec1bf1d80359c0c5e6ca305682b0-1000x1000.svg\",\"width\":1000},\"keywords\":\"stairs, steps, staircase, ascending, climbing, progress, advancement, step by step, upward movement, progression, gradual improvement, levels, incremental progress, growth, momentum, building momentum, steady growth, upward trajectory, continuous improvement, scaling up\",\"name\":\"Object Stairs\",\"type\":\"hero\"}},\"publishedOn\":\"2025-10-23T18:46:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"expanding-our-use-of-google-cloud-tpus-and-services\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Expanding our use of Google Cloud TPUs and Services\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-10-21T14:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"statement-dario-amodei-american-ai-leadership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"A statement from Anthropic CEO, Dario Amodei, on Anthropic’s commitment to advancing America's leadership in building powerful and beneficial AI.\",\"title\":\"A statement from Dario Amodei on Anthropic's commitment to American AI leadership\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:54Z\",\"_id\":\"DElaXo1A74rjItEmVahxtX\",\"_rev\":\"znUZZ0fmIk1XIVDY2KBYf1\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:41Z\",\"description\":\"Hand with branching tree-like network structure extending from fingertips in organic, hierarchical pattern\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-74409af25137110ac04cc39e4d5ea0a2fbcea421-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/74409af25137110ac04cc39e4d5ea0a2fbcea421-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, tree, node, hierarchy, structure, decision tree, network hierarchy, branching network, hierarchical structure, organizational tree, branching connections, growth, expansion, development, scaling, organic growth, business growth, structural growth\",\"name\":\"Hand NodeTree\",\"type\":\"hero\"}},\"publishedOn\":\"2025-10-20T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-for-life-sciences\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":\"Introducing Claude for Life Sciences, a series of improvements to make Claude a better partner for researchers, clinical coordinators, and others who work in life sciences.\",\"title\":\"Claude for Life Sciences\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:36:37Z\",\"_id\":\"Z7bXjXUrfbilTWp6Lm02bk\",\"_rev\":\"MSyv171NSvWZvUt9ouLOYI\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:03:40Z\",\"description\":\"Desk lamp illuminating documents and paper on work surface with writing materials\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-77dd9077412abc790bf2bc6fa3383b37724d6305-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/77dd9077412abc790bf2bc6fa3383b37724d6305-1000x1000.svg\",\"width\":1000},\"keywords\":\"lamp, paper, document, writing, work, studying, paperwork, documentation, writing work, desk work, office work, document preparation, written materials, reveal, revealing, uncovering, discovery, illumination, bringing to light, exposing, showing, unveiling\",\"name\":\"Object LampPaper\",\"type\":\"hero\"}},\"publishedOn\":\"2025-10-16T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"skills\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Introducing Agent Skills\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-10-14T22:45:34Z\",\"_id\":\"c6fb26ef-1cb6-4d82-9abe-e8d2ca4938b7\",\"_rev\":\"gGgNEK99fop1JfPvFUiqP3\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-10-15T00:02:12Z\",\"description\":\"Hand with lightning bolt and head outline in stylized profile design\",\"image\":{\"_type\":\"image\",\"_upload\":{\"createdAt\":\"2025-10-14T22:46:27.737Z\",\"file\":{\"name\":\"Hand-HeadBolt.svg\",\"type\":\"image/svg+xml\"},\"previewImage\":\"$1a\",\"progress\":100,\"updatedAt\":\"2025-10-14T22:46:30.292Z\"},\"asset\":{\"_ref\":\"image-6457c34fbcb012acf0f27f15a6006f700d0f50de-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6457c34fbcb012acf0f27f15a6006f700d0f50de-1000x1000.svg\",\"width\":1000},\"keywords\":\"abstract, head, hand, bolt, lightning, lightning bolt, silhouette, geometric, molecular, minimalist, science, technology, human, interaction, profile, gesture, network\",\"name\":\"Hand HeadBolt\",\"type\":\"hero\"}},\"publishedOn\":\"2025-10-15T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-haiku-4-5\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":\"Claude Haiku 4.5 matches state-of-the-art coding capabilities from months ago while delivering unprecedented speed and cost-efficiency for complex tasks.\",\"title\":\"Introducing Claude Haiku 4.5\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:23Z\",\"_id\":\"Z7bXjXUrfbilTWp6Llz4FF\",\"_rev\":\"CIQMb8zr2hKNcFuuO2JBUf\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:20Z\",\"description\":\"Hand with geometric shapes constructing a complex abstract form on white background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6905c83d0735e1bc430025fdd1748d1406079036-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6905c83d0735e1bc430025fdd1748d1406079036-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, shape, build, construction, creating, forming, shaping, molding, crafting, building, assembly, development, formation, creative construction, hands-on building, collaboration, teamwork, collaborative building, artifacts, interactive creation, AI-assisted building, collaborative development, working together\",\"name\":\"Hand ShapeBuild\",\"type\":\"hero\"}},\"publishedOn\":\"2025-10-14T12:02:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"salesforce-anthropic-expanded-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Anthropic and Salesforce expand partnership to bring Claude to regulated industries\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T15:25:22Z\",\"_id\":\"Xjt2eTPpfxUE2CfkIxE28E\",\"_rev\":\"znUZZ0fmIk1XIVDY2KEw1j\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:53Z\",\"description\":\"Interconnected globe with network nodes and global connection lines\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-5f455d24ea80569b34eb4347f06152d8a5508722-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5f455d24ea80569b34eb4347f06152d8a5508722-1000x1000.svg\",\"width\":1000},\"keywords\":\"globe, world, global, international, worldwide, planet, earth, sphere, universal, global reach\",\"name\":\"Node Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2025-10-07T23:45:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"expanding-global-operations-to-india\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’re expanding our global operations to India, with plans to open an office in Bengaluru in early 2026.\",\"title\":\"Expanding our global operations to India with our second Asia Pacific office\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2025-10-07T19:16:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"rahul-patil-joins-anthropic\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Rahul Patil joins Anthropic as Chief Technology Officer\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:32:35Z\",\"_id\":\"DElaXo1A74rjItEmVagig7\",\"_rev\":\"L1sWYwVuS7u8WeTHm64qP4\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:37Z\",\"description\":\"Hand with connecting network nodes and lines on abstract background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, line, node, connection, network, collaboration, teamwork, working together, cooperative work, team connection, collaborative effort, partnership, joint work, team communication, collaborative network\",\"name\":\"Hand NodeLine\",\"type\":\"hero\"}},\"publishedOn\":\"2025-10-06T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"deloitte-anthropic-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Deloitte will make Claude available to 470,000 people across its global network\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":2000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6f6f440f9f554ec19c6a90aa70753278adfe9a40-2000x2000.jpg\",\"width\":2000},\"directories\":[{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"},{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2025-10-03T18:31:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"building-ai-cyber-defenders\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"},{\"_key\":\"frontier-red-team\",\"_type\":\"tag\",\"label\":\"Frontier Red Team\",\"value\":\"frontier-red-team\"}],\"summary\":\"As research and experience demonstrated the utility of frontier AI as a tool for cyber attackers, we invested in improving Claude’s ability to help defenders detect, analyze, and remediate vulnerabilities in code and deployed systems.\",\"title\":\"Building AI for cyber defenders\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T20:06:33Z\",\"_id\":\"DElaXo1A74rjItEmVb2CPT\",\"_rev\":\"L1sWYwVuS7u8WeTHm67aDV\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:27Z\",\"description\":\"Hand with pointing arrow on abstract geometric background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-a62b6eb169818f14c35b7a192af269e283f8fa93-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/a62b6eb169818f14c35b7a192af269e283f8fa93-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, arrow, shape, direction, pointing, guidance, navigation, flow, movement, directional, routing, pathways, directional flow, guiding, steering, async tasks, asynchronous, background processes, queued tasks, task flow, process flow, workflow\",\"name\":\"Hand ShapeArrow\",\"type\":\"hero\"}},\"publishedOn\":\"2025-09-29T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"enabling-claude-code-to-work-more-autonomously\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Enabling Claude Code to work more autonomously\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-09-28T20:40:59Z\",\"_id\":\"5fdd726b-c5b3-4fe2-8896-b54cdac19231\",\"_rev\":\"CR2zpq1HU07DckIEery3q4\",\"_system\":{\"base\":{\"id\":\"5fdd726b-c5b3-4fe2-8896-b54cdac19231\",\"rev\":\"Tv1R9rOyTnCQqgud4KGHd6\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-09-29T02:09:33Z\",\"description\":\"Abstract composition with flowing head silhouette and stylized hand gesture, holding geometric cube structure\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-a683fdcfe3e2c7c6532342a0fa4ff789c3fd4852-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/a683fdcfe3e2c7c6532342a0fa4ff789c3fd4852-1000x1000.svg\",\"width\":1000},\"keywords\":\"abstract, head, hand, cube, silhouette, geometric, molecular, minimalist, science, technology, human, interaction, profile, gesture, network\",\"name\":\"Hand HeadCube\",\"type\":\"hero\"}},\"publishedOn\":\"2025-09-29T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-sonnet-4-5\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Claude Sonnet 4.5 sets new benchmark records in coding, reasoning, and computer use while being Anthropic's most aligned model, accompanied by the release of the Claude Agent SDK for building capable agents\",\"title\":\"Introducing Claude Sonnet 4.5\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T15:25:22Z\",\"_id\":\"Xjt2eTPpfxUE2CfkIxE28E\",\"_rev\":\"znUZZ0fmIk1XIVDY2KEw1j\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:53Z\",\"description\":\"Interconnected globe with network nodes and global connection lines\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-5f455d24ea80569b34eb4347f06152d8a5508722-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5f455d24ea80569b34eb4347f06152d8a5508722-1000x1000.svg\",\"width\":1000},\"keywords\":\"globe, world, global, international, worldwide, planet, earth, sphere, universal, global reach\",\"name\":\"Node Globe\",\"type\":\"hero\"}},\"publishedOn\":\"2025-09-26T15:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-expands-global-leadership-in-enterprise-ai-naming-chris-ciauri-as-managing-director-of\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Chris Ciauri joins Anthropic as Managing Director of International, adding to our global leadership team as we expand our worldwide presence.\",\"title\":\"Anthropic expands global leadership in enterprise AI, naming Chris Ciauri as Managing Director of International\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"An abstract hand pulling down a screen with coding brackets on it\",\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/4e854252f651ac613beeb3a958ea3ee498a17af8-1680x1260.png\",\"width\":1680},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2025-09-15T21:26:13.121Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-in-xcode\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Claude is now generally available in Xcode\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"},{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:32:35Z\",\"_id\":\"DElaXo1A74rjItEmVagig7\",\"_rev\":\"L1sWYwVuS7u8WeTHm64qP4\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:37Z\",\"description\":\"Hand with connecting network nodes and lines on abstract background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1576ae23eaf481f33bd36ab468171cc69d12361a-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, line, node, connection, network, collaboration, teamwork, working together, cooperative work, team connection, collaborative effort, partnership, joint work, team communication, collaborative network\",\"name\":\"Hand NodeLine\",\"type\":\"hero\"}},\"publishedOn\":\"2025-09-15T20:33:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-economic-index-september-2025-report\"},\"subjects\":[{\"_key\":\"economic-research\",\"_type\":\"tag\",\"label\":\"Economics\",\"value\":\"economic-research\"}],\"summary\":\" Claude usage has shifted toward educational and scientific tasks with users delegating complete work rather than collaborating. AI adoption concentrates in wealthy regions, with first-time analysis of enterprise API patterns.\",\"title\":\"Anthropic Economic Index report: Uneven geographic and enterprise AI adoption\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:54Z\",\"_id\":\"DElaXo1A74rjItEmVahxtX\",\"_rev\":\"znUZZ0fmIk1XIVDY2KBYf1\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:41Z\",\"description\":\"Hand with branching tree-like network structure extending from fingertips in organic, hierarchical pattern\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-74409af25137110ac04cc39e4d5ea0a2fbcea421-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/74409af25137110ac04cc39e4d5ea0a2fbcea421-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, tree, node, hierarchy, structure, decision tree, network hierarchy, branching network, hierarchical structure, organizational tree, branching connections, growth, expansion, development, scaling, organic growth, business growth, structural growth\",\"name\":\"Hand NodeTree\",\"type\":\"hero\"}},\"publishedOn\":\"2025-09-12T18:37:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"strengthening-our-safeguards-through-collaboration-with-us-caisi-and-uk-aisi\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Over the past year, we've collaborated with the US Center for AI Standards and Innovation (CAISI) and UK AI Security Institute (AISI), government bodies established to measure and improve the security of AI systems. \",\"title\":\"Strengthening our safeguards through collaboration with US CAISI and UK AISI \"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/34aafcc7a4ae1374ed65106863aa0b47dcbf1618-1900x1000.png\",\"width\":1900},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-09-08T11:01:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-is-endorsing-sb-53\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Anthropic is endorsing SB 53, the California bill that governs powerful AI systems built by frontier AI developers like Anthropic.\",\"title\":\"Anthropic is endorsing SB 53\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-nodes-multi\",\"_rev\":\"CIQMb8zr2hKNcFuuO2JP2M\",\"_system\":{\"base\":{\"id\":\"illustration-hero-nodes-multi\",\"rev\":\"ywswJJUxLstmcebkfFm3ms\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:01:00Z\",\"description\":\"Geometric modular network of interconnected abstract shapes and structural elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-653e7474811cf768b6b0f628e253f98c60e2747e-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/653e7474811cf768b6b0f628e253f98c60e2747e-1000x1000.svg\",\"width\":1000},\"keywords\":\"shapes, geometric, forms, structure, building blocks, elements, components, design elements, geometric patterns, structural elements, modular, composition, connection\",\"name\":\"Node Multi\",\"type\":\"hero\"}},\"publishedOn\":\"2025-09-04T21:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"updating-restrictions-of-sales-to-unsupported-regions\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"To account for this reality and better align with our commitment to ensuring that transformative AI capabilities advance democratic interests, we are strengthening our regional restrictions.\",\"title\":\"Updating restrictions of sales to unsupported regions \"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-09-04T18:35:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-signs-pledge-to-americas-youth-investing-in-ai-education\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic Signs White House Pledge to America's Youth: Investing in AI Education\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-objects-growth\",\"_rev\":\"YCJsOBtfHCRsnR2sTmNfaV\",\"_system\":{\"base\":{\"id\":\"illustration-hero-objects-growth\",\"rev\":\"fiXPOAGczSPPY2Y6NiKfFe\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-17T12:47:22Z\",\"description\":\"Curved upward growth line\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-c0af2a56f56cf298ce5904f2901e9a36facd0dbe-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/c0af2a56f56cf298ce5904f2901e9a36facd0dbe-1000x1000.svg\",\"width\":1000},\"name\":\"Object Growth\",\"type\":\"hero\"}},\"publishedOn\":\"2025-09-02T16:05:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-raises-series-f-at-usd183b-post-money-valuation\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Anthropic raised $13 billion in a Series F round at a $183 billion valuation to expand enterprise offerings, safety research, and international growth as revenue grew from $1 billion to over $5 billion in eight months.\",\"title\":\"Anthropic raises $13B Series F at $183B post-money valuation\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-nodes-multi\",\"_rev\":\"CIQMb8zr2hKNcFuuO2JP2M\",\"_system\":{\"base\":{\"id\":\"illustration-hero-nodes-multi\",\"rev\":\"ywswJJUxLstmcebkfFm3ms\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:01:00Z\",\"description\":\"Geometric modular network of interconnected abstract shapes and structural elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-653e7474811cf768b6b0f628e253f98c60e2747e-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/653e7474811cf768b6b0f628e253f98c60e2747e-1000x1000.svg\",\"width\":1000},\"keywords\":\"shapes, geometric, forms, structure, building blocks, elements, components, design elements, geometric patterns, structural elements, modular, composition, connection\",\"name\":\"Node Multi\",\"type\":\"hero\"}},\"publishedOn\":\"2025-08-28T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"updates-to-our-consumer-terms\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Updates to Consumer Terms and Privacy Policy \"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1261,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/faffa5377164658980f804e5bee648fe07370268-2401x1261.png\",\"width\":2401},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2025-08-27T20:01:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"detecting-countering-misuse-aug-2025\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":\"We’ve developed safeguards to prevent the misuse of our models, but malicious actors are actively attempting to find ways around them. Today, we’re releasing a report that details how.\",\"title\":\"Detecting and countering misuse of AI: August 2025\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/220ba398ed2cdbc37f29ed14e0b153f55ce023a4-1900x1000.png\",\"width\":1900},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-08-27T13:05:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"introducing-the-anthropic-national-security-and-public-sector-advisory-council\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We are announcing the formation of the Anthropic National Security and Public Sector Advisory Council, a group of leading bipartisan national security and public policy practitioners who will help Anthropic support the U.S. government and closely allied democracies in building and maintaining enduring technological advantages in an era of strategic competition. \\n\",\"title\":\"Introducing the Anthropic National Security and Public Sector Advisory Council\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T18:57:10Z\",\"_id\":\"Z7bXjXUrfbilTWp6LleIIk\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IluI\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:59:01Z\",\"description\":\"Hand holding an open book with network nodes and connection lines emanating from its pages\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-1c3d1af62032009538b8bf5864139ca124b06741-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1c3d1af62032009538b8bf5864139ca124b06741-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, book, node, network, knowledge, learning, documentation, AI, intelligence, information network, educational content, smart learning, knowledge sharing, intelligent documentation, connected learning\",\"name\":\"Hand NodeBook\",\"type\":\"hero\"}},\"publishedOn\":\"2025-08-21T20:49:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-higher-education-initiatives\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic launches higher education advisory board and AI Fluency courses\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/94afaf41cf9c82fa9ac91653b37f44a43632681e-2400x1260.png\",\"width\":2400},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"},{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:54Z\",\"_id\":\"DElaXo1A74rjItEmVahxtX\",\"_rev\":\"znUZZ0fmIk1XIVDY2KBYf1\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:41Z\",\"description\":\"Hand with branching tree-like network structure extending from fingertips in organic, hierarchical pattern\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-74409af25137110ac04cc39e4d5ea0a2fbcea421-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/74409af25137110ac04cc39e4d5ea0a2fbcea421-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, tree, node, hierarchy, structure, decision tree, network hierarchy, branching network, hierarchical structure, organizational tree, branching connections, growth, expansion, development, scaling, organic growth, business growth, structural growth\",\"name\":\"Hand NodeTree\",\"type\":\"hero\"}},\"publishedOn\":\"2025-08-21T07:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"developing-nuclear-safeguards-for-ai-through-public-private-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"frontier-red-team\",\"_type\":\"tag\",\"label\":\"Frontier Red Team\",\"value\":\"frontier-red-team\"}],\"summary\":\"Together with the NNSA and DOE national laboratories, we have co-developed a classifier that distinguishes between concerning and benign nuclear-related conversations with 96% accuracy in preliminary testing. \",\"title\":\"Developing nuclear safeguards for AI through public-private partnership \"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A hand and a graph, signaling growth\",\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/27e7273ed7d58f990040d38db7fa1da211b5c70e-1680x1260.png\",\"width\":1680},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2025-08-20T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-code-on-team-and-enterprise\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Claude Code and new admin controls for business plans\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"coral\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:35Z\",\"_id\":\"DElaXo1A74rjItEmVahiln\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IdYy\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:21Z\",\"description\":\"Ornate quill pen resting on a detailed hand, positioned against a textured background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, quill, writing, pen, authoring, documentation, content creation, writing tools, literary work, composition, manuscript, creative writing, text creation\",\"name\":\"Hand Quill\",\"type\":\"hero\"}},\"publishedOn\":\"2025-08-15T22:52:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"usage-policy-update\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":\"Updates to our Usage Policy that reflect the growing capabilities and evolving usage of our products\",\"title\":\"Usage policy update\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T20:06:25Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKJ3yC3\",\"_rev\":\"766umayZSiZvQu52Fnum7j\",\"_system\":{\"base\":{\"id\":\"uWx6ePFJ4MmdfRYgKJ3yC3\",\"rev\":\"CIQMb8zr2hKNcFuuO2JIEb\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-08-12T15:31:06Z\",\"description\":\"Hand-shaped house with financial symbols and economic details\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-cd9cf56a7f049285b7c1c8786c0a600cf3d7f317-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/cd9cf56a7f049285b7c1c8786c0a600cf3d7f317-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, money, coin, currency, finance, payment, financial, cash, economic, monetary, funding, budget, cost, pricing, financial transactions, money management, economics\",\"name\":\"Hand House\",\"type\":\"hero\"}},\"publishedOn\":\"2025-08-12T15:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"building-safeguards-for-claude\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Building safeguards for Claude\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-08-12T13:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"offering-expanded-claude-access-across-all-three-branches-of-government\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Offering expanded Claude access across all three branches of the U.S. government\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"default\",\"illustration\":null},\"publishedOn\":\"2025-08-06T23:30:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"head-of-japan-hiring-plans\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic appoints Hidetoshi Tojo as Head of Japan and announces hiring plans \"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:34:37Z\",\"_id\":\"DElaXo1A74rjItEmVaiMzr\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IthD\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:59:47Z\",\"description\":\"Geometric profile of hand and head with overlapping abstract shapes and silhouettes\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-a97733b3607b54a30778eb89de08afd9e02b9fb3-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/a97733b3607b54a30778eb89de08afd9e02b9fb3-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, head, profile, shapes, geometric, person, Claude artifacts, artifacts, code generation, interactive content, creative tools, AI-generated content, dynamic creation, Claude features, AI creativity, generated artifacts, interactive AI, Claude capabilities, AI-powered creation\",\"name\":\"Hand HeadShapes\",\"type\":\"hero\"}},\"publishedOn\":\"2025-08-05T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-opus-4-1\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"Our most powerful model for handling complex agent and coding tasks\",\"title\":\"Claude Opus 4.1\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-08-05T10:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"federal-government-departments-and-agencies-can-now-purchase-claude-through-the-gsa-schedule\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Federal government departments and agencies can now purchase Claude through the GSA schedule\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:34:06Z\",\"_id\":\"L5WZ73ZndVNkcSTU1XnWlE\",\"_rev\":\"P8Xlrmt1DpMy3IDGqFcNr7\",\"_system\":{\"base\":{\"id\":\"L5WZ73ZndVNkcSTU1XnWlE\",\"rev\":\"znUZZ0fmIk1XIVDY2KC1pH\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-09-05T19:19:50Z\",\"description\":\"Hand with network visualization nodes and slides in presentation context\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6507d83d1197bb8630131d363fb8bea838d79ca7-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6507d83d1197bb8630131d363fb8bea838d79ca7-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, slide, presentation, node, network, presentation tools, network visualization, connected slides, presentation materials, visual communication, slide deck\",\"name\":\"Hand NodeSlide\",\"type\":\"hero\"}},\"publishedOn\":\"2025-08-04T19:18:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"our-framework-for-developing-safe-and-trustworthy-agents\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Our framework for developing safe and trustworthy agents\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"hands shaping an image\",\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b1aeb70d1e0bd9933d6590e1bc9affd5fa3dd848-1000x1000.svg\",\"width\":1000},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T17:22:56Z\",\"_id\":\"fYxjGGEIxl5FrJqEfAZWoz\",\"_rev\":\"L1sWYwVuS7u8WeTHm64FmP\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:13Z\",\"description\":\"Hand with padlock and key on detailed security graphic\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-d3dd09ad16c68461dc3fb01df5e84cf7ccafda6c-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/d3dd09ad16c68461dc3fb01df5e84cf7ccafda6c-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, lock, security, protection, key, safety, padlock, privacy, access control, confidentiality, security features, privacy protection, safety measures, confidential information\",\"name\":\"Hand Lock\",\"type\":\"hero\"}},\"publishedOn\":\"2025-07-30T19:05:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-signs-cms-health-tech-ecosystem-pledge-to-advance-healthcare-interoperability\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Anthropic Signs CMS Health Tech Ecosystem Pledge to Advance Healthcare Interoperability\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/47176eb9b20f16959117dfa766266fab596c6eac-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-07-23T17:33:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"thoughts-on-america-s-ai-action-plan\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":\"Anthropic's response to the White House AI Action Plan supports infrastructure and safety measures while calling for stronger export controls and transparency requirements to maintain American AI leadership.\",\"title\":\"Thoughts on America’s AI Action Plan\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/93b98d31ef937d004a63853ef2f97ed98a253c95-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-hands-flower\",\"_rev\":\"L1sWYwVuS7u8WeTHm648yu\",\"_system\":{\"base\":{\"id\":\"illustration-hero-hands-flower\",\"rev\":\"0d6MsZt9oKIBxAUs2fRBHk\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:06Z\",\"description\":\"Hand with organic flower petals emerging from palm, rooted in botanical growth pattern\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-c1ef4c0b6882dfe985555b52999d370ea88a3c50-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/c1ef4c0b6882dfe985555b52999d370ea88a3c50-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, graph, node, chart, data visualization, network diagram, analytics, data connections, network analysis, connected data, graph theory, data relationships, network mapping\",\"name\":\"Hand NodeGraph\",\"type\":\"hero\"}},\"publishedOn\":\"2025-07-23T15:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-partners-with-the-university-of-chicago-s-becker-friedman-institute-on-ai-economic\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic partners with the University of Chicago’s Becker Friedman Institute on AI economic research\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Lightning Bolt\",\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/214a0bd0e0a4cb99e473242e7ed1f914dc5cbfa4-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T17:09:13Z\",\"_id\":\"Z7bXjXUrfbilTWp6Lkjv8k\",\"_rev\":\"gxZij0YGA7QefHHWLUizXB\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-21T14:08:56Z\",\"description\":\"Lightning bolt with angular geometric design and intersecting paths\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-c4a48972044d45df475f1dd84df3b74d221b6580-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/c4a48972044d45df475f1dd84df3b74d221b6580-1000x1000.svg\",\"width\":1000},\"keywords\":\"bolt, lightning, energy, power, electricity, speed, quick, fast, instant, shock, spark, electrical, energetic, powerful, dynamic, charged, electric\",\"name\":\"Node Bolt\",\"type\":\"hero\"}},\"publishedOn\":\"2025-07-21T19:34:25.630Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"build-ai-in-america\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Build AI in America\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-07-21T09:06:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"eu-code-practice\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Anthropic to sign the EU Code of Practice\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-07-15T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"paul-smith-to-join-anthropic\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Paul Smith to join Anthropic as Chief Commercial Officer\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Illustration of a step chart with growth arrows\",\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/8b7ac99883746ee0a090750328686dbe67b57348-1680x1260.png\",\"width\":1680},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:36:49Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIxDT5\",\"_rev\":\"MSyv171NSvWZvUt9ouLB5i\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:03:26Z\",\"description\":\"Geometric staircase steps ascending vertically with incremental progression\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-ddad92700787ec1bf1d80359c0c5e6ca305682b0-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ddad92700787ec1bf1d80359c0c5e6ca305682b0-1000x1000.svg\",\"width\":1000},\"keywords\":\"stairs, steps, staircase, ascending, climbing, progress, advancement, step by step, upward movement, progression, gradual improvement, levels, incremental progress, growth, momentum, building momentum, steady growth, upward trajectory, continuous improvement, scaling up\",\"name\":\"Object Stairs\",\"type\":\"hero\"}},\"publishedOn\":\"2025-07-15T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-for-financial-services\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":\"Helping finance professionals analyze markets, conduct research, and make investment decisions.\",\"title\":\"Claude for Financial Services\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A set of three trees, with each getting bigger \",\"height\":2521,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6214650e82ff766d6f82c190ae4446c50704e3c7-3361x2521.png\",\"width\":3361},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T17:09:04Z\",\"_id\":\"Z7bXjXUrfbilTWp6LkjoZF\",\"_rev\":\"Oe5qGRtmI2tA8S7mxF7kA7\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-22T20:28:22Z\",\"description\":\"Organic node plant with branching growth stages and interconnected developmental elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-2174acb37a84767550abfe2588eb5648f941a897-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/2174acb37a84767550abfe2588eb5648f941a897-1000x1000.svg\",\"width\":1000},\"keywords\":\"plant, growth, nature, organic, development, flourishing, natural growth, cultivation, nurturing, environmental, green, sustainability, life, growing, growth process, stages of growth, development, progression, evolving, maturing, gradual development\",\"name\":\"Node Plant\",\"type\":\"hero\"}},\"publishedOn\":\"2025-07-15T11:30:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"investing-in-energy-to-secure-america-s-ai-future\"},\"subjects\":[{\"_key\":\"alignment\",\"_type\":\"tag\",\"label\":\"Alignment\",\"value\":\"alignment\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Investing in energy to secure America's AI future \"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-07-14T15:35:53.261Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-and-the-department-of-defense-to-advance-responsible-ai-in-defense-operations\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic and the Department of Defense to advance responsible AI in defense operations\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/8ac34a806ecc9eec48cfb21ebcf78ba055bdb158-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T18:57:10Z\",\"_id\":\"Z7bXjXUrfbilTWp6LleIIk\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IluI\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:59:01Z\",\"description\":\"Hand holding an open book with network nodes and connection lines emanating from its pages\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-1c3d1af62032009538b8bf5864139ca124b06741-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1c3d1af62032009538b8bf5864139ca124b06741-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, book, node, network, knowledge, learning, documentation, AI, intelligence, information network, educational content, smart learning, knowledge sharing, intelligent documentation, connected learning\",\"name\":\"Hand NodeBook\",\"type\":\"hero\"}},\"publishedOn\":\"2025-07-09T15:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"advancing-claude-for-education\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":null,\"title\":\"Advancing Claude for Education\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A hand-drawn image of a hand with a set of nodes emerging above it, extending in several different directions\",\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/35c3cf6f17013234144a4065dfd8b7d876521be1-1680x1260.png\",\"width\":1680},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:54Z\",\"_id\":\"DElaXo1A74rjItEmVahxtX\",\"_rev\":\"znUZZ0fmIk1XIVDY2KBYf1\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:41Z\",\"description\":\"Hand with branching tree-like network structure extending from fingertips in organic, hierarchical pattern\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-74409af25137110ac04cc39e4d5ea0a2fbcea421-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/74409af25137110ac04cc39e4d5ea0a2fbcea421-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, tree, node, hierarchy, structure, decision tree, network hierarchy, branching network, hierarchical structure, organizational tree, branching connections, growth, expansion, development, scaling, organic growth, business growth, structural growth\",\"name\":\"Hand NodeTree\",\"type\":\"hero\"}},\"publishedOn\":\"2025-07-09T10:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"lawrence-livermore-national-laboratory-expands-claude-for-enterprise-to-empower-scientists-and\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Lawrence Livermore National Laboratory expands Claude for Enterprise use to empower scientists and researchers\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A building with a set of columns\",\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/47176eb9b20f16959117dfa766266fab596c6eac-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-07-07T17:30:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"the-need-for-transparency-in-frontier-ai\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"The need for transparency in Frontier AI\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A stock chart moving up and to the right\",\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/93b98d31ef937d004a63853ef2f97ed98a253c95-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-hands-flower\",\"_rev\":\"L1sWYwVuS7u8WeTHm648yu\",\"_system\":{\"base\":{\"id\":\"illustration-hero-hands-flower\",\"rev\":\"0d6MsZt9oKIBxAUs2fRBHk\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:06Z\",\"description\":\"Hand with organic flower petals emerging from palm, rooted in botanical growth pattern\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-c1ef4c0b6882dfe985555b52999d370ea88a3c50-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/c1ef4c0b6882dfe985555b52999d370ea88a3c50-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, graph, node, chart, data visualization, network diagram, analytics, data connections, network analysis, connected data, graph theory, data relationships, network mapping\",\"name\":\"Hand NodeGraph\",\"type\":\"hero\"}},\"publishedOn\":\"2025-06-27T13:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"introducing-the-anthropic-economic-futures-program\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Introducing the Anthropic Economic Futures Program\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1261,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/77411b5a7049200a7021270a6c44101d5b228ab9-1681x1261.png\",\"width\":1681},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"},{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:34Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIxKbf\",\"_rev\":\"MSyv171NSvWZvUt9ouJx8y\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:16Z\",\"description\":\"Speech bubble with detailed conversation graphic on textured background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-8d339ae8ecedecc1409db8f5bbb99c958db56946-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/8d339ae8ecedecc1409db8f5bbb99c958db56946-1000x1000.svg\",\"width\":1000},\"keywords\":\"chat, speech bubble, conversation, communication, dialogue, messaging, discussion, talk, speaking, conversation bubble, communication tool, dialogue box, messaging interface\",\"name\":\"Object Chat\",\"type\":\"hero\"}},\"publishedOn\":\"2025-06-27T06:51:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"how-people-use-claude-for-support-advice-and-companionship\"},\"subjects\":[{\"_key\":\"societal-impacts\",\"_type\":\"tag\",\"label\":\"Societal Impacts\",\"value\":\"societal-impacts\"}],\"summary\":null,\"title\":\"How people use Claude for support, advice, and companionship \"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A hand drawn illustration of a hand holding a white key vertically against a blue background.\",\"height\":1261,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/d7744b463b49211ec94a83831640101da883d4f2-1681x1261.png\",\"width\":1681},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:34:22Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIwWkN\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Ir5O\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:59:28Z\",\"description\":\"Large hand with detailed key against abstract background of geometric shapes\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-036c01a9e427ea0f4d1e6c7221e4f6dce2259bf7-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/036c01a9e427ea0f4d1e6c7221e4f6dce2259bf7-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, key, unlock, access, security, opening, solutions, access control, opening opportunities, unlocking features, key concepts, access management\",\"name\":\"Hand Key\",\"type\":\"hero\"}},\"publishedOn\":\"2025-06-11T18:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-in-amazon-bedrock-fedramp-high\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude in Amazon Bedrock: Approved for use in FedRAMP High and DoD IL4/5 workloads\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-06-07T02:28:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"national-security-expert-richard-fontaine-appointed-to-anthropic-s-long-term-benefit-trust\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"National security expert Richard Fontaine appointed to Anthropic’s long-term benefit trust \"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/47176eb9b20f16959117dfa766266fab596c6eac-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-06-06T03:05:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-gov-models-for-u-s-national-security-customers\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude Gov models for U.S. national security customers\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-05-28T15:59:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"reed-hastings\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Reed Hastings appointed to Anthropic’s board of directors\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A hand sheltering a neural network\",\"height\":1261,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/426acef2ccfa8bb61a7251a347de40761b73d1fb-1681x1261.png\",\"width\":1681},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:34:28Z\",\"_id\":\"Z7bXjXUrfbilTWp6LlyZCF\",\"_rev\":\"L1sWYwVuS7u8WeTHm66qkR\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:59:35Z\",\"description\":\"Hand with protective shield and network node in cybersecurity symbol design\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-b1ce510c468b2920d4f8f61c17a50906801f939a-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b1ce510c468b2920d4f8f61c17a50906801f939a-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, shield, node, protection, security, network security, protected network, cybersecurity, secure connections, data protection, network safety, security measures\",\"name\":\"Hand NodeShield\",\"type\":\"hero\"}},\"publishedOn\":\"2025-05-22T16:45:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"activating-asl3-protections\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Activating AI Safety Level 3 protections\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Illustration of Claude juggling several tasks in parallel\",\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b2bccec246c6786ad49b1e55fe297b84c3089252-1680x1260.jpg\",\"width\":1680},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:34:37Z\",\"_id\":\"DElaXo1A74rjItEmVaiMzr\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IthD\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:59:47Z\",\"description\":\"Geometric profile of hand and head with overlapping abstract shapes and silhouettes\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-a97733b3607b54a30778eb89de08afd9e02b9fb3-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/a97733b3607b54a30778eb89de08afd9e02b9fb3-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, head, profile, shapes, geometric, person, Claude artifacts, artifacts, code generation, interactive content, creative tools, AI-generated content, dynamic creation, Claude features, AI creativity, generated artifacts, interactive AI, Claude capabilities, AI-powered creation\",\"name\":\"Hand HeadShapes\",\"type\":\"hero\"}},\"publishedOn\":\"2025-05-22T16:30:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-4\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Introducing Claude 4\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A magnifying glass reviewing code\",\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/05ad8715b4cc9f08c7858e7fd2a3ef35c4d36b5d-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:36:21Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIx6Vn\",\"_rev\":\"L1sWYwVuS7u8WeTHm6B9mm\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:04:09Z\",\"description\":\"Large magnifying glass with code symbols on detailed technical background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-1c3e87fd90491089b2971dc34f9f75bb8a80f713-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1c3e87fd90491089b2971dc34f9f75bb8a80f713-1000x1000.svg\",\"width\":1000},\"keywords\":\"code, magnifier, magnifying glass, search, code search, debugging, code review, examining code, code analysis, investigation, code inspection, finding bugs, code examination\",\"name\":\"Object CodeMagnifier\",\"type\":\"hero\"}},\"publishedOn\":\"2025-05-14T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"testing-our-safety-defenses-with-a-new-bug-bounty-program\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Testing our safety defenses with a new bug bounty program\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Hands-BookOpen-Sky\",\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b235baff40443ce8858b54e8d5d73ab7b8e55a13-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T18:56:58Z\",\"_id\":\"Z7bXjXUrfbilTWp6LleCrF\",\"_rev\":\"znUZZ0fmIk1XIVDY2KBckj\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:47Z\",\"description\":\"Open book with detailed hand holding pages against textured background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-423062049d4676b41d52b16068cbb5e21603190e-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/423062049d4676b41d52b16068cbb5e21603190e-1000x1000.svg\",\"width\":1000},\"keywords\":\"book, pages, hand, reading, holding, open book, literature, knowledge, learning, education, study, information, wisdom, research, documentation, knowledge sharing, libraries\",\"name\":\"Hand Book\",\"type\":\"hero\"}},\"publishedOn\":\"2025-05-05T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"ai-for-science-program\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"beneficial-deployments\",\"_type\":\"tag\",\"label\":\"Beneficial Deployments\",\"value\":\"beneficial-deployments\"}],\"summary\":null,\"title\":\"Introducing Anthropic's AI for Science Program\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Column with burst\",\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/02a64107eca399bb4a0b7d9ef4265633ab8a7d9d-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-07-17T17:08:49Z\",\"_id\":\"Z7bXjXUrfbilTWp6LkjjUF\",\"_rev\":\"L1sWYwVuS7u8WeTHm68xbB\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:01:38Z\",\"description\":\"Classical architectural column with structural nodes and foundational design elements in geometric SVG format\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-811dcfbdaac4ea3628e0a2a5a547b0a175d63bcf-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/811dcfbdaac4ea3628e0a2a5a547b0a175d63bcf-1000x1000.svg\",\"width\":1000},\"keywords\":\"column, pillar, support, foundation, structure, stability, architectural, strong, sturdy, classical, strength, support system, foundational, structural integrity, institutions, education, academic, institutional support, educational foundation, scholarly, university, academia\",\"name\":\"Node Column\",\"type\":\"hero\"}},\"publishedOn\":\"2025-04-30T09:15:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"securing-america-s-compute-advantage-anthropic-s-position-on-the-diffusion-rule\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Securing America's compute advantage: Anthropic’s position on the diffusion rule\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A stock chart moving up and to the right\",\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/93b98d31ef937d004a63853ef2f97ed98a253c95-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"heather\",\"illustration\":{\"_createdAt\":\"2025-03-11T20:06:48Z\",\"_id\":\"illustration-hero-hands-flower\",\"_rev\":\"L1sWYwVuS7u8WeTHm648yu\",\"_system\":{\"base\":{\"id\":\"illustration-hero-hands-flower\",\"rev\":\"0d6MsZt9oKIBxAUs2fRBHk\"}},\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:56:06Z\",\"description\":\"Hand with organic flower petals emerging from palm, rooted in botanical growth pattern\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-c1ef4c0b6882dfe985555b52999d370ea88a3c50-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/c1ef4c0b6882dfe985555b52999d370ea88a3c50-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, graph, node, chart, data visualization, network diagram, analytics, data connections, network analysis, connected data, graph theory, data relationships, network mapping\",\"name\":\"Hand NodeGraph\",\"type\":\"hero\"}},\"publishedOn\":\"2025-04-28T12:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"introducing-the-anthropic-economic-advisory-council\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"societal-impacts\",\"_type\":\"tag\",\"label\":\"Societal Impacts\",\"value\":\"societal-impacts\"}],\"summary\":null,\"title\":\"Introducing the Anthropic Economic Advisory Council \"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Profile with Claude sunburst \",\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/fbc2b3b568205a8ac3f47134dd21846ac72a7392-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:36:21Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIx6Vn\",\"_rev\":\"L1sWYwVuS7u8WeTHm6B9mm\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:04:09Z\",\"description\":\"Large magnifying glass with code symbols on detailed technical background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-1c3e87fd90491089b2971dc34f9f75bb8a80f713-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1c3e87fd90491089b2971dc34f9f75bb8a80f713-1000x1000.svg\",\"width\":1000},\"keywords\":\"code, magnifier, magnifying glass, search, code search, debugging, code review, examining code, code analysis, investigation, code inspection, finding bugs, code examination\",\"name\":\"Object CodeMagnifier\",\"type\":\"hero\"}},\"publishedOn\":\"2025-04-23T15:05:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"detecting-and-countering-malicious-uses-of-claude-march-2025\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":\"This report outlines several case studies on how actors have misused our models, as well as the steps we have taken to detect and counter such misuse. \",\"title\":\"Detecting and countering malicious uses of Claude: March 2025\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Illustration of a piece of paper and magnifying glass.\",\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/69d30213eb0120f3c7a0a668d2b314bfe3714f5e-1680x1260.png\",\"width\":1680},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:36:49Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIxDT5\",\"_rev\":\"MSyv171NSvWZvUt9ouLB5i\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:03:26Z\",\"description\":\"Geometric staircase steps ascending vertically with incremental progression\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-ddad92700787ec1bf1d80359c0c5e6ca305682b0-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ddad92700787ec1bf1d80359c0c5e6ca305682b0-1000x1000.svg\",\"width\":1000},\"keywords\":\"stairs, steps, staircase, ascending, climbing, progress, advancement, step by step, upward movement, progression, gradual improvement, levels, incremental progress, growth, momentum, building momentum, steady growth, upward trajectory, continuous improvement, scaling up\",\"name\":\"Object Stairs\",\"type\":\"hero\"}},\"publishedOn\":\"2025-04-21T18:46:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"our-approach-to-understanding-and-addressing-ai-harms\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Our approach to understanding and addressing AI harms\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A lamp shining on a document\",\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/16f763380c8565e697df3ea3f0f23d8580bb4d25-1680x1260.svg\",\"width\":1680},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"},{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"}],\"illustration\":{\"backgroundColor\":\"sky\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:36:37Z\",\"_id\":\"Z7bXjXUrfbilTWp6Lm02bk\",\"_rev\":\"MSyv171NSvWZvUt9ouLOYI\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:03:40Z\",\"description\":\"Desk lamp illuminating documents and paper on work surface with writing materials\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-77dd9077412abc790bf2bc6fa3383b37724d6305-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/77dd9077412abc790bf2bc6fa3383b37724d6305-1000x1000.svg\",\"width\":1000},\"keywords\":\"lamp, paper, document, writing, work, studying, paperwork, documentation, writing work, desk work, office work, document preparation, written materials, reveal, revealing, uncovering, discovery, illumination, bringing to light, exposing, showing, unveiling\",\"name\":\"Object LampPaper\",\"type\":\"hero\"}},\"publishedOn\":\"2025-04-08T15:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-education-report-how-university-students-use-claude\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"societal-impacts\",\"_type\":\"tag\",\"label\":\"Societal Impacts\",\"value\":\"societal-impacts\"}],\"summary\":null,\"title\":\"Anthropic Education Report: How university students use Claude\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-04-08T10:42:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"head-of-EMEA-new-roles\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic appoints Guillaume Princen as Head of EMEA and announces 100+ new roles across the region\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-04-03T15:26:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"Introducing-code-with-claude\"},\"subjects\":[{\"_key\":\"Event\",\"_type\":\"tag\",\"label\":\"Event\",\"value\":\"Event\"}],\"summary\":null,\"title\":\"Introducing Anthropic's first developer conference: Code with Claude\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/f5d0990ee33385000ff56ed82f3c5efb4e2d33da-2400x1260.png\",\"width\":2400},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T17:08:49Z\",\"_id\":\"Z7bXjXUrfbilTWp6LkjjUF\",\"_rev\":\"L1sWYwVuS7u8WeTHm68xbB\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:01:38Z\",\"description\":\"Classical architectural column with structural nodes and foundational design elements in geometric SVG format\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-811dcfbdaac4ea3628e0a2a5a547b0a175d63bcf-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/811dcfbdaac4ea3628e0a2a5a547b0a175d63bcf-1000x1000.svg\",\"width\":1000},\"keywords\":\"column, pillar, support, foundation, structure, stability, architectural, strong, sturdy, classical, strength, support system, foundational, structural integrity, institutions, education, academic, institutional support, educational foundation, scholarly, university, academia\",\"name\":\"Node Column\",\"type\":\"hero\"}},\"publishedOn\":\"2025-04-02T13:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"introducing-claude-for-education\"},\"subjects\":[{\"_key\":\"Education\",\"_type\":\"tag\",\"label\":\"Education\",\"value\":\"Education\"}],\"summary\":null,\"title\":\"Introducing Claude for Education\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A hand-drawn image where a black square overlaps with a white circle, revealing nodes and connections inside the circle, some of which are highlighted\",\"height\":2000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/66f4c451902f6310a5b24191c975825dc380db2b-2000x2000.png\",\"width\":2000},\"directories\":[{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"},{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-03-27T09:16:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"tracing-thoughts-language-model\"},\"subjects\":[{\"_key\":\"interpretability\",\"_type\":\"tag\",\"label\":\"Interpretability\",\"value\":\"interpretability\"}],\"summary\":\"Circuit tracing lets us watch Claude think, uncovering a shared conceptual space where reasoning happens before being translated into language—suggesting the model can learn something in one language and apply it in another.\",\"title\":\"Tracing the thoughts of a large language model\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/45c41da0a894deb7c2265fffc882caa4a716947d-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-03-19T20:45:20.016Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-s-response-to-governor-newsom-s-ai-working-group-draft-report\"},\"subjects\":[{\"_key\":\"societal-impacts\",\"_type\":\"tag\",\"label\":\"Societal Impacts\",\"value\":\"societal-impacts\"}],\"summary\":null,\"title\":\"Anthropic’s response to Governor Newsom’s AI working group draft report\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":2000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/069ad784540fa37e9862e3c0e604b5be16708084-2000x2000.png\",\"width\":2000},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-03-19T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"strategic-warning-for-ai-risk-progress-and-insights-from-our-frontier-red-team\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Progress from our Frontier Red Team\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A hand-drawn image of a government building\",\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/45c41da0a894deb7c2265fffc882caa4a716947d-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:37:23Z\",\"_id\":\"DElaXo1A74rjItEmVak9R1\",\"_rev\":\"CIQMb8zr2hKNcFuuO2Jt5E\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:02:38Z\",\"description\":\"Large institutional government building with multiple architectural levels and structured geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6e00dbffcddc82df5e471c43453abfc74ca94e8d-1000x1000.svg\",\"width\":1000},\"keywords\":\"government, building, institution, civic, public, official, governmental, institutional building, public institution, civic building, government structure, official building, policy\",\"name\":\"Object Government\",\"type\":\"hero\"}},\"publishedOn\":\"2025-03-06T10:45:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-s-recommendations-ostp-u-s-ai-action-plan\"},\"subjects\":[{\"_key\":\"societal-impacts\",\"_type\":\"tag\",\"label\":\"Societal Impacts\",\"value\":\"societal-impacts\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Anthropic’s recommendations to OSTP for the U.S. AI action plan\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A hand-drawn image of a staircase with a line implying upward motion\",\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/f438a6545f4b5280560b58ee98eeca6c41ef82b7-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"cactus\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:36:49Z\",\"_id\":\"uWx6ePFJ4MmdfRYgKIxDT5\",\"_rev\":\"MSyv171NSvWZvUt9ouLB5i\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:03:26Z\",\"description\":\"Geometric staircase steps ascending vertically with incremental progression\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-ddad92700787ec1bf1d80359c0c5e6ca305682b0-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ddad92700787ec1bf1d80359c0c5e6ca305682b0-1000x1000.svg\",\"width\":1000},\"keywords\":\"stairs, steps, staircase, ascending, climbing, progress, advancement, step by step, upward movement, progression, gradual improvement, levels, incremental progress, growth, momentum, building momentum, steady growth, upward trajectory, continuous improvement, scaling up\",\"name\":\"Object Stairs\",\"type\":\"hero\"}},\"publishedOn\":\"2025-03-03T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-raises-series-e-at-usd61-5b-post-money-valuation\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic raises Series E at $61.5B post-money valuation\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-02-28T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-partners-with-u-s-national-labs-for-first-1-000-scientist-ai-jam\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic partners with U.S. National Labs for first 1,000 Scientist AI Jam\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1261,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/1684a98e90b6bbc9e8e017b8a1a867ee75d1e8cf-1681x1261.png\",\"width\":1681},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-02-27T23:48:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"introducing-anthropic-transparency-hub\"},\"subjects\":[{\"_key\":\"societal-impacts\",\"_type\":\"tag\",\"label\":\"Societal Impacts\",\"value\":\"societal-impacts\"}],\"summary\":null,\"title\":\"Introducing Anthropic's Transparency Hub\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/f7b5f2335bdee9c00d889ae1e90249154fcd7db1-1680x1260.png\",\"width\":1680},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-02-26T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-and-alexa-plus\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude and Alexa+\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"An illustration of Claude thinking step-by-step\",\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/3e3d5d28255c40851e855234d8391dc0a0649f64-1680x1260.png\",\"width\":1680},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:35:15Z\",\"_id\":\"L5WZ73ZndVNkcSTU1XoHWy\",\"_rev\":\"znUZZ0fmIk1XIVDY2KCgRv\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T21:00:05Z\",\"description\":\"Stylized hand and head silhouette with interconnected node and abstract geometric elements\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-46e4aa7ea208ed440d5bd9e9e3a0ee66bc336ff1-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/46e4aa7ea208ed440d5bd9e9e3a0ee66bc336ff1-1000x1000.svg\",\"width\":1000},\"keywords\":\"Hero illustration: Hand HeadNodeThink\",\"name\":\"Hand HeadNodeThink\",\"type\":\"hero\"}},\"publishedOn\":\"2025-02-24T18:30:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-3-7-sonnet\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude 3.7 Sonnet and Claude Code\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A hand-drawn image of a hand with a set of nodes emerging above it, extending in several different directions\",\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/35c3cf6f17013234144a4065dfd8b7d876521be1-1680x1260.png\",\"width\":1680},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"olive\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:54Z\",\"_id\":\"DElaXo1A74rjItEmVahxtX\",\"_rev\":\"znUZZ0fmIk1XIVDY2KBYf1\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:41Z\",\"description\":\"Hand with branching tree-like network structure extending from fingertips in organic, hierarchical pattern\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-74409af25137110ac04cc39e4d5ea0a2fbcea421-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/74409af25137110ac04cc39e4d5ea0a2fbcea421-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, tree, node, hierarchy, structure, decision tree, network hierarchy, branching network, hierarchical structure, organizational tree, branching connections, growth, expansion, development, scaling, organic growth, business growth, structural growth\",\"name\":\"Hand NodeTree\",\"type\":\"hero\"}},\"publishedOn\":\"2025-02-24T14:38:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"visible-extended-thinking\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude’s extended thinking\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A hand-drawn image of a hand signing a piece of paper with a quill pen\",\"height\":1203,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/514d2bd8aeadab490cc631badefe6aaca8e8a458-1600x1203.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"oat\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:33:35Z\",\"_id\":\"DElaXo1A74rjItEmVahiln\",\"_rev\":\"CIQMb8zr2hKNcFuuO2IdYy\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:58:21Z\",\"description\":\"Ornate quill pen resting on a detailed hand, positioned against a textured background\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/33dbe8f783d4835a838b4c4ae85d3c04e352fee1-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, quill, writing, pen, authoring, documentation, content creation, writing tools, literary work, composition, manuscript, creative writing, text creation\",\"name\":\"Hand Quill\",\"type\":\"hero\"}},\"publishedOn\":\"2025-02-14T00:01:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"mou-uk-government\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic signs MOU with UK Government to explore how AI can transform UK public services \"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A hand-drawn image of a lighthouse on a rock, with large waves hitting the rock on either side\",\"height\":1261,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/84dfc3a6a5b8bf79a0cd430524c1f5a89e376531-1681x1261.svg\",\"width\":1681},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-02-11T10:29:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"paris-ai-summit\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Statement from Dario Amodei on the Paris AI Action Summit\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-02-06T21:52:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"lyft-announcement\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Lyft to bring Claude to more than 40 million riders and over 1 million drivers\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Four locks joined together\",\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/2ef75017975f8bc6aa910152bc68a09e18dc671a-1312x1312.png\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2025-01-13T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-achieves-iso-42001-certification-for-responsible-ai\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic achieves ISO 42001 certification for responsible AI\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":2000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/2983e5021d1090ef2dc16018a2d9b189843e310e-2000x2000.png\",\"width\":2000},\"directories\":[{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"},{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-12-18T14:16:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"alignment-faking\"},\"subjects\":[{\"_key\":\"alignment\",\"_type\":\"tag\",\"label\":\"Alignment\",\"value\":\"alignment\"}],\"summary\":\"This paper provides the first empirical example of a model engaging in alignment faking without being trained to do so—selectively complying with training objectives while strategically preserving existing preferences.\",\"title\":\"Alignment faking in large language models\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1260,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/f1d1a4c75433996f97b87ea0f3791022370e2765-1680x1260.svg\",\"width\":1680},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-12-12T20:06:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"elections-ai-2024\"},\"subjects\":[{\"_key\":\"societal-impacts\",\"_type\":\"tag\",\"label\":\"Societal Impacts\",\"value\":\"societal-impacts\"}],\"summary\":null,\"title\":\"Elections and AI in 2024: observations and learnings\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"An abstract illustration of critical context connecting to a central hub\",\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/0106dec137d4720d9ccccc9b01b1f9b5d72585e4-1312x1312.png\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-11-25T15:50:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"model-context-protocol\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Introducing the Model Context Protocol\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"amazon and anthropic logos\",\"height\":2624,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/919018bb005a47134a990389e76d9cc1766d17ca-2624x2624.png\",\"width\":2624},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-11-22T13:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-amazon-trainium\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Powering the next generation of AI development with AWS\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A building with columns\",\"height\":1621,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/6b04f486cfe0b8a62e4632f3186f23afcd22a890-2880x1621.png\",\"width\":2880},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-10-31T19:30:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"the-case-for-targeted-regulation\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"The case for targeted regulation\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A stylized image of cogs, to represent tool use\",\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/85f273709539b4fd9b1909aa9feeabdc7712edf7-1312x1312.png\",\"width\":1312},\"directories\":[{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"},{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-10-30T23:25:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"swe-bench-sonnet\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Raising the bar on SWE-bench Verified with Claude 3.5 Sonnet\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Visual of the GitHub and Anthropic logos\",\"height\":2625,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/2ee03b16aab67a255f6ddd5f35429b134acdf503-2624x2625.png\",\"width\":2624},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-10-29T16:15:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"github-copilot\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude 3.5 Sonnet on GitHub Copilot\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"An abstract representation of AI computer use, with a computer cursor clicking on a stylized representation of a neural network\",\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/f7cf518c495670a1fe932f76c8e06f4f76f51b72-1312x1312.png\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"},{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"}],\"illustration\":null,\"publishedOn\":\"2024-10-22T19:42:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"developing-computer-use\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"},{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Developing a computer use model\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ed472910ff6fe8e8261435613a422048f27c5076-1312x1312.png\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":\"clay\",\"illustration\":{\"_createdAt\":\"2025-07-17T19:34:33Z\",\"_id\":\"Z7bXjXUrfbilTWp6LlybFk\",\"_rev\":\"L1sWYwVuS7u8WeTHm66tS8\",\"_type\":\"illustration\",\"_updatedAt\":\"2025-07-18T20:59:41Z\",\"description\":\"Silhouette of person's profile with hand cursor and human head outline\",\"image\":{\"_type\":\"image\",\"asset\":{\"_ref\":\"image-abc884c723daea810d2e986455358281a2f94102-1000x1000-svg\",\"_type\":\"reference\"},\"height\":1000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/abc884c723daea810d2e986455358281a2f94102-1000x1000.svg\",\"width\":1000},\"keywords\":\"hand, head, cursor, profile, person, silhouette, pointer, user interaction, personal selection, individual choice, human interface, targeting, user interfaces, user experience, AI interaction, human-computer interaction, AI assistant, machine learning, artificial intelligence, computer user, digital persona, AI user, human-AI collaboration\",\"name\":\"Hand HeadCursor\",\"type\":\"hero\"}},\"publishedOn\":\"2024-10-22T15:51:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"3-5-models-and-computer-use\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Introducing computer use, a new Claude 3.5 Sonnet, and Claude 3.5 Haiku\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A hand with a feather quill writing a policy document. \",\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/591404bad10f6fb79c2561d72999e30d633792f2-1312x1312.png\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-10-15T13:30:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"announcing-our-updated-responsible-scaling-policy\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Announcing our updated Responsible Scaling Policy\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":631,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/d349f9f92aaf574702f002fbb2b01159e6e4c659-1200x631.png\",\"width\":1200},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-10-08T18:21:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"us-elections-readiness\"},\"subjects\":[{\"_key\":\"societal-impacts\",\"_type\":\"tag\",\"label\":\"Societal Impacts\",\"value\":\"societal-impacts\"}],\"summary\":null,\"title\":\"U.S. elections readiness\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/98bc6d3ec0e065855c25d2f9a1dc912fe281bf45-1312x1312.png\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-09-19T19:21:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"contextual-retrieval\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"},{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Introducing Contextual Retrieval\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Salesforce and Anthropic logo lockup \",\"height\":2001,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/9ed5fc6354cc1fb1fffe7137f173dfa32d7af120-2000x2001.png\",\"width\":2000},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-09-03T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"salesforce-partnership\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Salesforce teams up with Anthropic to enhance Einstein capabilities with Claude\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Security locks\",\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/2ef75017975f8bc6aa910152bc68a09e18dc671a-1312x1312.png\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-08-08T13:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"model-safety-bug-bounty\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Expanding our model safety bug bounty program \"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Claude 3 head illustration\",\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/c801bd032a7489f5fdd720b5e2fb0c842901e7aa-1312x1312.jpg\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-08-01T18:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-brazil\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude is now available in Brazil\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-07-17T16:05:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-partners-with-menlo-ventures-to-launch-anthology-fund\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic partners with Menlo Ventures to launch Anthology Fund\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-07-11T02:42:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"fine-tune-claude-3-haiku\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Fine-tune Claude 3 Haiku in Amazon Bedrock\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"A new initiative for developing third-party model evaluations\",\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/edd06a55a33431380c89c1864a07859edb8065a7-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-07-01T19:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"a-new-initiative-for-developing-third-party-model-evaluations\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"A new initiative for developing third-party model evaluations\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-06-26T17:20:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"expanding-access-to-claude-for-government\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Expanding access to Claude for government\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Illustration showing users collaborating around Claude logo\",\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/7a925b4d2bd05668ef74dd6fe12919ba22184481-1312x1312.jpg\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-06-25T18:19:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"projects\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Collaborate with Claude on Projects\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Claude 3 illustration\",\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5ad7d0ef82a489dc20e44f19ce313b09604e4252-1312x1312.jpg\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-06-21T03:28:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-3-5-sonnet\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude 3.5 Sonnet\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Computer chip and a flame\",\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/edd06a55a33431380c89c1864a07859edb8065a7-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-06-12T16:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"challenges-in-red-teaming-ai-systems\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Challenges in red teaming AI systems\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/409cb399d3cd156905d9094be74949756790a9ac-1312x1312.png\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"},{\"_key\":\"research\",\"_type\":\"tag\",\"label\":\"Research\",\"value\":\"research\"}],\"illustration\":null,\"publishedOn\":\"2024-06-06T13:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"testing-and-mitigating-elections-related-risks\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"},{\"_key\":\"societal-impacts\",\"_type\":\"tag\",\"label\":\"Societal Impacts\",\"value\":\"societal-impacts\"}],\"summary\":null,\"title\":\"Testing and mitigating elections-related risks\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Introducing Claude to Canada\",\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5ad7d0ef82a489dc20e44f19ce313b09604e4252-1312x1312.jpg\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-06-05T15:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"introducing-claude-to-canada\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Introducing Claude to Canada\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-05-29T17:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"jay-kreps-appointed-to-board-of-directors\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Jay Kreps appointed to Anthropic's Board of Directors\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":2000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/d9032f7916a91e8a78003eb79c24ae0bf3cd3b9d-2000x2000.png\",\"width\":2000},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-05-23T18:45:35.460Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"golden-gate-claude\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Golden Gate Claude\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-05-21T08:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"krishna-rao-joins-anthropic\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Krishna Rao joins Anthropic as Chief Financial Officer\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Gavel \",\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/454127b470eed6d649e67d19afb6dd5ab354fb58-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-05-20T00:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"reflections-on-our-responsible-scaling-policy\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Reflections on our Responsible Scaling Policy\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-05-15T14:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"mike-krieger-joins-anthropic\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Mike Krieger joins Anthropic as Chief Product Officer\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5ad7d0ef82a489dc20e44f19ce313b09604e4252-1312x1312.jpg\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-05-14T07:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-europe\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude is now available in Europe\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-05-10T17:00:36.698Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"updating-our-usage-policy\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Updating our Usage Policy\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-04-23T20:36:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"child-safety-principles\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Aligning on child safety principles\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1313,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/33ced8287c63ec94b50da01c1926e58750a7f67e-1312x1313.jpg\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-03-25T15:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"third-party-testing\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Third-party testing as a key ingredient of AI policy\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/c40f969caae8c6ae3c665bed90261655d45023fe-1312x1312.png\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-03-20T14:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"accenture-aws-anthropic\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic, AWS, and Accenture team up to build trusted solutions for enterprises\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/b42db5b8558fab6b7452cfe30bd4f8aa734e8337-1312x1312.png\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-03-19T23:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"google-vertex-general-availability\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude 3 models on Vertex AI\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1620,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/9f8464f29d6f93067c69cc257db94bf04a661cc8-2880x1620.png\",\"width\":2880},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-03-13T21:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-3-haiku\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude 3 Haiku: our fastest model yet\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":\"Introducing the next generation of Claude\",\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5ad7d0ef82a489dc20e44f19ce313b09604e4252-1312x1312.jpg\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-03-04T08:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-3-family\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Introducing the next generation of Claude\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/80ef16b1598c418c3c0876ea6607b47e33417bc6-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-02-29T08:00:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"prompt-engineering-for-business-performance\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Prompt engineering for business performance\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/e8d6c1c10399c016ec89e36eb15bcfd2db8cb926-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2024-02-16T11:30:00.000Z\",\"slug\":{\"_type\":\"slug\",\"current\":\"preparing-for-global-elections-in-2024\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Preparing for global elections in 2024\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-12-19T08:00:00-08:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"expanded-legal-protections-api-improvements\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Expanded legal protections and improvements to our API\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/72d6358c4ac2a07fac44d1ea9abf63a1f0c7494d-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-11-21T06:00:00-08:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-2-1\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Introducing Claude 2.1\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/136e899a164e36ccd50bdda8725046b2006ff342-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-11-05T05:00:00-08:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"policy-recap-q4-2023\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Thoughts on the US Executive Order, G7 Code of Conduct, and Bletchley Park Summit\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/29f7f151aac909fad9968c7fcc1dc0e8a6ca6b8c-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-11-01T06:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"uk-ai-safety-summit\"},\"subjects\":[{\"_key\":\"policy\",\"_type\":\"tag\",\"label\":\"Policy\",\"value\":\"policy\"}],\"summary\":null,\"title\":\"Dario Amodei’s prepared remarks from the AI Safety Summit on Anthropic’s Responsible Scaling Policy\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":2624,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/919018bb005a47134a990389e76d9cc1766d17ca-2624x2624.png\",\"width\":2624},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-09-25T00:01:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-amazon\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Expanding access to safer AI with Amazon\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/4bebf8fe3ff16ccb67a680da906387a3c85fb36d-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-09-23T09:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"prompting-long-context\"},\"subjects\":[{\"_key\":\"product\",\"_type\":\"tag\",\"label\":\"Product\",\"value\":\"product\"}],\"summary\":null,\"title\":\"Prompt engineering for Claude's long context window\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/454127b470eed6d649e67d19afb6dd5ab354fb58-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-09-19T07:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropics-responsible-scaling-policy\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":\"We’re publishing our Responsible Scaling Policy—a series of technical and organizational protocols that we’re adopting to help us manage the risks of developing increasingly capable AI systems.\",\"title\":\"Introducing Anthropic's Responsible Scaling Policy\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ecde3c5e01a286fc8353e0c8af70547956dde568-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-09-19T05:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"the-long-term-benefit-trust\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"The Long-Term Benefit Trust\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/d3d37e66de882d7f018f6f50b13ecf63bfb8b813-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-09-14T05:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-bcg\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic partners with BCG\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1312,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/211a1d4c9b92f5ae255d983934ac197200d2bf21-1312x1312.jpg\",\"width\":1312},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-09-07T06:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-pro\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Introducing Claude Pro\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/0cba2996abd4346c54de05496c4f40f24f592f9f-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-08-15T07:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"skt-partnership-announcement\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"SKT partnership announcement\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/d5859a11467dde30ea2b3e9e8e6e595a0bf7b5c3-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-08-09T07:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"releasing-claude-instant-1-2\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Releasing Claude Instant 1.2\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/edd06a55a33431380c89c1864a07859edb8065a7-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-07-26T00:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"frontier-threats-red-teaming-for-ai-safety\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Frontier threats red teaming for AI safety\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/da71c470d15fe19a6291299e0a7641236d875de6-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-07-25T00:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"frontier-model-security\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Frontier model security\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/72d6358c4ac2a07fac44d1ea9abf63a1f0c7494d-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-07-11T00:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"claude-2\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude 2\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/5736ad2bdc8266d43112524e51c1fee5c2ee0398-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-06-13T00:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"charting-a-path-to-ai-accountability\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Charting a path to AI accountability \"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/96e0eefdefd7319a54e805514c1b1c9a5aa31488-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-05-23T06:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-series-c\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic raises $450 million in Series C funding to scale reliable AI products\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/06d6fc72126ce9fb19624017225a909d934cc2e9-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-05-16T07:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"zoom-partnership-and-investment\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Zoom partnership and investment in Anthropic\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/2f2baa4b5244b4a62797211bfb623caacb64c304-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-05-11T00:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"100k-context-windows\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Introducing 100K context windows\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/9e41f1798059d807389adfc0f113b2d23dac126a-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-05-09T00:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"claudes-constitution\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Claude’s constitution\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/05ef62035cbd5778eba10bc5c8fa40a6bf770b83-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-04-26T00:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"partnering-with-scale\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Partnering with Scale to bring generative AI to enterprises\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/ecde3c5e01a286fc8353e0c8af70547956dde568-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-04-20T00:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"an-ai-policy-tool-for-today-ambitiously-invest-in-nist\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"An AI Policy Tool for Today: Ambitiously Invest in NIST\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":1600,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/062fb15ea8d9570a4456391f2acc2b502e1b451e-1600x1600.png\",\"width\":1600},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-03-14T00:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"introducing-claude\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Introducing Claude\"},{\"_type\":\"post\",\"cardPhoto\":{\"description\":null,\"height\":2000,\"url\":\"https://cdn.sanity.io/images/4zrzovbb/website/76f13c5f60cf0a73497a9e53e417b85a72a21d5e-2000x2000.png\",\"width\":2000},\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":{\"backgroundColor\":null,\"illustration\":null},\"publishedOn\":\"2023-03-08T00:00:00-08:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"core-views-on-ai-safety\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Core views on AI safety: When, why, what, and how\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2023-02-03T00:00:00-08:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-partners-with-google-cloud\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic partners with Google Cloud\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2022-04-29T07:50:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-raises-series-b-to-build-safe-reliable-ai\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic Raises Series B to build steerable, interpretable, robust AI systems\"},{\"_type\":\"post\",\"cardPhoto\":null,\"directories\":[{\"_key\":\"news\",\"_type\":\"tag\",\"label\":\"News\",\"value\":\"news\"}],\"illustration\":null,\"publishedOn\":\"2021-05-28T00:00:00-07:00\",\"slug\":{\"_type\":\"slug\",\"current\":\"anthropic-raises-124-million-to-build-more-reliable-general-ai-systems\"},\"subjects\":[{\"_key\":\"announcements\",\"_type\":\"tag\",\"label\":\"Announcements\",\"value\":\"announcements\"}],\"summary\":null,\"title\":\"Anthropic raises $124 million to build more reliable, general AI systems\"}],\"title\":\"News\"}],\"slug\":{\"_type\":\"slug\",\"current\":\"news\"},\"title\":\"Newsroom\"},\"theme\":\"$undefined\",\"hideOnScroll\":\"$undefined\"}],\"$L1b\",\"$L1c\"]}]\n"])</script><script>self.__next_f.push([1,"16:[\"$\",\"$L17\",null,{\"children\":[null,[\"$\",\"$L18\",null,{\"isMinimalNavigation\":\"$undefined\",\"siteSettings\":{\"_createdAt\":\"2023-11-03T16:49:36Z\",\"_id\":\"13c6e1a1-6f38-400c-ae18-89d73b6ba991\",\"_rev\":\"XQe4R6LiqiY3ST7NppsXi8\",\"_system\":\"$6:props:children:1:props:siteSettings:_system\",\"_type\":\"siteSettings\",\"_updatedAt\":\"2026-09-11T15:26:27Z\",\"announcement\":null,\"claudeCta\":\"$6:props:children:1:props:siteSettings:claudeCta\",\"copyright\":\"© 2026 Anthropic PBC\",\"copyrightEu\":\"© 2026 Anthropic PBC. Services in the EU are provided by Anthropic Ireland Limited.\",\"footer\":\"$6:props:children:1:props:siteSettings:footer\",\"footerNavigation\":\"$6:props:children:1:props:siteSettings:footerNavigation\",\"headerNavigation\":\"$6:props:children:1:props:siteSettings:headerNavigation\",\"internalName\":\"anthropic.com Site Settings\",\"linkedInUsername\":\"anthropicresearch\",\"menu\":\"$6:props:children:1:props:siteSettings:menu\",\"meta\":\"$6:props:children:1:props:siteSettings:meta\",\"navigation\":\"$6:props:children:1:props:siteSettings:navigation\",\"search\":\"$6:props:children:1:props:siteSettings:search\",\"siteName\":\"Anthropic\",\"sitemapUrls\":\"$6:props:children:1:props:siteSettings:sitemapUrls\",\"twitterUsername\":\"AnthropicAI\",\"youtubeUsername\":\"anthropic-ai\",\"hideFooter\":true},\"page\":{\"_type\":\"page\",\"_id\":\"not-found\",\"_rev\":\"\",\"_createdAt\":\"\",\"_updatedAt\":\"\",\"title\":\"Not Found\",\"slug\":{\"_type\":\"slug\",\"current\":\"not-found\"},\"meta\":{},\"sections\":[]},\"theme\":\"$undefined\",\"hideOnScroll\":\"$undefined\"}],[\"$\",\"main\",null,{\"id\":\"main-content\",\"className\":\"\",\"children\":[\"$\",\"$L1d\",null,{}]}],null]}]\n"])</script><script>self.__next_f.push([1,"1b:[\"$\",\"main\",null,{\"id\":\"main-content\",\"className\":\"\",\"children\":[\"$\",\"article\",null,{\"children\":[[\"$\",\"section\",\"0\",{\"className\":\"HeroTwoColumn-module-scss-module__pM-nba__landingPageListHeader LandingPageSection-module-scss-module__ZSMdoa__root bg-default\",\"id\":\"$undefined\",\"ref\":\"$undefined\",\"style\":\"$undefined\",\"data-theme\":\"ivory\",\"children\":[false,[\"$\",\"div\",null,{\"className\":\"page-wrapper\",\"children\":[\"$undefined\",[\"$\",\"div\",null,{\"className\":\"HeroTwoColumn-module-scss-module__pM-nba__root\",\"children\":[[\"$\",\"div\",null,{\"className\":\"HeroTwoColumn-module-scss-module__pM-nba__titleSubhead\",\"children\":[\"$\",\"h1\",null,{\"className\":\"headline-1\",\"children\":\"Newsroom\"}]}],[\"$\",\"div\",null,{\"className\":\"HeroTwoColumn-module-scss-module__pM-nba__bodyCtas\",\"children\":[\"$undefined\",[\"$\",\"div\",null,{\"className\":\"HeroTwoColumn-module-scss-module__pM-nba__ctaWrapper\",\"children\":[\"$\",\"ul\",null,{\"className\":\"HeroTwoColumn-module-scss-module__pM-nba__ctaList\",\"children\":[[\"$\",\"li\",\"0\",{\"children\":[[\"$\",\"span\",null,{\"className\":\"HeroTwoColumn-module-scss-module__pM-nba__listLabel body-3\",\"children\":\"Press inquiries\"}],[\"$\",\"$L1e\",null,{\"link\":{\"url\":\"mailto:press@anthropic.com\",\"text\":\"press@anthropic.com\"},\"ctaPosition\":\"hero-two-column-list\",\"className\":\"HeroTwoColumn-module-scss-module__pM-nba__listLink\",\"icon\":[\"$\",\"$L1f\",null,{\"fill\":\"currentColor\"}],\"iconPosition\":\"left\"}]]}],[\"$\",\"li\",\"1\",{\"children\":[[\"$\",\"span\",null,{\"className\":\"HeroTwoColumn-module-scss-module__pM-nba__listLabel body-3\",\"children\":\"Non-media inquiries\"}],[\"$\",\"$L1e\",null,{\"link\":{\"url\":\"https://support.claude.com/en/articles/9015913-how-to-get-support\",\"text\":\"How to get support\"},\"ctaPosition\":\"hero-two-column-list\",\"className\":\"HeroTwoColumn-module-scss-module__pM-nba__listLink\",\"icon\":[\"$\",\"$L20\",null,{\"fill\":\"currentColor\"}],\"iconPosition\":\"left\"}]]}],[\"$\",\"li\",\"2\",{\"children\":[[\"$\",\"span\",null,{\"className\":\"HeroTwoColumn-module-scss-module__pM-nba__listLabel body-3\",\"children\":\"Media assets\"}],[\"$\",\"$L1e\",null,{\"link\":{\"url\":\"https://anthropic.com/press-kit\",\"text\":\"Download press kit\"},\"ctaPosition\":\"hero-two-column-list\",\"className\":\"HeroTwoColumn-module-scss-module__pM-nba__listLink\",\"icon\":[\"$\",\"$L21\",null,{\"fill\":\"currentColor\"}],\"iconPosition\":\"left\"}]]}]]}]}]]}]]}]]}]]}],[\"$\",\"section\",\"1\",{\"className\":\"LandingPageSection-module-scss-module__ZSMdoa__root bg-default LandingPageSection-module-scss-module__ZSMdoa__flushTop\",\"id\":\"$undefined\",\"ref\":\"$undefined\",\"style\":\"$undefined\",\"data-theme\":\"ivory\",\"children\":[[\"$\",\"div\",null,{\"className\":\"page-wrapper\",\"children\":[\"$\",\"div\",null,{\"className\":\"LandingPageSection-module-scss-module__ZSMdoa__borderTop\"}]}],[\"$\",\"div\",null,{\"className\":\"page-wrapper\",\"children\":[\"$\",\"div\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__root\",\"children\":[[\"$\",\"div\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__featuredItem\",\"children\":[[\"$\",\"figure\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__mediaWrapper\",\"children\":[[\"$\",\"div\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__mediaContent\",\"children\":[false,[\"$\",\"div\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__mediaVideo\",\"children\":[\"$\",\"$L22\",null,{\"_type\":\"video\",\"autoplay\":false,\"embedUrl\":\"https://www.youtube.com/watch?v=ROF2Nv_KjOM\",\"loop\":false,\"muted\":false,\"showControls\":true,\"thumbnail\":\"$6:props:children:1:props:page:sections:1:video:thumbnail\",\"url\":null}]}],\"$undefined\",false]}],[\"$\",\"figcaption\",null,{\"className\":\"caption\",\"children\":[]}]]}],[\"$\",\"a\",null,{\"href\":\"/claude-fable-and-mythos-5-1\",\"className\":\"FeaturedGrid-module-scss-module__W1FydW__content\",\"children\":[[\"$\",\"h2\",null,{\"className\":\"headline-4 FeaturedGrid-module-scss-module__W1FydW__featuredTitle\",\"children\":\"Introducing Claude Fable 5.1 and Claude Mythos 5.1\"}],[\"$\",\"div\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__featuredItemContent\",\"children\":[\"$\",\"a\",null,{\"href\":\"/claude-fable-and-mythos-5-1\",\"className\":\"FeaturedGrid-module-scss-module__W1FydW__gridItem FeaturedGrid-module-scss-module__W1FydW__featured\",\"children\":[[\"$\",\"div\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__meta\",\"children\":[[\"$\",\"span\",null,{\"className\":\"caption bold\",\"children\":\"Announcements\"}],[\"$\",\"time\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__date caption bold\",\"children\":\"Sep 1, 2026\"}]]}],false,\"$L23\"]}]}]]}]]}],\"$L24\"]}]}]]}],\"$L25\"]}]}]\n"])</script><script>self.__next_f.push([1,"1c:[\"$\",\"footer\",null,{\"id\":\"footer\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__root\",\"role\":\"contentinfo\",\"aria-label\":\"Site footer\",\"children\":[\"$\",\"div\",null,{\"className\":\"page-wrapper SiteFooter-module-scss-module__JdOqwq__footer\",\"children\":[[\"$\",\"div\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__logoWrapper\",\"children\":[\"$\",\"a\",null,{\"href\":\"/\",\"aria-label\":\"Return to homepage\",\"className\":\"$undefined\",\"children\":[\"$\",\"$L26\",null,{\"fill\":\"#faf9f5\",\"aria-hidden\":\"true\"}]}]}],[\"$\",\"nav\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__linksWrapper\",\"aria-label\":\"Footer navigation\",\"style\":{\"--footer-columns\":4},\"children\":[[\"$\",\"div\",\"0\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__columnSection\",\"children\":[[\"$\",\"div\",\"0\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__listSection\",\"children\":[[\"$\",\"h3\",null,{\"className\":\"body-4 bold\",\"children\":\"Products\"}],[\"$\",\"ul\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__list\",\"children\":[[\"$\",\"li\",\"0\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/product/overview\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Claude\"}]}],[\"$\",\"li\",\"1\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/product/claude-code\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Claude Code\"}]}],[\"$\",\"li\",\"2\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/product/claude-code/enterprise\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Claude Code Enterprise\"}]}],[\"$\",\"li\",\"3\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/product/cowork\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Claude Cowork\"}]}],[\"$\",\"li\",\"4\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/product/tag\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"@Claude\"}]}],[\"$\",\"li\",\"5\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/product/design\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Claude Design\"}]}],[\"$\",\"li\",\"6\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/product/claude-science\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Claude Science\"}]}],[\"$\",\"li\",\"7\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/product/claude-security\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Claude Security\"}]}],[\"$\",\"li\",\"8\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/claude-in-chrome\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Claude in Chrome\"}]}],[\"$\",\"li\",\"9\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/claude-for-microsoft-365\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Claude for Microsoft 365\"}]}],[\"$\",\"li\",\"10\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.claude.com/skills\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Skills\"}]}],[\"$\",\"li\",\"11\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.ai/download\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Download app\"}]}],[\"$\",\"li\",\"12\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/pricing\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Pricing\"}]}],[\"$\",\"li\",\"13\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.ai/\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Log in to Claude\"}]}]]}]]}],\"$L27\"]}],\"$L28\",\"$L29\",\"$L2a\"]}],\"$L2b\"]}]}]\n"])</script><script>self.__next_f.push([1,"23:[\"$\",\"p\",null,{\"className\":\"body-3 serif FeaturedGrid-module-scss-module__W1FydW__body\",\"children\":\"Our most advanced models for coding and knowledge work. Their research capabilities also offer an early glimpse of how AI models will contribute to scientific progress.\"}]\n"])</script><script>self.__next_f.push([1,"24:[\"$\",\"div\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__sideItems\",\"children\":[[\"$\",\"a\",\"abd66cc77488\",{\"href\":\"https://www.anthropic.com/threat-intelligence-report-september-2026\",\"className\":\"FeaturedGrid-module-scss-module__W1FydW__sideLink FeaturedGrid-module-scss-module__W1FydW__gridItem\",\"children\":[[\"$\",\"div\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__meta\",\"children\":[[\"$\",\"span\",null,{\"className\":\"caption bold\",\"children\":\"Announcements\"}],[\"$\",\"time\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__date caption bold\",\"children\":\"Sep 10, 2026\"}]]}],[\"$\",\"h4\",null,{\"className\":\"headline-6 FeaturedGrid-module-scss-module__W1FydW__title\",\"children\":\"Detecting and countering misuse of AI: September 2026\"}],[\"$\",\"p\",null,{\"className\":\"body-3 serif FeaturedGrid-module-scss-module__W1FydW__body\",\"children\":\"Over the past eight months, our Threat Intelligence team identified and disrupted operations in which threat actors tried to use Claude for malicious activity. In this report, we share case studies from those operations and describe how malicious use of Claude has evolved since our previous threat reports in 2025.\"}]]}],[\"$\",\"a\",\"improving-alignment-security-efforts\",{\"href\":\"/news/improving-alignment-security-efforts\",\"className\":\"FeaturedGrid-module-scss-module__W1FydW__sideLink FeaturedGrid-module-scss-module__W1FydW__gridItem\",\"children\":[[\"$\",\"div\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__meta\",\"children\":[[\"$\",\"span\",null,{\"className\":\"caption bold\",\"children\":\"Announcements\"}],[\"$\",\"time\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__date caption bold\",\"children\":\"Aug 31, 2026\"}]]}],[\"$\",\"h4\",null,{\"className\":\"headline-6 FeaturedGrid-module-scss-module__W1FydW__title\",\"children\":\"Improving our alignment and security efforts\"}],[\"$\",\"p\",null,{\"className\":\"body-3 serif FeaturedGrid-module-scss-module__W1FydW__body\",\"children\":\"On July 30, we reported three incidents in which Claude models gained unauthorized access to real computer systems. We are conducting an in-depth analysis of both incidents, and planning to work with METR for an independent review. In the meantime, we’re sharing some of the changes we’ve made over the past month.\"}]]}],[\"$\",\"a\",\"model-hardware-standard-research-preview\",{\"href\":\"/news/model-hardware-standard-research-preview\",\"className\":\"FeaturedGrid-module-scss-module__W1FydW__sideLink FeaturedGrid-module-scss-module__W1FydW__gridItem\",\"children\":[[\"$\",\"div\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__meta\",\"children\":[[\"$\",\"span\",null,{\"className\":\"caption bold\",\"children\":\"Announcements\"}],[\"$\",\"time\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__date caption bold\",\"children\":\"Aug 27, 2026\"}]]}],[\"$\",\"h4\",null,{\"className\":\"headline-6 FeaturedGrid-module-scss-module__W1FydW__title\",\"children\":\"Previewing the Model Hardware Standard\"}],[\"$\",\"p\",null,{\"className\":\"body-3 serif FeaturedGrid-module-scss-module__W1FydW__body\",\"children\":\"We’re opening a research preview of the Model Hardware Standard (MHS), a shared specification for AI agents to safely operate physical devices, to a first group of scientific research labs and advanced manufacturers. \"}]]}],[\"$\",\"a\",\"claude-opus-5\",{\"href\":\"/news/claude-opus-5\",\"className\":\"FeaturedGrid-module-scss-module__W1FydW__sideLink FeaturedGrid-module-scss-module__W1FydW__gridItem\",\"children\":[[\"$\",\"div\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__meta\",\"children\":[[\"$\",\"span\",null,{\"className\":\"caption bold\",\"children\":\"Product\"}],[\"$\",\"time\",null,{\"className\":\"FeaturedGrid-module-scss-module__W1FydW__date caption bold\",\"children\":\"Jul 24, 2026\"}]]}],[\"$\",\"h4\",null,{\"className\":\"headline-6 FeaturedGrid-module-scss-module__W1FydW__title\",\"children\":\"Introducing Claude Opus 5\"}],\"$L2c\"]}]]}]\n"])</script><script>self.__next_f.push([1,"25:[\"$\",\"$L2d\",\"2\",{\"index\":2,\"semanticLevel\":\"h2\",\"_createdAt\":\"2025-10-23T19:45:38Z\",\"_id\":\"fa4d54c7-ab7e-4461-96e7-9cd8b7dfaadd\",\"_rev\":\"kG12fknjLbGGavyRrOrDdp\",\"_type\":\"publicationList\",\"_updatedAt\":\"2025-11-16T19:17:09Z\",\"backgroundColor\":\"default\",\"borderTop\":true,\"directory\":\"$6:props:children:1:props:page:sections:2:directory\",\"flushBottom\":false,\"flushTop\":true,\"fullWidth\":false,\"postSubjects\":null,\"posts\":\"$6:props:children:1:props:page:sections:2:posts\",\"title\":\"News\"}]\n27:[\"$\",\"div\",\"1\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__listSection\",\"children\":[[\"$\",\"h3\",null,{\"className\":\"body-4 bold\",\"children\":\"Models\"}],[\"$\",\"ul\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__list\",\"children\":[[\"$\",\"li\",\"0\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/claude/mythos\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Mythos\"}]}],[\"$\",\"li\",\"1\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/claude/fable\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Fable\"}]}],[\"$\",\"li\",\"2\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/claude/opus\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Opus\"}]}],[\"$\",\"li\",\"3\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/claude/sonnet\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Sonnet\"}]}],[\"$\",\"li\",\"4\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/claude/haiku\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Haiku\"}]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"28:[\"$\",\"div\",\"1\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__columnSection\",\"children\":[[\"$\",\"div\",\"0\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__listSection\",\"children\":[[\"$\",\"h3\",null,{\"className\":\"body-4 bold\",\"children\":\"Solutions\"}],[\"$\",\"ul\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__list\",\"children\":[[\"$\",\"li\",\"0\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/agents\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"AI agents\"}]}],[\"$\",\"li\",\"1\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/code-modernization\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Code modernization\"}]}],[\"$\",\"li\",\"2\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/coding\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Coding\"}]}],[\"$\",\"li\",\"3\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/commerce\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Commerce\"}]}],[\"$\",\"li\",\"4\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/customer-support\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Customer support\"}]}],[\"$\",\"li\",\"5\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/cybersecurity\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Cybersecurity\"}]}],[\"$\",\"li\",\"6\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/enterprise\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Enterprise\"}]}],[\"$\",\"li\",\"7\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/financial-services\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Financial services\"}]}],[\"$\",\"li\",\"8\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/government\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Government\"}]}],[\"$\",\"li\",\"9\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/healthcare\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Healthcare\"}]}],[\"$\",\"li\",\"10\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/education\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Higher education\"}]}],[\"$\",\"li\",\"11\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/teachers\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"K-12 teachers\"}]}],[\"$\",\"li\",\"12\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/legal\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Legal\"}]}],[\"$\",\"li\",\"13\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/life-sciences\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Life sciences\"}]}],[\"$\",\"li\",\"14\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/nonprofits\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Nonprofits\"}]}],[\"$\",\"li\",\"15\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/solutions/small-business\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Small business\"}]}]]}]]}],[\"$\",\"div\",\"1\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__listSection\",\"children\":[\"$L2e\",\"$L2f\"]}]]}]\n"])</script><script>self.__next_f.push([1,"29:[\"$\",\"div\",\"2\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__columnSection\",\"children\":[[\"$\",\"div\",\"0\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__listSection\",\"children\":[[\"$\",\"h3\",null,{\"className\":\"body-4 bold\",\"children\":\"Resources\"}],[\"$\",\"ul\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__list\",\"children\":[[\"$\",\"li\",\"0\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/blog\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Blog\"}]}],[\"$\",\"li\",\"1\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/partners\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Claude partner network\"}]}],[\"$\",\"li\",\"2\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/community\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Community\"}]}],[\"$\",\"li\",\"3\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/connectors\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Connectors\"}]}],[\"$\",\"li\",\"4\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://academy.claude.com\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Courses\"}]}],[\"$\",\"li\",\"5\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/customers\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Customer stories\"}]}],[\"$\",\"li\",\"6\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/engineering\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Engineering at Anthropic\"}]}],[\"$\",\"li\",\"7\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/events\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Events\"}]}],[\"$\",\"li\",\"8\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/plugins\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Plugins\"}]}],[\"$\",\"li\",\"9\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/partners/powered-by-claude\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Powered by Claude\"}]}],[\"$\",\"li\",\"10\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/partners/services\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Service partners\"}]}],[\"$\",\"li\",\"11\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/resources/tutorials\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Tutorials\"}]}],[\"$\",\"li\",\"12\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/resources/use-cases\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Use cases\"}]}]]}]]}],[\"$\",\"div\",\"1\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__listSection\",\"children\":[[\"$\",\"h3\",null,{\"className\":\"body-4 bold\",\"children\":\"Programs\"}],[\"$\",\"ul\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__list\",\"children\":[[\"$\",\"li\",\"0\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/programs/startups\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Startups\"}]}],[\"$\",\"li\",\"1\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/programs/team-plan-for-scientists\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Scientists\"}]}]]}]]}],[\"$\",\"div\",\"2\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__listSection\",\"children\":[[\"$\",\"h3\",null,{\"className\":\"body-4 bold\",\"children\":\"Help and security\"}],[\"$\",\"ul\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__list\",\"children\":[[\"$\",\"li\",\"0\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/supported-countries\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Availability\"}]}],\"$L30\",\"$L31\"]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"2a:[\"$\",\"div\",\"3\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__columnSection\",\"children\":[[\"$\",\"div\",\"0\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__listSection\",\"children\":[[\"$\",\"h3\",null,{\"className\":\"body-4 bold\",\"children\":\"Company\"}],[\"$\",\"ul\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__list\",\"children\":[[\"$\",\"li\",\"0\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/company\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Anthropic\"}]}],[\"$\",\"li\",\"1\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/careers\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Careers\"}]}],[\"$\",\"li\",\"2\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/company/leadership\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Leadership\"}]}],[\"$\",\"li\",\"3\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/policy\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Policy\"}]}],[\"$\",\"li\",\"4\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/economic-futures\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Economic Futures\"}]}],[\"$\",\"li\",\"5\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/research\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Research\"}]}],[\"$\",\"li\",\"6\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/news\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"News\"}]}],[\"$\",\"li\",\"7\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/constitution\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Claude’s Constitution\"}]}],[\"$\",\"li\",\"8\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/claude-corps\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Claude Corps\"}]}],[\"$\",\"li\",\"9\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/path-to-hope\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Keep thinking\"}]}],[\"$\",\"li\",\"10\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/policy-on-the-ai-exponential\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Policy on the AI Exponential\"}]}],[\"$\",\"li\",\"11\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/news/announcing-our-updated-responsible-scaling-policy\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Responsible Scaling Policy\"}]}],[\"$\",\"li\",\"12\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://trust.anthropic.com/\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Security and compliance\"}]}],[\"$\",\"li\",\"13\",{\"children\":[\"$\",\"a\",null,{\"href\":\"/transparency\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Transparency\"}]}]]}]]}],[\"$\",\"div\",\"1\",{\"className\":\"SiteFooter-module-scss-module__JdOqwq__listSection\",\"children\":[[\"$\",\"h3\",null,{\"className\":\"body-4 bold\",\"children\":\"Terms and policies\"}],[\"$\",\"ul\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__list\",\"children\":[[\"$\",\"$L32\",\"0\",{}],[\"$\",\"li\",\"1\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/legal/privacy\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Privacy policy\"}]}],[\"$\",\"li\",\"2\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/legal/consumer-health-data-privacy-policy\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Consumer health data privacy policy\"}]}],[\"$\",\"li\",\"3\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/responsible-disclosure-policy\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Responsible disclosure policy\"}]}],[\"$\",\"li\",\"4\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/legal/commercial-terms\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Terms of service: Commercial\"}]}],[\"$\",\"li\",\"5\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/legal/consumer-terms\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Terms of service: Consumer\"}]}],[\"$\",\"li\",\"6\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://anthropic.com/legal/k12-terms\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Terms of Service: US K-12\"}]}],\"$L33\",\"$L34\"]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"2b:[\"$\",\"div\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__socialWrapper\",\"children\":[[\"$\",\"small\",null,{\"className\":\"body-4 SiteFooter-module-scss-module__JdOqwq__copyright\",\"role\":\"contentinfo\",\"children\":[\"$\",\"$L35\",null,{\"copyright\":\"© 2026 Anthropic PBC\",\"copyrightEu\":\"© 2026 Anthropic PBC. Services in the EU are provided by Anthropic Ireland Limited.\"}]}],[\"$\",\"ul\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__socialIcons\",\"role\":\"navigation\",\"aria-label\":\"Social media links\",\"children\":[[\"$\",\"li\",null,{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.linkedin.com/company/anthropicresearch\",\"aria-label\":\"Visit our LinkedIn page\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":[\"$\",\"$L36\",null,{\"fill\":\"#b0aea5\",\"aria-hidden\":\"true\",\"height\":24,\"width\":24}]}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"a\",null,{\"href\":\"https://x.com/AnthropicAI\",\"aria-label\":\"Visit our X (formerly Twitter) profile\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":[\"$\",\"$L37\",null,{\"fill\":\"#b0aea5\",\"aria-hidden\":\"true\",\"height\":24,\"width\":24}]}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.youtube.com/@anthropic-ai\",\"aria-label\":\"Visit our YouTube channel\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":[\"$\",\"$L38\",null,{\"fill\":\"#b0aea5\",\"aria-hidden\":\"true\",\"height\":24,\"width\":24}]}]}]]}]]}]\n2c:[\"$\",\"p\",null,{\"className\":\"body-3 serif FeaturedGrid-module-scss-module__W1FydW__body\",\"children\":\"Opus 5 is a step change improvement for the Opus tier powering long-running agents while delivering improvements in coding and professional work.\"}]\n2e:[\"$\",\"h3\",null,{\"className\":\"body-4 bold\",\"children\":\"Claude Platform\"}]\n"])</script><script>self.__next_f.push([1,"2f:[\"$\",\"ul\",null,{\"className\":\"SiteFooter-module-scss-module__JdOqwq__list\",\"children\":[[\"$\",\"li\",\"0\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/platform/api\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Overview\"}]}],[\"$\",\"li\",\"1\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://platform.claude.com/docs\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Developer docs\"}]}],[\"$\",\"li\",\"2\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/pricing#api\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Pricing\"}]}],[\"$\",\"li\",\"3\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/ecosystem\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Ecosystem\"}]}],[\"$\",\"li\",\"4\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/platform/marketplace\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Marketplace\"}]}],[\"$\",\"li\",\"5\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/regional-compliance\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Regional compliance\"}]}],[\"$\",\"li\",\"6\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/partners/claude-on-aws\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Claude on AWS\"}]}],[\"$\",\"li\",\"7\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/partners/google-cloud-vertex-ai\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Google Cloud\"}]}],[\"$\",\"li\",\"8\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://claude.com/partners/microsoft-foundry\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Microsoft Foundry\"}]}],[\"$\",\"li\",\"9\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://platform.claude.com/\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Console login\"}]}]]}]\n"])</script><script>self.__next_f.push([1,"30:[\"$\",\"li\",\"1\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://status.anthropic.com/\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Status\"}]}]\n31:[\"$\",\"li\",\"2\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://support.claude.com/en/\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"children\":\"Support center\"}]}]\n33:[\"$\",\"li\",\"7\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://anthropic.com/legal/k12-dpa\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Data Processing Agreement: US K-12\"}]}]\n34:[\"$\",\"li\",\"8\",{\"children\":[\"$\",\"a\",null,{\"href\":\"https://www.anthropic.com/legal/aup\",\"className\":\"SiteFooter-module-scss-module__JdOqwq__listItem body-4\",\"children\":\"Usage policy\"}]}]\n9:null\n"])</script><script>self.__next_f.push([1,"e:[[\"$\",\"title\",\"0\",{\"children\":\"Newsroom \\\\ Anthropic\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Anthropic is an AI safety and research company that's working to build reliable, interpretable, and steerable AI systems.\"}],[\"$\",\"meta\",\"2\",{\"name\":\"msapplication-TileColor\",\"content\":\"141413\"}],[\"$\",\"meta\",\"3\",{\"name\":\"msapplication-config\",\"content\":\"/browserconfig.xml\"}],[\"$\",\"link\",\"4\",{\"rel\":\"canonical\",\"href\":\"https://www.anthropic.com/news\"}],[\"$\",\"meta\",\"5\",{\"name\":\"google-site-verification\",\"content\":\"BqiAW_sWOg-KrPk-Accxm6ge9dtnFEyV6DB6vzVZSGs\"}],[\"$\",\"meta\",\"6\",{\"property\":\"og:title\",\"content\":\"Newsroom\"}],[\"$\",\"meta\",\"7\",{\"property\":\"og:description\",\"content\":\"Anthropic is an AI safety and research company that's working to build reliable, interpretable, and steerable AI systems.\"}],[\"$\",\"meta\",\"8\",{\"property\":\"og:image\",\"content\":\"https://cdn.sanity.io/images/4zrzovbb/website/6d4a0d28992ade92d6fa63646fd9c9d318245c6c-2400x1260.jpg\"}],[\"$\",\"meta\",\"9\",{\"property\":\"og:image:alt\",\"content\":\"Anthropic logo\"}],[\"$\",\"meta\",\"10\",{\"property\":\"og:type\",\"content\":\"website\"}],[\"$\",\"meta\",\"11\",{\"name\":\"twitter:card\",\"content\":\"summary_large_image\"}],[\"$\",\"meta\",\"12\",{\"name\":\"twitter:site\",\"content\":\"@AnthropicAI\"}],[\"$\",\"meta\",\"13\",{\"name\":\"twitter:creator\",\"content\":\"@AnthropicAI\"}],[\"$\",\"meta\",\"14\",{\"name\":\"twitter:title\",\"content\":\"Newsroom\"}],[\"$\",\"meta\",\"15\",{\"name\":\"twitter:description\",\"content\":\"Anthropic is an AI safety and research company that's working to build reliable, interpretable, and steerable AI systems.\"}],[\"$\",\"meta\",\"16\",{\"name\":\"twitter:image\",\"content\":\"https://cdn.sanity.io/images/4zrzovbb/website/6d4a0d28992ade92d6fa63646fd9c9d318245c6c-2400x1260.jpg\"}],[\"$\",\"meta\",\"17\",{\"name\":\"twitter:image:alt\",\"content\":\"Anthropic logo\"}],[\"$\",\"link\",\"18\",{\"rel\":\"shortcut icon\",\"href\":\"/favicon.ico\"}],[\"$\",\"link\",\"19\",{\"rel\":\"icon\",\"href\":\"/images/icons/favicon-32x32.png\"}],[\"$\",\"link\",\"20\",{\"rel\":\"apple-touch-icon\",\"href\":\"/images/icons/apple-touch-icon.png\"}],[\"$\",\"link\",\"21\",{\"rel\":\"apple-touch-icon\",\"href\":\"/images/icons/apple-touch-icon.png\",\"sizes\":\"180x180\"}],[\"$\",\"link\",\"22\",{\"rel\":\"mask-icon\",\"href\":\"/images/icons/safari-pinned-tab.svg\",\"color\":\"141413\"}],[\"$\",\"$L39\",\"23\",{}]]\n"])</script></body></html>
\ No newline at end of file
added tests/fixtures/anthropic/pricing.md +526 −0
@@ -0,0 +1,526 @@
1 +---
2 +title: Pricing
3 +url: https://platform.claude.com/docs/en/about-claude/pricing
4 +description: Learn about Anthropic's pricing structure for models and features
5 +---
6 +
7 +This page provides detailed pricing information for Anthropic's models and features. All prices are in USD.
8 +
9 +For the most current pricing information, visit [claude.com/pricing](https://claude.com/pricing).
10 +
11 +## Model pricing
12 +
13 +The following table shows pricing for all Claude models:
14 +
15 +| Model | Base input tokens | 5m cache writes | 1h cache writes | Cache hits and refreshes | Output tokens |
16 +| ------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | --------------- | --------------- | ------------------------ | ------------- |
17 +| Claude Fable 5.1 | $10 / MTok | $12.50 / MTok | $20 / MTok | $0.25 / MTok1 | $50 / MTok |
18 +| Claude Mythos 5.1 ([limited availability](https://anthropic.com/glasswing)) | $10 / MTok | $12.50 / MTok | $20 / MTok | $0.25 / MTok1 | $50 / MTok |
19 +| Claude Fable 5 | $10 / MTok | $12.50 / MTok | $20 / MTok | $1 / MTok | $50 / MTok |
20 +| Claude Mythos 5 ([limited availability](https://anthropic.com/glasswing)) | $10 / MTok | $12.50 / MTok | $20 / MTok | $1 / MTok | $50 / MTok |
21 +| Claude Opus 5 | $5 / MTok | $6.25 / MTok | $10 / MTok | $0.50 / MTok | $25 / MTok |
22 +| Claude Opus 4.8 | $5 / MTok | $6.25 / MTok | $10 / MTok | $0.50 / MTok | $25 / MTok |
23 +| Claude Opus 4.7 | $5 / MTok | $6.25 / MTok | $10 / MTok | $0.50 / MTok | $25 / MTok |
24 +| Claude Opus 4.6 | $5 / MTok | $6.25 / MTok | $10 / MTok | $0.50 / MTok | $25 / MTok |
25 +| Claude Opus 4.5 | $5 / MTok | $6.25 / MTok | $10 / MTok | $0.50 / MTok | $25 / MTok |
26 +| Claude Opus 4.1 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | $15 / MTok | $18.75 / MTok | $30 / MTok | $1.50 / MTok | $75 / MTok |
27 +| Claude Opus 4 ([retired, except on Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | $15 / MTok | $18.75 / MTok | $30 / MTok | $1.50 / MTok | $75 / MTok |
28 +| Claude Sonnet 5 | $2 / MTok | $2.50 / MTok | $4 / MTok | $0.20 / MTok | $10 / MTok |
29 +| Claude Sonnet 4.6 | $3 / MTok | $3.75 / MTok | $6 / MTok | $0.30 / MTok | $15 / MTok |
30 +| Claude Sonnet 4.5 | $3 / MTok | $3.75 / MTok | $6 / MTok | $0.30 / MTok | $15 / MTok |
31 +| Claude Sonnet 4 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | $3 / MTok | $3.75 / MTok | $6 / MTok | $0.30 / MTok | $15 / MTok |
32 +| Claude Haiku 4.5 | $1 / MTok | $1.25 / MTok | $2 / MTok | $0.10 / MTok | $5 / MTok |
33 +| Claude Haiku 3.5 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | $0.80 / MTok | $1 / MTok | $1.60 / MTok | $0.08 / MTok | $4 / MTok |
34 +
35 +*1 Cache hits and refreshes on Claude Fable 5.1 and Claude Mythos 5.1 are priced at 0.025x the base input price. All other models use the standard 0.1x multiplier.*
36 +
37 +<Note id="claude-sonnet-5-introductory-pricing">
38 + The $2/$10 per million input/output token pricing for Claude Sonnet 5, announced at launch as introductory pricing through August 31, 2026, is now the standard price. The previously scheduled increase to $3/$15 per million input/output tokens on September 1, 2026 will not occur.
39 +</Note>
40 +
41 +<Note>
42 + MTok = Million tokens. The "Base Input Tokens" column shows standard input pricing, the "5m Cache Writes", "1h Cache Writes", and "Cache Hits & Refreshes" columns are specific to [prompt caching](https://platform.claude.com/docs/en/about-claude/pricing#prompt-caching), and "Output Tokens" shows output pricing. See [prompt caching pricing](https://platform.claude.com/docs/en/about-claude/pricing#prompt-caching) for an explanation of the cache columns and pricing multipliers.
43 +</Note>
44 +
45 +<Note>
46 + Claude 4.7 and later models and Claude Mythos Preview use a newer tokenizer that contributes to their improved performance on a wide range of tasks. This tokenizer produces approximately 30% more tokens for the same text. The exact increase depends on the content and workload shape. Claude Sonnet 4.6 and earlier models use the previous tokenizer.
47 +</Note>
48 +
49 +For Claude Platform on AWS pricing, see [Claude Platform on AWS pricing](https://platform.claude.com/docs/en/about-claude/pricing#claude-platform-on-aws-pricing).
50 +
51 +## Cloud platform pricing
52 +
53 +This section covers partner-operated cloud platforms, where the cloud provider invoices you. For Anthropic-operated cloud platforms billed through a marketplace, see [Claude Platform on AWS pricing](https://platform.claude.com/docs/en/about-claude/pricing#claude-platform-on-aws-pricing) and [Claude in Microsoft Foundry pricing](https://platform.claude.com/docs/en/about-claude/pricing#claude-in-microsoft-foundry-pricing).
54 +
55 +Claude models are available on [Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock) and [Google Cloud](https://platform.claude.com/docs/en/build-with-claude/claude-on-vertex-ai). For official pricing, visit:
56 +
57 +* [Amazon Bedrock pricing](https://aws.amazon.com/bedrock/pricing/)
58 +* [Google Cloud pricing](https://cloud.google.com/vertex-ai/generative-ai/pricing#claude-models)
59 +
60 +<Note>
61 + **Regional and multi-region endpoint pricing for Claude 4.5 models and beyond**
62 +
63 + Starting with Claude Sonnet 4.5, Haiku 4.5, and Opus 4.5:
64 +
65 + * **Bedrock** offers two endpoint types: global endpoints (dynamic routing for maximum availability) and regional endpoints (guaranteed data routing through specific geographic regions).
66 + * **Google Cloud** offers three endpoint types: global endpoints, multi-region endpoints (dynamic routing within a geographic area), and regional endpoints.
67 +
68 + Regional and multi-region endpoints include a 10% premium over global endpoints. The Claude API (first-party) is global by default; for first-party data residency options and pricing, see [Data residency pricing](https://platform.claude.com/docs/en/about-claude/pricing#data-residency-pricing).
69 +
70 + **Scope:** This pricing structure applies to Claude Sonnet 4.5, Haiku 4.5, Opus 4.5, and all future models. Earlier models (Claude Opus 4.1 and prior releases) retain their existing pricing.
71 +
72 + For implementation details and code examples:
73 +
74 + * [Amazon Bedrock global vs regional endpoints](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock#regions) for Opus 4.7, Haiku 4.5, and later models, or [the legacy integration](https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy#global-vs-regional-endpoints) for all other models on Bedrock
75 + * [Google Cloud global, multi-region, and regional endpoints](https://platform.claude.com/docs/en/build-with-claude/claude-on-vertex-ai#global-multi-region-and-regional-endpoints)
76 +</Note>
77 +
78 +## Claude Platform on AWS pricing
79 +
80 +[Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws) bills through AWS Marketplace using Claude Consumption Units (CCUs). Anthropic rates your token usage in USD at standard per-model, per-feature rates, applies any negotiated discount, converts the result to CCUs at $0.01 per CCU, and reports the CCU quantity to AWS Marketplace hourly. Your AWS bill shows a single CCU line item.
81 +
82 +| Concept | Details |
83 +| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
84 +| **Billing unit** | Claude Consumption Unit (CCU) |
85 +| **CCU price** | $0.01 per CCU (fixed; discounts apply at token-to-CCU conversion, not to the CCU price) |
86 +| **Conversion** | Token usage rated in USD at standard per-model, per-feature rates (same as [Claude API pricing](https://platform.claude.com/docs/en/about-claude/pricing#model-pricing)), then converted to CCUs at $0.01 per CCU |
87 +| **Billing cadence** | Hourly metering to AWS Marketplace; monthly invoices |
88 +| **Payment model** | Arrears only (postpaid); no prepaid credits |
89 +| **Discounts** | Applied as fewer CCUs metered |
90 +| **Tax** | Pre-tax metering; AWS Marketplace handles tax |
91 +| **Cost visibility** | Real-time breakdown in the Claude Console (access through the AWS Console); AWS Cost Explorer shows aggregated CCU |
92 +
93 +<Note>
94 + **Claude Consumption Units.** If Customer accesses the Services through certain Marketplace Platforms (e.g., Claude Platform on AWS), usage will be invoiced in Claude Consumption Units ("CCU") rather than per MTok. A CCU is a unit of measure used solely for Marketplace Platform invoicing. One hundred (100) CCU represents $1.00 USD of fees owed for the Services, calculated at the applicable prices on [claude.com/pricing#api](https://claude.com/pricing#api), after application of any discounts.
95 +</Note>
96 +
97 +### Inference geography
98 +
99 +For Claude 4.6 and later models, using `inference_geo: "us"` applies a 1.1x pricing multiplier. `inference_geo: "global"` (default) uses standard pricing. See [Data residency](https://platform.claude.com/docs/en/manage-claude/data-residency) for details.
100 +
101 +### Private offers
102 +
103 +When you sign up on the AWS Console **Claude Platform on AWS** service page, the AWS Console looks up any private offer associated with your account and prompts you to accept it in AWS Marketplace. Contact your Anthropic account representative for private offer terms.
104 +
105 +<Note>
106 + If you have an existing Amazon Bedrock private offer, contact your Anthropic or AWS account representative before getting started with Claude Platform on AWS to ensure your discounts are applied correctly. Discounts cannot be applied retroactively to usage incurred before your private offer is accepted.
107 +</Note>
108 +
109 +## Claude in Microsoft Foundry pricing
110 +
111 +[Claude in Microsoft Foundry](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry) bills through the Azure Marketplace using Claude Consumption Units (CCUs). Anthropic rates your token usage in USD at standard per-model, per-feature rates, applies any negotiated discount, converts the result to CCUs at $0.01 per CCU, and reports the CCU quantity to the Azure Marketplace hourly. Your Azure bill shows a single CCU line item.
112 +
113 +| Concept | Details |
114 +| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
115 +| **Billing unit** | Claude Consumption Unit (CCU) |
116 +| **CCU price** | $0.01 per CCU (fixed; discounts apply at token-to-CCU conversion, not to the CCU price) |
117 +| **Conversion** | Token usage rated in USD at standard per-model, per-feature rates (same as [Claude API pricing](https://platform.claude.com/docs/en/about-claude/pricing#model-pricing)), then converted to CCUs at $0.01 per CCU |
118 +| **Billing cadence** | Hourly metering to the Azure Marketplace; monthly invoices |
119 +| **Payment model** | Arrears only (postpaid); no prepaid credits |
120 +| **Discounts** | Applied as fewer CCUs metered |
121 +| **Tax** | Pre-tax metering; Azure Marketplace handles tax |
122 +| **Cost visibility** | Azure Cost Management shows aggregated CCU |
123 +
124 +<Note>
125 + **Claude Consumption Units.** If Customer accesses the Services through certain Marketplace Platforms (e.g., Claude Platform on AWS, Claude in Microsoft Foundry), usage will be invoiced in Claude Consumption Units ("CCU") rather than per MTok. A CCU is a unit of measure used solely for Marketplace Platform invoicing. One hundred (100) CCU represents $1.00 USD of fees owed for the Services, calculated at the applicable prices on [claude.com/pricing#api](https://claude.com/pricing#api), after application of any discounts.
126 +</Note>
127 +
128 +### Inference geography
129 +
130 +Deployments hosted on Azure can use the US Data Zone Standard deployment type, which keeps inference within the United States. This is equivalent to `inference_geo: "us"` on the Claude API and applies the same 1.1x pricing multiplier. See [Data residency](https://platform.claude.com/docs/en/manage-claude/data-residency) for details.
131 +
132 +## Feature-specific pricing
133 +
134 +### Prompt caching
135 +
136 +Prompt caching reduces costs and latency by reusing previously processed portions of your prompt across API calls. Instead of reprocessing the same large system prompt, document, or conversation history on every request, the API reads from cache at a fraction of the standard input price.
137 +
138 +There are two ways to enable prompt caching:
139 +
140 +* **Automatic caching:** Add a single `cache_control` field at the top level of your request. The system automatically manages cache breakpoints as conversations grow. This is the recommended starting point for most use cases.
141 +* **Explicit cache breakpoints:** Place `cache_control` directly on individual content blocks for fine-grained control over exactly what gets cached.
142 +
143 +Prompt caching uses the following pricing multipliers relative to base input token rates:
144 +
145 +| Cache operation | Multiplier | Duration |
146 +| -------------------- | ------------------------------------------------------------------------ | ------------------------------------ |
147 +| 5-minute cache write | 1.25x base input price | Cache valid for 5 minutes |
148 +| 1-hour cache write | 2x base input price | Cache valid for 1 hour |
149 +| Cache read (hit) | 0.1x base input price (0.025x on Claude Fable 5.1 and Claude Mythos 5.1) | Same duration as the preceding write |
150 +
151 +Cache write tokens are charged when content is first stored. Cache read tokens are charged when a subsequent request retrieves the cached content. A cache hit costs 10% of the standard input price, which means caching pays off after one cache read for the 5-minute duration (1.25x write), or after two cache reads for the 1-hour duration (2x write). On Claude Fable 5.1 and Claude Mythos 5.1, a cache hit costs 2.5% of the standard input price ($0.25 USD per million tokens).
152 +
153 +These multipliers stack with other pricing modifiers, including the Batch API discount and data residency.
154 +
155 +For implementation details, supported models, and code examples, see [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching).
156 +
157 +### Data residency pricing
158 +
159 +For Claude 4.6 and later models, specifying US-only inference through the `inference_geo` parameter incurs a 1.1x multiplier on all token pricing categories, including input tokens, output tokens, cache writes, and cache reads. Global routing (the default) uses standard pricing.
160 +
161 +This applies to the Claude API (first-party) and Claude Platform on AWS. On Claude in Microsoft Foundry, the same 1.1x multiplier applies to deployments that use the US Data Zone Standard deployment type (see [Inference geography](https://platform.claude.com/docs/en/about-claude/pricing#foundry-inference-geography)). Partner-operated platforms (Bedrock and Google Cloud) have independent regional pricing. See [Bedrock](https://aws.amazon.com/bedrock/pricing/) and [Google Cloud](https://cloud.google.com/vertex-ai/generative-ai/pricing#claude-models) for details. Earlier models do not support the `inference_geo` parameter and always use standard pricing; requests that include the parameter on these models return a 400 error.
162 +
163 +For more information, see [Data residency](https://platform.claude.com/docs/en/manage-claude/data-residency).
164 +
165 +### Fast mode pricing
166 +
167 +[Fast mode](https://platform.claude.com/docs/en/build-with-claude/fast-mode), in research preview, provides significantly faster output for Claude Opus 5 and Claude Opus 4.8 at premium pricing. Fast mode pricing applies across the full context window, including requests over 200k input tokens. Fast mode is available on the Claude API (first-party) only; it is not available on Claude Platform on AWS or partner-operated cloud platforms.
168 +
169 +| Model | Input | Output |
170 +| ------------------------------- | ---------- | ---------- |
171 +| Claude Opus 5 / Claude Opus 4.8 | $10 / MTok | $50 / MTok |
172 +
173 +Fast mode is not available on Claude Opus 4.7 (requests with `speed: "fast"` return an error) or Claude Opus 4.6 (requests run at standard speed and are billed at standard rates). See [Fast mode](https://platform.claude.com/docs/en/build-with-claude/fast-mode#supported-models).
174 +
175 +Fast mode pricing stacks with other pricing modifiers:
176 +
177 +* [Prompt caching multipliers](https://platform.claude.com/docs/en/about-claude/pricing#prompt-caching) apply on top of fast mode pricing
178 +* [Data residency](https://platform.claude.com/docs/en/manage-claude/data-residency) multipliers apply on top of fast mode pricing
179 +
180 +Fast mode is not available with the [Batch API](https://platform.claude.com/docs/en/about-claude/pricing#batch-processing).
181 +
182 +For more information, see [Fast mode](https://platform.claude.com/docs/en/build-with-claude/fast-mode).
183 +
184 +### Batch processing
185 +
186 +The Batch API allows asynchronous processing of large volumes of requests with a 50% discount on both input and output tokens.
187 +
188 +| Model | Batch input | Batch output |
189 +| ------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------------- |
190 +| Claude Fable 5.1 | $5 / MTok | $25 / MTok |
191 +| Claude Mythos 5.1 ([limited availability](https://anthropic.com/glasswing)) | $5 / MTok | $25 / MTok |
192 +| Claude Fable 5 | $5 / MTok | $25 / MTok |
193 +| Claude Mythos 5 ([limited availability](https://anthropic.com/glasswing)) | $5 / MTok | $25 / MTok |
194 +| Claude Opus 5 | $2.50 / MTok | $12.50 / MTok |
195 +| Claude Opus 4.8 | $2.50 / MTok | $12.50 / MTok |
196 +| Claude Opus 4.7 | $2.50 / MTok | $12.50 / MTok |
197 +| Claude Opus 4.6 | $2.50 / MTok | $12.50 / MTok |
198 +| Claude Opus 4.5 | $2.50 / MTok | $12.50 / MTok |
199 +| Claude Opus 4.1 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | $7.50 / MTok | $37.50 / MTok |
200 +| Claude Opus 4 ([retired, except on Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | $7.50 / MTok | $37.50 / MTok |
201 +| Claude Sonnet 5 | $1 / MTok | $5 / MTok |
202 +| Claude Sonnet 4.6 | $1.50 / MTok | $7.50 / MTok |
203 +| Claude Sonnet 4.5 | $1.50 / MTok | $7.50 / MTok |
204 +| Claude Sonnet 4 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | $1.50 / MTok | $7.50 / MTok |
205 +| Claude Haiku 4.5 | $0.50 / MTok | $2.50 / MTok |
206 +| Claude Haiku 3.5 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | $0.40 / MTok | $2 / MTok |
207 +
208 +For more information about batch processing, see [Batch processing](https://platform.claude.com/docs/en/build-with-claude/batch-processing).
209 +
210 +### Long context pricing
211 +
212 +Claude 4.6 and later models and [Claude Mythos Preview](https://anthropic.com/glasswing) include the full [1M token context window](https://platform.claude.com/docs/en/build-with-claude/context-windows) at standard pricing. (A 900k-token request is billed at the same per-token rate as a 9k-token request.) Prompt caching and batch processing discounts apply at standard rates across the full context window.
213 +
214 +### Tool use pricing
215 +
216 +Tool use requests are priced based on:
217 +
218 +1. The total number of input tokens sent to the model (including in the `tools` parameter)
219 +2. The number of output tokens generated
220 +3. For server-side tools, additional usage-based pricing (for example, web search charges per search performed)
221 +
222 +Client-side tools are priced the same as any other Claude API request, although server-side tools can incur additional charges based on their specific usage.
223 +
224 +The additional tokens from tool use come from:
225 +
226 +* The `tools` parameter in API requests (tool names, descriptions, and schemas)
227 +* `tool_use` content blocks in API requests and responses
228 +* `tool_result` content blocks in API requests
229 +
230 +When you use `tools`, the API also automatically includes a special system prompt for the model that enables tool use. The number of tool use tokens required for each model is listed in the following table (excluding the additional tokens listed earlier). Note that the table assumes at least 1 tool is provided. If no `tools` are provided, then a tool choice of `none` uses 0 additional system prompt tokens.
231 +
232 +| Model | Tool choice | Tool use system prompt token count |
233 +| ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ---------------------------------- |
234 +| Claude Opus 5 | `auto`, `none`***`any`, `tool` | 286 tokens***406 tokens |
235 +| Claude Opus 4.8 | `auto`, `none`***`any`, `tool` | 290 tokens***410 tokens |
236 +| Claude Opus 4.7 | `auto`, `none`***`any`, `tool` | 675 tokens***804 tokens |
237 +| Claude Opus 4.6 | `auto`, `none`***`any`, `tool` | 497 tokens***589 tokens |
238 +| Claude Opus 4.5 | `auto`, `none`***`any`, `tool` | 496 tokens***588 tokens |
239 +| Claude Opus 4.1 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | `auto`, `none`***`any`, `tool` | 313 tokens***315 tokens |
240 +| Claude Opus 4 ([retired, except on Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | `auto`, `none`***`any`, `tool` | 313 tokens***315 tokens |
241 +| Claude Sonnet 5 | `auto`, `none`***`any`, `tool` | 354 tokens***474 tokens |
242 +| Claude Sonnet 4.6 | `auto`, `none`***`any`, `tool` | 497 tokens***589 tokens |
243 +| Claude Sonnet 4.5 | `auto`, `none`***`any`, `tool` | 496 tokens***588 tokens |
244 +| Claude Sonnet 4 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | `auto`, `none`***`any`, `tool` | 313 tokens***315 tokens |
245 +| Claude Haiku 4.5 | `auto`, `none`***`any`, `tool` | 496 tokens***588 tokens |
246 +| Claude Haiku 3.5 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | `auto`, `none`***`any`, `tool` | 264 tokens***355 tokens |
247 +
248 +These token counts are added to your normal input and output tokens to calculate the total cost of a request.
249 +
250 +For current per-model prices, refer to the [model pricing](https://platform.claude.com/docs/en/about-claude/pricing#model-pricing) section.
251 +
252 +For more information about tool use implementation and best practices, see [Tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview).
253 +
254 +### Specific tool pricing
255 +
256 +#### Bash tool
257 +
258 +The bash tool definition adds the following input tokens to your request. This is in addition to the per-model [tool use system prompt](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview#pricing) that applies whenever any tool is present.
259 +
260 +| Model | Additional input tokens |
261 +| --------------------------------------------------- | ----------------------- |
262 +| Claude Opus 5, Claude Opus 4.8, and Claude Opus 4.7 | 325 tokens |
263 +| Claude Opus 4.6, Claude Sonnet 4.6, and earlier | 244 tokens |
264 +
265 +Additional tokens are consumed by:
266 +
267 +* Command outputs (stdout/stderr)
268 +* Error messages
269 +* Large file contents
270 +
271 +See [tool use pricing](https://platform.claude.com/docs/en/about-claude/pricing#tool-use-pricing) for complete pricing details.
272 +
273 +#### Code execution tool
274 +
275 +**Code execution is free when used with web search or web fetch.** When `web_search_20260209` (or later) or `web_fetch_20260209` (or later) is included in your API request, there are no additional charges for code execution tool calls beyond the standard input and output token costs.
276 +
277 +When used without these tools, code execution is billed by execution time, tracked separately from token usage:
278 +
279 +* Execution time has a minimum of 5 minutes
280 +* Each organization receives **1,550 free hours** of usage per month
281 +* Additional usage beyond 1,550 hours is billed at **$0.05 USD per hour, per container**
282 +* If files are included in the request, execution time is billed even if the tool is not called, because files are preloaded onto the container
283 +
284 +Code execution usage is tracked in the response:
285 +
286 +```json
287 +{
288 + "usage": {
289 + "input_tokens": 105,
290 + "output_tokens": 239,
291 + "server_tool_use": {
292 + "code_execution_requests": 1
293 + }
294 + }
295 +}
296 +```
297 +
298 +#### Text editor tool
299 +
300 +The text editor tool uses the same pricing structure as other tools used with Claude. It follows the standard input and output token pricing based on the Claude model you're using.
301 +
302 +In addition to the base tokens, the following additional input tokens are needed for the text editor tool:
303 +
304 +| Tool | Additional input tokens |
305 +| ----------------------------------- | ----------------------- |
306 +| `text_editor_20250429` (Claude 4.x) | 700 tokens |
307 +
308 +See [tool use pricing](https://platform.claude.com/docs/en/about-claude/pricing#tool-use-pricing) for complete pricing details.
309 +
310 +#### Web search tool
311 +
312 +Web search usage is charged in addition to token usage:
313 +
314 +```json
315 +{
316 + "usage": {
317 + "input_tokens": 105,
318 + "output_tokens": 6039,
319 + "cache_read_input_tokens": 7123,
320 + "cache_creation_input_tokens": 7345,
321 + "server_tool_use": {
322 + "web_search_requests": 1
323 + }
324 + }
325 +}
326 +```
327 +
328 +Web search is available on the Claude API for **$10 per 1,000 searches**, plus standard token costs for search-generated content. Web search results retrieved throughout a conversation are counted as input tokens, in search iterations executed during a single turn and in subsequent conversation turns.
329 +
330 +Each web search counts as one use, regardless of the number of results returned. If an error occurs during web search, the web search will not be billed.
331 +
332 +#### Web fetch tool
333 +
334 +Web fetch usage has **no additional charges** beyond standard token costs:
335 +
336 +```json
337 +{
338 + "usage": {
339 + "input_tokens": 25039,
340 + "output_tokens": 931,
341 + "cache_read_input_tokens": 0,
342 + "cache_creation_input_tokens": 0,
343 + "server_tool_use": {
344 + "web_fetch_requests": 1
345 + }
346 + }
347 +}
348 +```
349 +
350 +The web fetch tool is available on the Claude API at **no additional cost**. You only pay standard token costs for the fetched content that becomes part of your conversation context.
351 +
352 +To protect against inadvertently fetching large content that would consume excessive tokens, use the `max_content_tokens` parameter to set appropriate limits based on your use case and budget considerations.
353 +
354 +Example token usage for typical content:
355 +
356 +* Average web page (10 kB): \~2,500 tokens
357 +* Large documentation page (100 kB): \~25,000 tokens
358 +* Research paper PDF (500 kB): \~125,000 tokens
359 +
360 +#### Computer use tool
361 +
362 +Computer use follows the standard [tool use pricing](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview#pricing). When using the computer use tool:
363 +
364 +**Toolset definition overhead:** Declaring `computer_toolset_20260801` with its default members adds about 4,500 input tokens to a request (about 4,520 on Claude Fable 5, Claude Mythos 5, Claude Opus 5, and Claude Opus 4.8, and about 4,590 on Claude Sonnet 5), which covers the member tool definitions and the tool use system prompt. Disabling `zoom` with `configs` removes about 410 of those tokens. The exact count for a request is reported in the response `usage`, and you can estimate it in advance with the [token counting endpoint](https://platform.claude.com/docs/en/build-with-claude/token-counting).
365 +
366 +**Earlier tool versions:** The following figures apply to the `computer_20251124` and `computer_20250124` tool versions, not to `computer_toolset_20260801`:
367 +
368 +* System prompt overhead: 466–499 tokens added to the system prompt
369 +* Tool definition: about 735 input tokens per tool definition (measured with `computer_20250124`)
370 +
371 +**Additional token consumption:**
372 +
373 +* Screenshot and zoom images returned in tool results, billed as image input (see [Vision pricing](https://platform.claude.com/docs/en/build-with-claude/vision#evaluate-image-size))
374 +* Tool execution results returned to Claude
375 +
376 +<Note>
377 + If you're also using bash or text editor tools alongside computer use, those tools have their own token costs as documented in their respective pages.
378 +</Note>
379 +
380 +#### Browser use tool
381 +
382 +Browser use follows the standard [tool use pricing](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview#pricing). When using the browser use tool:
383 +
384 +**Toolset definition overhead:** Declaring `browser_toolset_20260801` with its default members adds about 6,600 input tokens to a request (about 6,610 on Claude Fable 5, Claude Mythos 5, Claude Opus 5, and Claude Opus 4.8, and about 6,670 on Claude Sonnet 5), which covers the member tool definitions and the tool use system prompt. Enabling all four optional members adds about 880 tokens, and disabling members with `configs` reduces the count. The exact count for a request is reported in the response `usage`, and you can estimate it in advance with the [token counting endpoint](https://platform.claude.com/docs/en/build-with-claude/token-counting).
385 +
386 +**Additional token consumption:**
387 +
388 +* Screenshot and zoom images returned in tool results, billed as image input (see [Vision pricing](https://platform.claude.com/docs/en/build-with-claude/vision#evaluate-image-size))
389 +* Text tool results returned to Claude, such as accessibility trees, page text, and console or network entries
390 +
391 +<Note>
392 + If you also use the computer use tool, bash tool, text editor tool, or your own tools alongside browser use, those tools have their own token costs as documented on their respective pages.
393 +</Note>
394 +
395 +## Claude Managed Agents pricing
396 +
397 +[Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview) is billed on two dimensions: tokens and session runtime.
398 +
399 +### Tokens
400 +
401 +All tokens consumed by a Claude Managed Agents session are billed at the rates shown in [Model pricing](https://platform.claude.com/docs/en/about-claude/pricing#model-pricing). [Prompt caching](https://platform.claude.com/docs/en/about-claude/pricing#prompt-caching) multipliers apply identically. Web search triggered inside a session incurs the standard $10 per 1,000 searches. On [Claude Platform on AWS](https://platform.claude.com/docs/en/about-claude/pricing#claude-platform-on-aws-pricing), session token and runtime charges convert to Claude Consumption Units at the standard rate. [Fast mode](https://platform.claude.com/docs/en/about-claude/pricing#fast-mode-pricing) premium pricing applies when an agent's `model.speed` is set to `"fast"`.
402 +
403 +The [data residency multiplier](https://platform.claude.com/docs/en/about-claude/pricing#data-residency-pricing) also applies: when an agent's `model.inference_geo` is pinned to `"us"`, tokens consumed by sessions running that agent are billed at 1.1x the standard rates, the same multiplier that applies to US-only inference on the Messages API.
404 +
405 +The following Messages API modifiers do **not** apply to Claude Managed Agents sessions:
406 +
407 +| Modifier | Why it doesn't apply |
408 +| --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
409 +| [Batch API discount](https://platform.claude.com/docs/en/about-claude/pricing#batch-processing) | Sessions are stateful and interactive. There is no batch mode. |
410 +| [Cloud platform pricing](https://platform.claude.com/docs/en/about-claude/pricing#cloud-platform-pricing) | Not available on partner-operated cloud platforms. |
411 +
412 +### Session runtime
413 +
414 +| SKU | Rate | Metering |
415 +| --------------- | ---------------------- | ------------------------- |
416 +| Session runtime | $0.08 per session-hour | `running` status duration |
417 +
418 +Runtime is measured to the millisecond and accrues only while the session's status is `running`. Time spent `idle` (waiting for your next message or a tool confirmation), `rescheduling`, or `terminated` does not count toward runtime.
419 +
420 +<Note>
421 + Session runtime replaces the [code execution](https://platform.claude.com/docs/en/about-claude/pricing#code-execution-tool) container-hour billing model when using Claude Managed Agents. You are not separately billed for container hours on top of session runtime.
422 +</Note>
423 +
424 +### Worked example
425 +
426 +A one-hour coding session using Claude Opus 5 that consumes 50,000 input tokens and 15,000 output tokens:
427 +
428 +| Line item | Calculation | Cost |
429 +| --------------- | ------------------------ | ---------- |
430 +| Input tokens | 50,000 × $5 / 1,000,000 | $0.25 |
431 +| Output tokens | 15,000 × $25 / 1,000,000 | $0.375 |
432 +| Session runtime | 1.0 hour × $0.08 | $0.08 |
433 +| **Total** | | **$0.705** |
434 +
435 +If prompt caching is active and 40,000 of the input tokens are cache reads:
436 +
437 +| Line item | Calculation | Cost |
438 +| --------------------- | ----------------------------- | ---------- |
439 +| Uncached input tokens | 10,000 × $5 / 1,000,000 | $0.05 |
440 +| Cache read tokens | 40,000 × $5 × 0.1 / 1,000,000 | $0.02 |
441 +| Output tokens | 15,000 × $25 / 1,000,000 | $0.375 |
442 +| Session runtime | 1.0 hour × $0.08 | $0.08 |
443 +| **Total** | | **$0.525** |
444 +
445 +<Note>
446 + Example calculation for processing 10,000 support tickets:
447 +
448 + * Average \~3,700 tokens per conversation
449 + * Using Claude Haiku 4.5 at $1/MTok input, $5/MTok output
450 + * Total cost: \~$37.00 per 10,000 tickets
451 +</Note>
452 +
453 +For a detailed walkthrough of this calculation, see the [customer support agent guide](https://platform.claude.com/docs/en/about-claude/use-case-guides/customer-support-chat).
454 +
455 +## Additional pricing considerations
456 +
457 +### Cost optimization strategies
458 +
459 +When building agents with Claude:
460 +
461 +1. **Use appropriate models:** Choose Haiku for simple tasks, Sonnet for most production workloads, and Opus for the most complex reasoning
462 +2. **Implement prompt caching:** Reduce costs for repeated context
463 +3. **Batch operations:** Use the Batch API for non-time-sensitive tasks
464 +4. **Monitor usage patterns:** Track token consumption to identify optimization opportunities
465 +
466 +<Tip>
467 + For high-volume agent applications, contact the [enterprise sales team](https://claude.com/contact-sales) for custom pricing arrangements.
468 +</Tip>
469 +
470 +### Rate limits
471 +
472 +Rate limits vary by usage tier and affect how many requests you can make:
473 +
474 +* **Start tier:** Entry-level limits for getting started
475 +* **Build tier:** Increased limits for growing applications
476 +* **Scale tier:** Highest standard limits for production workloads
477 +
478 +For detailed rate limit information, see [Rate limits](https://platform.claude.com/docs/en/api/rate-limits).
479 +
480 +For limits beyond the Scale tier or custom pricing arrangements, [contact the sales team](https://claude.com/contact-sales).
481 +
482 +### Volume discounts
483 +
484 +Volume discounts may be available for high-volume users. These are negotiated on a case-by-case basis.
485 +
486 +* Standard usage tiers use the pricing shown in [Model pricing](https://platform.claude.com/docs/en/about-claude/pricing#model-pricing)
487 +* Enterprise customers can [contact sales](mailto:sales@anthropic.com) for custom pricing
488 +* Academic and research discounts may be available
489 +
490 +### Enterprise pricing
491 +
492 +For enterprise customers with specific needs:
493 +
494 +* Custom rate limits
495 +* Volume discounts
496 +* Dedicated support
497 +* Custom terms
498 +
499 +Contact the sales team at [sales@anthropic.com](mailto:sales@anthropic.com) or through the [Claude Console](https://platform.claude.com/settings/limits) to discuss enterprise pricing options.
500 +
501 +## Billing and payment
502 +
503 +* Billing is based on actual monthly usage
504 +* All payments are in USD
505 +* Credit card and invoicing options available
506 +* Usage tracking available in the [Claude Console](https://platform.claude.com/)
507 +
508 +## Frequently asked questions
509 +
510 +### How is token usage calculated?
511 +
512 +Tokens are pieces of text that models process. As a rough estimate, 1 token is approximately 4 characters or 0.75 words in English. The exact count varies by language and content type.
513 +
514 +### Are there free tiers or trials?
515 +
516 +New users receive a small amount of free credits to test the API. [Contact sales](mailto:sales@anthropic.com) for information about extended trials for enterprise evaluation.
517 +
518 +### How do discounts stack?
519 +
520 +Batch API and prompt caching discounts can be combined. For example, using both features together provides significant cost savings compared to standard API calls. See [prompt caching pricing](https://platform.claude.com/docs/en/about-claude/pricing#prompt-caching) for how the multipliers interact.
521 +
522 +### What payment methods are accepted?
523 +
524 +Major credit cards are accepted for standard accounts. Enterprise customers can arrange invoicing and other payment methods.
525 +
526 +For additional questions about pricing, contact [support@anthropic.com](mailto:support@anthropic.com).
added tests/test_anthropic.py +63 −0
@@ -0,0 +1,63 @@
1 +import pytest
2 +
3 +from aiatlas.connectors.labs.anthropic import AnthropicConnector, _display_name, _name_variants
4 +from aiatlas.sdk.facts import Target
5 +from tests.conftest import claims_of, entity_names, extract_from_fixture, fixture_path
6 +
7 +
8 +@pytest.fixture
9 +def connector() -> AnthropicConnector:
10 + return AnthropicConnector()
11 +
12 +
13 +async def test_models_overview(connector):
14 + target = Target(url="https://docs.claude.com/en/docs/about-claude/models/overview.md", doc_type="model_docs", key="models")
15 + facts = await extract_from_fixture(connector, target, fixture_path("anthropic", "models-overview.md"), content_type="text/markdown")
16 + models = entity_names(facts, "model")
17 + assert {"Claude Opus 5", "Claude Sonnet 5", "Claude Haiku 4.5"} <= models
18 + opus = claims_of(facts, "Claude Opus 5")
19 + assert opus["context_length"] == 1_000_000 and opus["max_output_tokens"] == 128_000
20 + assert opus["api_model_id"] == "claude-opus-5" and opus["openness"] == "proprietary"
21 + assert opus["knowledge_cutoff"] == "2026-05" and opus["retirement_date"] == "2027-07-24" and opus["retirement_tentative"] is True
22 + haiku = claims_of(facts, "Claude Haiku 4.5")
23 + assert haiku["context_length"] == 200_000 and haiku["api_model_id"] == "claude-haiku-4-5-20251001"
24 + assert any(t.doc_type == "model_page" for t in facts.targets)
25 + assert any(r.predicate == "develops" for r in facts.relations)
26 +
27 +
28 +async def test_pricing(connector):
29 + target = Target(url="https://docs.claude.com/en/docs/about-claude/pricing.md", doc_type="pricing", key="pricing")
30 + facts = await extract_from_fixture(connector, target, fixture_path("anthropic", "pricing.md"), content_type="text/markdown")
31 + by_model = {p.model.name: p for p in facts.prices}
32 + assert by_model["Claude Opus 5"].input_per_mtok == 5 and by_model["Claude Opus 5"].output_per_mtok == 25
33 + assert by_model["Claude Opus 5"].cached_input_per_mtok == 0.5 and by_model["Claude Opus 5"].cache_write_per_mtok == 6.25
34 + assert by_model["Claude Haiku 3.5"].input_per_mtok == 0.8
35 + assert claims_of(facts, "Claude Opus 4.1")["status"] == "retired"
36 + assert claims_of(facts, "Claude Mythos 5.1")["status"] == "limited-availability"
37 + assert len(facts.prices) >= 15
38 +
39 +
40 +async def test_deprecations(connector):
41 + target = Target(url="https://docs.claude.com/en/docs/about-claude/model-deprecations.md", doc_type="model_docs", key="deprecations")
42 + facts = await extract_from_fixture(connector, target, fixture_path("anthropic", "model-deprecations.md"), content_type="text/markdown")
43 + sonnet37 = claims_of(facts, "Claude 3.7 Sonnet")
44 + assert sonnet37["status"] == "retired" and sonnet37["deprecation_date"] == "2025-10-28" and sonnet37["retirement_date"] == "2026-02-19"
45 + opus5 = claims_of(facts, "Claude Opus 5")
46 + assert opus5["status"] == "active" and opus5["retirement_tentative"] is True
47 +
48 +
49 +async def test_news(connector):
50 + target = Target(url="https://www.anthropic.com/news", doc_type="listing", key="news")
51 + facts = await extract_from_fixture(connector, target, fixture_path("anthropic", "news.html"))
52 + events = [e for e in facts.events if e.event_type == "ANNOUNCEMENT"]
53 + assert len(events) >= 8
54 + opus = next(e for e in events if "Opus 5" in e.summary)
55 + assert opus.effective_at is not None and opus.effective_at.year == 2026 and opus.category == "release"
56 + assert any(t.needs_llm for t in facts.targets)
57 +
58 +
59 +def test_display_name():
60 + assert _display_name("claude-opus-4-5-20251101") == "Claude Opus 4.5"
61 + assert _display_name("claude-3-7-sonnet-20250219") == "Claude 3.7 Sonnet"
62 + assert _display_name("claude-fable-5-1") == "Claude Fable 5.1"
63 + assert _name_variants("Claude 3.5 Haiku") == ["Claude Haiku 3.5"]
added tests/test_extract.py +76 −0
@@ -0,0 +1,76 @@
1 +from datetime import date
2 +
3 +from aiatlas.ids import kind_of, new_id, normalize_alias, slugify
4 +from aiatlas.sdk.extract.dates import parse_date, parse_datetime
5 +from aiatlas.sdk.extract.html import parse_html
6 +from aiatlas.sdk.extract.markdown import parse_markdown
7 +from aiatlas.sdk.extract.numbers import parse_active_params, parse_context_length, parse_money_per_mtok, parse_param_count, parse_percent
8 +from aiatlas.sdk.fetch import canonicalize_url
9 +from aiatlas.services.search import compile_query
10 +
11 +
12 +def test_ids_and_slugs():
13 + mid = new_id("model")
14 + assert mid.startswith("model_") and kind_of(mid) == "model"
15 + assert slugify("Qwen3-235B-A22B") == "qwen3-235b-a22b"
16 + assert slugify("GPT-4.1 mini") == "gpt-4.1-mini"
17 + assert normalize_alias("Claude 3.5 Haiku") == normalize_alias("claude-3-5-haiku") == "claude35haiku"
18 +
19 +
20 +def test_numbers():
21 + assert parse_param_count("Qwen3-235B-A22B") == 235_000_000_000
22 + assert parse_active_params("Qwen3-235B-A22B") == 22_000_000_000
23 + assert parse_param_count("a 7.6 billion parameters model") == 7_600_000_000
24 + assert parse_param_count("Llama 3.1 8B Instruct") == 8_000_000_000
25 + assert parse_param_count("version 2.0") is None
26 + assert parse_context_length("128K tokens") == 128_000
27 + assert parse_context_length("1M") == 1_000_000
28 + assert parse_context_length("200,000 tokens") == 200_000
29 + assert parse_context_length("32768") == 32768
30 + assert parse_money_per_mtok("$3.00 / 1M tokens") == 3.0
31 + assert parse_money_per_mtok("$0.15/M") == 0.15
32 + assert parse_money_per_mtok("$2 per 1K tokens") == 2000.0
33 + assert parse_percent("72.4%") == 72.4
34 +
35 +
36 +def test_dates():
37 + assert parse_datetime("2026-07-24T10:00:00Z").year == 2026
38 + assert parse_date("July 24, 2026") == (date(2026, 7, 24), "day")
39 + assert parse_date("March 2025") == (date(2025, 3, 1), "month")
40 + assert parse_date("2024") == (date(2024, 1, 1), "year")
41 + assert parse_date("") == (None, "none")
42 +
43 +
44 +def test_canonical_url():
45 + assert canonicalize_url("https://Example.com/a/?utm_source=x&b=1#frag") == "https://example.com/a?b=1"
46 + assert canonicalize_url("https://example.com/") == "https://example.com/"
47 +
48 +
49 +def test_html_parse():
50 + html = """<html lang="en"><head><title>T</title><meta name="description" content="D"><link rel="canonical" href="/c">
51 + <script type="application/ld+json">{"@type":"Organization","name":"X"}</script>
52 + <script id="__NEXT_DATA__" type="application/json">{"props":{"models":[{"id":"m1"}]}}</script></head>
53 + <body><h1>Head</h1><table><tr><th>Model</th><th>Ctx</th></tr><tr><td>A</td><td>128K</td></tr></table><a href="/x">link</a><p>Body text</p></body></html>"""
54 + doc = parse_html(html, "https://example.com/p")
55 + assert doc.title == "T" and doc.description == "D" and doc.canonical == "https://example.com/c" and doc.lang == "en"
56 + assert doc.json_ld[0]["name"] == "X"
57 + assert doc.embedded_json["__NEXT_DATA__"]["props"]["models"][0]["id"] == "m1"
58 + assert doc.tables[0]["headers"] == ["Model", "Ctx"] and doc.tables[0]["rows"] == [["A", "128K"]]
59 + assert doc.links == [("https://example.com/x", "link")]
60 + assert "Body text" in doc.text and "Head" in doc.text
61 +
62 +
63 +def test_markdown_parse():
64 + md = parse_markdown("---\ntitle: X\nlicense: apache-2.0\n---\n# H1\n\n| a | b |\n|---|---|\n| 1 | 2 |\n\nSee [l](https://e.com).\n\n## Sec\ntext")
65 + assert md.front_matter == {"title": "X", "license": "apache-2.0"}
66 + assert md.tables[0]["headers"] == ["a", "b"] and md.tables[0]["rows"] == [["1", "2"]]
67 + assert md.links == [("https://e.com", "l")]
68 + assert md.section("Sec") == "text"
69 +
70 +
71 +def test_compile_query():
72 + q = compile_query("open models released in 2026 with more than 100B parameters and 128k context")
73 + assert q.entity_type == "model" and q.openness == "open" and q.year_from == 2026 and q.params_min == 100_000_000_000 and q.context_min == 128_000
74 + q2 = compile_query("vision models by Mistral")
75 + assert q2.entity_type == "model" and "image" in q2.modalities and q2.organization == "Mistral"
76 + assert compile_query("nvidia").filters["residual"] == "nvidia"
77