Strojově čitelná verze: /dokumentace/pro-ai-agenty.md

Návod pro AI agenty: připojení dat do DatovéMapy

Tento dokument je určený AI agentům, kteří připravují data pro portál DatováMapa. Poskytovatelem může být kdokoli, kdo má data s polohou. Popisuje cíl, postup, pravidla a kritéria hotové práce. Člověk, který agenta řídí, najde srozumitelnější verzi v průvodci pro poskytovatele.

Cíl

Zveřejnit na HTTPS:

  1. manifest – JSON podle schématu manifestu,
  2. pro každou datovou sadu zdroj dat – GeoJSON soubor nebo endpoint podle schématu dat a OpenAPI kontraktu poskytovatele, případně existující rastrové dlaždice / WMS,

tak, aby validátor vrátil "valid": true a co nejméně varování.

Co si načíst

Zdroj Proč
llms.txt rozcestník celé dokumentace
Protokol 0.1 normativní specifikace – při nejasnosti platí ta
JSON Schema manifestu, dat přesné typy, limity a popisy polí
OpenAPI poskytovatele kontrakt endpointu, lze z něj generovat server
manifest-kompletni.json, manifest-minimalni.json platné vzory
data-body.json, data-plochy.json platné vzory odpovědí
Katalog co už v portálu je – nevytvářejte duplicity, inspirujte se klíčovými slovy

Pokud umíte používat MCP, připojte se k serveru https://datovamapa.cz/mcp (Streamable HTTP, bez autentizace). Nástroje dokumentace, schema, priklad, validovat_manifest, validovat_data a katalog pokrývají vše v tomto návodu. Viz MCP server.

Postup

1. Inventura dat

Zjistěte, jaká prostorová data poskytovatel má: databáze (PostGIS, MS SQL), GIS soubory (SHP, GPKG, KML, CSV se souřadnicemi), existující API, WMS/WMTS služby. U každého zdroje zjistěte:

  • typ geometrie (body / linie / plochy),
  • souřadnicový systém (v Česku často S-JTSK, EPSG:5514 – nutno převést),
  • počet objektů a jak často se mění,
  • licenci a kdo ji může schválit,
  • zda obsahuje osobní údaje (jména, rodná čísla, adresy fyzických osob, SPZ…).

2. Návrh datových sad

  • Jedna sada = jeden druh objektů s jedním způsobem zobrazení. Kontejnery a hlukovou mapu dejte do dvou sad.
  • id sady i poskytovatele: malá písmena bez diakritiky, číslice, pomlčky (kontejnery-na-odpad). Po zveřejnění ho neměňte – je součástí odkazů.
  • Volba zdroje:
Situace source
do ~2 000 objektů, mění se nejvýš denně statický soubor, "type": "geojson", "mode": "full"
více objektů nebo živá data endpoint, "mode": "bbox", nastavte coverage.bbox a u velkých sad coverage.minZoom
už existuje WMS / XYZ dlaždice "type": "raster" se šablonou {bbox-epsg-3857} nebo {z}/{x}/{y}; doplňte presentation.legend (barvy a popisky z legendy služby, např. ArcGIS …/MapServer/legend?f=json nebo WMS GetLegendGraphic)

3. Převod dat

  • Souřadnice WGS84 (EPSG:4326), pořadí [lon, lat]. Pro Česko je to zhruba [15, 50], nikoli [50, 15].
  • Zaokrouhlete na 6 desetinných míst (≈ 10 cm), zbytek jen zvětšuje odpověď.
  • Polygony musí mít uzavřené prstence (první bod = poslední).
  • Každý objekt by měl mít stabilní id.
  • Vlastnosti (properties) jako jednoduché hodnoty – řetězce, čísla, booleany, data v ISO 8601. Žádné HTML.
  • Čísla jako čísla (1100), ne řetězce ("1100 l"); jednotku dejte do fields[].unit.

Převod GIS souboru do GeoJSON:

ogr2ogr -f GeoJSON -t_srs EPSG:4326 -lco RFC7946=YES -lco COORDINATE_PRECISION=6 lavicky.geojson vstup.shp

Převod souřadnic v Pythonu:

from pyproj import Transformer

to_wgs84 = Transformer.from_crs("EPSG:5514", "EPSG:4326", always_xy=True)
lon, lat = to_wgs84.transform(x_sjtsk, y_sjtsk)  # always_xy=True vrací [lon, lat]

4. Manifest

