Skip to main content

Agent guide: querying Internacia data

Platform-neutral workflow for looking up countries, borders, org membership, and entity linking. Works with Cursor, Claude Code, Copilot, Codex, and any agent with file or API access.

Before querying

  1. Read llms.txt for join keys and gotchas (compact index).
  2. Use exported datasets — do not parse data/countries/*.yaml or data/intblocks/**/*.yaml unless authoring.
  3. Full consumption contract: ai-consumers.md.
  4. Verified recipes: query-examples.md (DuckDB), query-examples-polars.md (Polars / Parquet), query-examples-r.md (R / dplyr), query-examples-observable.md (Observable / Plot).

Access paths

MethodPath / URL
DuckDB (preferred, in-repo)data/datasets/internacia.duckdb
Parquetdata/datasets/countries.parquet, intblocks.parquet, blocktypes.parquet, memberships.parquet
Version checkSELECT * FROM _meta; or data/datasets/*.manifest.json
Python SDK (no full checkout)https://github.com/datenoio/internacia-python
HTTP APIhttps://github.com/datenoio/internacia-api (self-host only; no public hosted instance)

Join keys

EntityPrimary keyAlso useful
Countrycode (alpha-2)iso3code, numeric_code, wikidata_id
Intblockidwikidata_id, blocktype, partof
Membershipincludes[].id → country codeNot includes[].name
Blocktype taxonomyblocktypes.idmatches values in intblocks.blocktype list
Bordersalpha-3 in bordersjoin on neighbor iso3code

Scope (in / out)

In scope: ISO identifiers, geography, demographics with source/year, World Bank classifications, languages/currencies/timezones, org membership, Wikidata links.

Out of scope: HDI, GDP, government type, internet penetration, time-series indicators — enrich downstream from other datasets.

Canonical queries (DuckDB)

Version and schema:

SELECT dataset, version, schema_hash, build_date FROM _meta;

Current ISO countries (249):

SELECT code, name FROM countries
WHERE code_status = 'official_iso3166_1' ORDER BY code;

UN members:

SELECT code, name FROM countries WHERE un_member = true ORDER BY name;

Country attribute fields (former attribute intblocks — prefer these over retired LHTRAFFIC / DVD_* / WS* / LS* / *GAUGE ids; remap via attribute_intblock_migrations.json):

SELECT code, name FROM countries WHERE car_side = 'left';
SELECT code, name FROM countries WHERE dvd_region = 1;
SELECT c.code, c.name FROM countries c, UNNEST(c.writing_directions) t(d) WHERE d.id = 'rtl';
SELECT c.code, c.name FROM countries c, UNNEST(c.legal_systems) t(l) WHERE l.id = 'common_law';

Land neighbors (alpha-3 borders — join on iso3code):

SELECT n.code, n.name
FROM countries th,
UNNEST(th.borders) AS b(neighbor_iso3)
JOIN countries n ON n.iso3code = b.neighbor_iso3
WHERE th.code = 'TH'
ORDER BY n.name;

Org members (NATO example):

SELECT m.id AS member_code, m.name AS member_label, m.status
FROM intblocks i, UNNEST(i.includes) AS t(m)
WHERE i.id = 'NATO' AND m.type = 'country';

Orgs that include a country (Laos example):

SELECT i.id, i.name
FROM intblocks i, UNNEST(i.includes) AS t(m)
WHERE m.id = 'LA' AND m.type = 'country'
ORDER BY i.name;

Resolve intblock alias before join (Python):

import json
import pandas as pd

aliases = {a["alias"]: a["target"] for a in json.load(open("data/datasets/intblocks_aliases.json"))}
blocks = pd.read_parquet("data/datasets/intblocks.parquet")
blocks["id"] = blocks["id"].map(lambda x: aliases.get(x, x))

Structured population field (Pandas — .struct needs the Arrow dtype backend):

df = pd.read_parquet("data/datasets/countries.parquet", dtype_backend="pyarrow")
pop = df["population"].struct.field("value")

Common mistakes

MistakeCorrect approach
Join borders on alpha-2Use alpha-3; join bordersiso3code
Join intblocks on includes[].nameUse includes[].id (country code)
Assume 256 codes are all ISO officialFilter code_status = 'official_iso3166_1'
Read plain number from populationUse struct field .value (pandas: dtype_backend="pyarrow"; Polars: .struct.field("value"))
Expect HDI/GDP in this datasetOut of scope; enrich downstream
Ignore alias remapsLoad intblocks_aliases.json before joining on intblock id

DuckDB struct lists

Unnest list-of-struct columns: UNNEST(i.includes) AS t(m) then reference m.id, m.type, m.status.