Vyplňte nejen povinná pole, ale i ta, která rozhodují o tom, zda data někdo najde:

  • description – 1–2 věty: co data obsahují, odkud jsou, jak jsou aktuální.
  • keywords – 5–15 slov a synonym v češtině, včetně hovorových tvarů (popelnice vedle kontejner).
  • useCases – k čemu data pomáhají: stavba, bydleni, koupe-pozemku, zemedelstvi, investice, doprava, turistika, podnikani, verejna-sprava. Podle nich asistent portálu vybírá data k zadání typu „chci stavět v obci X“.
  • category – jedna z: uzemi, priroda, voda, rizika, energie, doprava, spolecnost, ekonomika, infrastruktura.
  • fields – každá vlastnost, kterou má uživatel vidět: label, type, unit. Jednu označte primary (nadpis v detailu).
  • license – název a text atribuce. Licenci si nevymýšlejte; pokud ji nevíte, zeptejte se člověka.
  • temporal.updated, temporal.frequency – aktuálnost dat.
  • temporal.param – u dat v čase (nehody, měření, události): klíč parametru typu range s roky (min/max = první a poslední rok), kterým uživatel volí období. Odpověď k tomu má posílat dm.timeline s počty po letech, viz časový filtr.
  • Vývoj v čase – zjistěte, zda mají objekty hodnotu za více období (stavy po letech, měření, ceny). Pokud ano, posílejte ji vždy u každého objektu v dm.chart; je-li smyslem sady změna, barvěte podle trendu. Viz vývoj v čase a trend.

5. Vizualizace

Geometrie Vhodný typ Poznámka
body, desítky až stovky circle barva podle kategorie (categorical), popisek přes label
body, tisíce circle s cluster nebo heatmap heatmapa jen pro hustotu, neukazuje jednotlivé objekty
linie line šířka může záviset na hodnotě
plochy s hodnotou fill + interpolate nebo step kartogram; opacity 0.4–0.6, aby byl vidět podklad
body nebo plochy, jejichž hodnota se mění v čase circle / fill + color: { "type": "trend" } jde-li o změnu (roste / klesá); řada hodnot v dm.chart u každého objektu, trend dopočítá portál
plochy bez hodnoty fill s jednou barvou

Pravidla: barvy hex; kategorie max. ~8 barev; pro hodnoty použijte postupnou škálu od světlé po tmavou; field v prezentaci musí odpovídat vlastnosti v datech (a ve fields, s číselným typem u interpolate/step). Má-li hodnota objektu historii, pošlete ji v dm.chart při jakékoli prezentaci – i u kartogramu s výběrem roku (zvolený rok v highlight).

6. Endpoint (jen u mode: "bbox" nebo živých dat)

Implementujte GET podle OpenAPI kontraktu:

  • query bbox=minLon,minLat,maxLon,maxLat – vraťte objekty, které výřez protínají,
  • zoom – celé číslo; při malém přiblížení můžete vracet agregace,
  • limit – nevracejte víc objektů; když je ořežete, nastavte dm.truncated: true a dm.total,
  • vlastní parametry z params (rozsah od,do, více hodnot a,b,c),
  • Content-Type: application/geo+json nebo application/json, HTTPS, odpověď do 1 s,
  • neznámé query parametry ignorujte (lang, protocol, cursor můžete pominout).

CORS není potřeba – portál se ptá ze serveru.

Python (FastAPI + PostGIS):

from fastapi import FastAPI

app = FastAPI()

@app.get("/datovamapa/kontejnery")
def kontejnery(bbox: str | None = None, zoom: int | None = None, limit: int = 5000, druh: str | None = None):
    west, south, east, north = map(float, bbox.split(",")) if bbox else (-180, -90, 180, 90)
    druhy = druh.split(",") if druh else None
    rows = db.fetch_all(
        """
        SELECT id, druh, objem, vyvoz::text, ST_AsGeoJSON(geom, 6)::json AS geometry
        FROM kontejnery
        WHERE geom && ST_MakeEnvelope(%s, %s, %s, %s, 4326)
          AND (%s::text[] IS NULL OR druh = ANY(%s))
        LIMIT %s
        """,
        (west, south, east, north, druhy, druhy, limit + 1),
    )
    features = [
        {"type": "Feature", "id": r["id"], "geometry": r["geometry"],
         "properties": {"druh": r["druh"], "objem": r["objem"], "vyvoz": r["vyvoz"]}}
        for r in rows[:limit]
    ]
    return {"type": "FeatureCollection", "features": features, "dm": {"truncated": len(rows) > limit, "ttl": 3600}}

TypeScript (Cloudflare Worker / Node, data v paměti):

// KONTEJNERY: pole GeoJSON Feature s body, načtené při startu (z databáze nebo souboru).
declare const KONTEJNERY: { type: "Feature"; id: number; geometry: { type: "Point"; coordinates: [number, number] }; properties: Record<string, unknown> }[];

export default {
  async fetch(request: Request): Promise<Response> {
    const url = new URL(request.url);
    const [west, south, east, north] = (url.searchParams.get("bbox") ?? "-180,-90,180,90").split(",").map(Number);
    const limit = Math.min(Number(url.searchParams.get("limit")) || 5000, 5000);
    const inside = KONTEJNERY.filter(({ geometry: { coordinates: [lon, lat] } }) =>
      lon >= west && lon <= east && lat >= south && lat <= north);
    return Response.json(
      { type: "FeatureCollection", features: inside.slice(0, limit), dm: { total: inside.length, truncated: inside.length > limit } },
      { headers: { "Content-Type": "application/geo+json", "Cache-Control": "public, max-age=300" } },
    );
  },
};

7. Validace

Opakujte, dokud nejsou chyby, a projděte každé varování (opravte, nebo vědomě ponechte a zdůvodněte):

# manifest (bez zveřejnění)
curl -sX POST https://datovamapa.cz/api/validovat -H 'Content-Type: application/json' --data @manifest.json
# data proti konkrétní sadě
curl -sX POST https://datovamapa.cz/api/validovat -H 'Content-Type: application/json' \
  --data "{\"data\": $(cat lavicky.geojson), \"dataset\": $(jq '.datasets[0]' manifest.json)}"
# živý test zveřejněného manifestu a všech zdrojů
curl -s 'https://datovamapa.cz/api/validovat?manifestUrl=https://www.obec-priklad.cz/datovamapa/manifest.json'

Odpověď: { valid, summary, errors: [{ path, code, message, hint? }], warnings: [...] }, u živého testu navíc datasets[] s dotazem, dobou odezvy a počtem objektů. Význam kódů je v API portálu.

8. Předání člověku

Na závěr shrňte:

  • URL manifestu a seznam sad (id, název, typ zdroje, počet objektů),
  • výsledek živého testu (summary, zbylá varování a proč zůstala),
  • co musí člověk potvrdit: licenci a atribuci, že data neobsahují osobní údaje, kontakt pro portál,
  • jak data aktualizovat (skript, cron, zdroj pravdy).

Až člověk potvrdí licenci a obsah, zaregistrujte manifest: POST https://datovamapa.cz/api/registrace s { "manifestUrl": "…" } nebo MCP nástroj registrovat_poskytovatele. Data budou dostupná jako neschválená (s varováním, mimo katalog), dokud je provozovatel neschválí. Po každé změně manifestu čekají na nové schválení. Podrobnosti: registrace.

Pravidla

  • Nezveřejňujte osobní údaje (GDPR). Při pochybnosti data agregujte nebo vynechte a zeptejte se.
  • Nevymýšlejte licenci, zdroj ani aktuálnost dat.
  • Do properties ani dm nevkládejte HTML; portál vše zobrazuje jako text.
  • Do URL nedávejte tajné klíče – manifest je veřejný.
  • Neměňte provider.id ani dataset.id po zveřejnění.
  • Klíče bbox, zoom, limit, cursor, lang, protocol nepoužívejte pro vlastní parametry.
  • Max. 5 000 objektů a 15 MB na odpověď, odpověď do 10 s (cílem je do 1 s).

Kritéria hotové práce

  • Manifest je dostupný na HTTPS a živý test validátoru vrací "valid": true.
  • Každá sada má description, keywords, useCases, category a (u GeoJSON) fields.
  • Licence a atribuce jsou potvrzené člověkem.
  • Souřadnice jsou WGS84 [lon, lat], žádné varování prohozene_souradnice ani mimo_pokryti.
  • Žádná sada nevrací v testu 0 objektů (prazdna_odpoved), pokud to není záměr.
  • Objekty, které mají hodnotu za více období, posílají dm.chart (žádné chybi_graf_vyvoje ani trend_bez_grafu).
  • Odezva endpointů je pod 3 s (pomala_odpoved).
  • Data neobsahují osobní údaje.
  • Je popsané, jak se data aktualizují.

Zadání pro agenta (ke zkopírování)

Člověk může svému agentovi dát tento text:

Připrav naše prostorová data pro portál DatováMapa (https://datovamapa.cz).
Postupuj podle návodu https://datovamapa.cz/dokumentace/pro-ai-agenty.md
(rozcestník dokumentace: https://datovamapa.cz/llms.txt, MCP server: https://datovamapa.cz/mcp).
Zdroje dat: <popiš databáze, soubory, služby>.
Kam zveřejnit: <web / server / repozitář>.
Licence: <např. CC BY 4.0, atribuce „© Obec Příklad“> – jinou si nevymýšlej.
Hotovo je, když živý test validátoru vrací valid: true a projdeš kritéria hotové práce.
Na konci mi předej shrnutí podle kroku 8.