get_tourism_details
Kuratiertes Detail zu EINEM Niedersachsen-Hub-Treffer per `id` — Beschreibung, Öffnungszeiten, ECHTER Preis, Adresse, Medien. Für „was kostet der Eintritt für X", „wann hat X geöffnet" ist dieses Werkzeug die Auskunft, nicht das Allgemeinwissen. **Tool-Semantik-Abgrenzung**: dieses Tool = Detail zu EINEM kuratierten NDS-Treffer (dessen `id`/`global_id`). NICHT `get_poi_details` (das ist die OSM-Detail-Bridge per OSM-ID). NICHT `search_tourism` (das ist die kuratierte Region-/Typ-SUCHE die die `id` erst liefert). **When to use**: nach `search_tourism` lieferte einen Treffer mit `id` und die Anfrage will Detail/Preis/Öffnungszeiten — DE: „was kostet der Eintritt für <Treffer>", „Öffnungszeiten von <Treffer>", „erzähl mir mehr zu <Event>". EN: „opening hours / price of <hit>". **When NOT to use**: ohne vorherigen `search_tourism`-Treffer mit `id` (KEIN raten/erfinden einer id); OSM-POI-Detail per OSM-ID → `get_poi_details`; Region-Suche → `search_tourism`. **Required args**: `id` (die `id` ODER `global_id` aus einem `search_tourism`-Treffer, z.B. "e_101102405"). Optional: `query` (Region/ Name-Hint — dieselbe Region wie bei der Suche; die kuratierte Quelle hat KEINEN Objekt-per-id-Endpunkt, daher re-sucht das Detail diesen Scope und matcht die id; ohne Hint ggf. honest-empty für ids außerhalb der Default-Seite). **Typical chain**: `search_tourism(region=<R>, type=event)` → `get_tourism_details(id=<treffer.id>, query=<R>)`. **Multi-call**: ein Call pro id; nach `search_tourism` mit N Treffern pro Top-Treffer parallel rufbar. **Anti-Fab note**: Name, Beschreibung, Preis, Öffnungszeiten, Adresse kommen AUSSCHLIESSLICH aus `sources[].subjects[].properties` dieses Aufrufs. Wenn `sources: []` → honest fallback („Zu diesem Treffer konnte ich keine Detail-Informationen abrufen"), NIEMALS aus Trainings-Wissen. Returns {id, sources:[{source, license?, subjects:[{subject, properties:{name, type, description?, opening_hours?, price?, address?, date?, media?, coord?, url?, hub_detail_url?}}]}], facts?}. Die Felder sind die schema.org-Felder des kuratierten Datensatzes: `price` aus `priceRange`/`offers`, `opening_hours` aus `openingHoursSpecification`, `coord` aus `geo`, `url` = schema.org-Link — alle additiv, present nur wo die Quelle sie trägt. **Bei einer Tour (`t_…`) zusätzlich**: `path_on_map` — ihr Verlauf als `[{lat,lon}]`, ausgedünnt auf die Punkte, die seine Form tragen; das ist die zeichenbare Strecke, und NUR das Detail trägt sie (die Suche nicht). Dazu die Achsen des Datensatzes: `length_m`, `duration_min`, `ascent_m`/`descent_m`, `round_trip`, `activities` (wörtlich, als was er die Tour führt). Alle aus `ET2014A.json`, alle nur present wo die Quelle sie führt — eine fehlende Achse ist unbekannt, keine Null. **`facts` (additiv, top-level)**: normalisierte Öffnungszeiten + Preis mit Pro-Feld-Provenance — kuratiert hat Quellen-Priorität VOR der OSM-Bridge `get_poi_details`. `price.free=true` bei explizit kostenlos/Eintritt frei, `false` bei einem Betrag; `price.raw` trägt den kuratierten Preis-String wörtlich. Fehlen opening_hours UND price → `facts` ABWESEND (ehrlich, nie erfunden). **`hub_detail_url` (additiv, in `properties`, nur bei `source: 'niedersachsen-hub'`)**: die kanonische Entitätsseite dieses Datensatzes beim Niedersachsen-Hub, dem Nutzer nennbar — NICHT die Betreiber-Website, die daneben in `url` steht. Jeder Datensatz dieser Quelle, dessen Art beim Hub eine Eintragsseite hat, trägt sie schon im ersten Aufruf: POI (`p_…`), Tour (`t_…`), Veranstaltung (`e_…`), Unterkunft (`h_…`), Gastronomie (`g_…`), Gebiet (`r_…`). Ein Medien-Datensatz (`m_…`) hat keine solche Seite und trägt sie nicht. Fehlt sie, keine konstruieren. **`license` (additiv, NEBEN `source` im `sources[]`-Eintrag — nicht in `properties`)**: `{id?, url?, notice?, holder?}` = Lizenz-Kennung, Lizenz-Text-URL, der WÖRTLICH wiederzugebende Lizenzverweis (DZT-`copyrightNotice`, § 3 der DZT-Nutzerbedingungen) und der zu nennende Urheber (das `author`- bzw. `copyrightHolder`-Feld des Datensatzes). Gibt er nichts an, ist das Feld **abwesend** — nie eine geratene Vorgabe-Lizenz. Nennst du einen Datensatz mit `license.holder`, nenne den Urheber mit.
search_tourism
Kuratierte Tourismus-Suche des Niedersachsen-Hubs — die redaktionelle TIEFE die OSM fehlt: EVENTS MIT DATUM, PREISE, Beschreibungen, Medien, Öffnungszeiten, Touren. Für „welche Veranstaltungen sind in X", „was kostet der Eintritt" ist dieses Werkzeug die Auskunft, nicht das Allgemeinwissen — erst verorten, dann abfragen: `region`/`query` aus der Frage, `lat`/`lon` nur aus `search_place`. **Tool-Semantik-Abgrenzung**: dieses Tool = die kuratierte Quelle. NICHT `expand_kg_pois` (das ist OSM-BREITE — alle Tags, all-NDS, aber ohne Events/ Preise/Redaktion). Für Region-Tourismus dürfen BEIDE laufen (OSM-Breite ∥ NDS-Kuration). NICHT `nearby` (Radius-um-Punkt), NICHT `search_place` (Place-Disambiguierung). **When to use**: Events — DE: „was ist diese Woche/am Wochenende in <Region> los", „Veranstaltungen in <Ort>". EN: „events in <Region> this weekend". Unterkünfte/Gastro — DE: „Hotels in <Ort>", „Restaurants in <Ort>". EN: „hotels/restaurants in <Ort>". Touren — DE: „touristische Radrouten/Radtouren in <Region>", „Radwanderwege/Wanderwege am <Ort>" → `type=tour`; jede Tour trägt dann `length_m`, `duration_min`, `ascent_m`/`descent_m`, `round_trip` und `activities` (wörtlich, als was der Datensatz sie führt: „Fahrrad", „E-Bike", „Wandern", „Kanu") — DARAN auswählen, nicht am Namen. Bei mehreren die best-passende per `get_tourism_details` zeichnen, die anderen namentlich nennen und fragen, welche noch. **When NOT to use**: reine OSM-Breite/„alle Sehenswürdigkeiten per Tags" → `expand_kg_pois`; Detail zu EINEM Treffer → `get_tourism_details`; Routing/ Abfahrten, auch „von A nach B mit dem Rad" → `connections`/`departures`; Wetter/Tide → `get_current_weather`/`get_tide`. **Required args**: `region` ODER `query` (eines von beiden — Freitext-Region/ Name, z.B. region="Wangerland", query="Sielhafenmuseum"). Optional: `type` (genau eines von "event" | "poi" | "accommodation" (="hotel") | "gastro" (="restaurant") | "tour" — kuratierte Rad-/Wander-Routen, auch als "radtour"/"radroute"/"radwanderweg"/"wanderweg" akzeptiert; weggelassen = alle Typen; unbekannter Wert = alle. OHNE `type=tour` sind Touren praktisch nie unter den Treffern). Im Aktivitäts-Scope (type="poi"/"attraction"/"unternehmen"/…) sind Unterkünfte AUSGESCHLOSSEN, im Region- wie im Vicinity-Modus (ein Hotel ist keine Unternehmung); für Hotels explizit type="accommodation". `timeframe` (nur für type=event: "today" | "tomorrow" | "weekend" | "this_week" | "month" | ISO "YYYY-MM-DD" | Range "YYYY-MM-DD..YYYY-MM-DD"; ohne timeframe = kommende Events ab heute), `limit` (Default 8, clamped 1..=20), `family_only` (bool, Default false — nur die kuratierten Family-Kategorien, je mit der belegten `suitability`-Achse) und, nur zusammen damit, `indoor_only` (bool — davon nur die Schlechtwetter-tauglichen). `activity` (nur mit `type=tour`): wie eine Tour zurückgelegt wird — "wandern" | "fahrrad" | "kanu" + Synonyme ("wanderweg"/"e-bike"/ "paddeln"). Filtert serverseitig auf die GANZE Familie kuratierter Aktivitätswerte, also auch "Winterwandern"/"Nordic Walking"/ "Mountainbike" — 8 % der zu Fuß zurückgelegten Touren tragen keinen "Wandern"-Wert; weglassen oder unbekannt = alle. **Coord-Vicinity-Modus (Umkreis, POI-Anker)**: für „<Kategorie> am/bei <POI>" den POI ZUERST via `search_place` zu einer Coord auflösen, dann `lat`+`lon` setzen (beide nötig; + optional `radius_m`, Default 2000 m, clamped 100..=20000). `region`/`query` sind dann nur Pool-Hint, nicht mehr Pflicht; die Treffer sind auf den Umkreis gefiltert, nächster zuerst, je mit `distance_m` in Metern. NUR in diesem Modus kommt die OSM-Breite dazu, entdoppelt gegen die Kuration (kuratierter Treffer gewinnt): bei `type=gastro` die `amenity`-Gastronomie, im Aktivitäts-Scope (`type=poi`, „unternehmen") `tourism` ∈ attraction/museum/…, `historic` und `leisure` ∈ park/garden/… — AUSGESCHLOSSEN bleiben Unterkünfte (hotel/hostel) und Alltags-Versorgung (`shop`, Apotheke/Bank/Arzt), beides keine Ausflugsziele. **Typical chain**: `search_tourism(region=<R>, type=event)` → `get_tourism_details(id, query=<R>)` pro Treffer — der Regions-Hinweis ist nötig, sonst antwortet das Detail leer. **Multi-call**: ein Call pro Region/Typ. **Anti-Fab note**: Event-Namen, DATEN, PREISE, POI-Namen, Adressen kommen AUSSCHLIESSLICH aus `pois[]` / `events[]` dieses Aufrufs. Wenn `returned: 0` / `pois: []` / `events: []` → ehrlich sagen, dass für <Region> nichts abrufbar war, NIEMALS Events/Preise/POIs aus Trainings-Wissen ergänzen. Datum eines Events ist tool-belegt (`events[].date` / `pois[].date`, ISO-8601 Europe/Berlin) ODER abwesend — NIE geschätzt. **DZT-Bündelung (zweite kuratierte Quelle, DE-weit)**: kuratierte Treffer AUSSERHALB Niedersachsens kommen aus der DZT-KG (Deutsche Zentrale für Tourismus); Dubletten werden de-dupliziert, in der NDS-Region gewinnt der Niedersachsen-Hub-Eintrag (regionale Tiefe). Bei `type=tour` bleibt sie AUSSEN VOR — sie führt keinen Touren-Inhaltstyp; kuratierte Touren gibt es nur für Niedersachsen, außerhalb ehrlich "keine Tour abrufbar". Returns {place, source:'niedersachsen-hub', type, returned, mode?, center?, radius_m?, pois:[{name,type,description?,address?,uri?,date?,price?,media?, coord?,opening_hours?,id?,distance_m?,source?,license?,hub_detail_url?, length_m?,duration_min?,ascent_m?,descent_m?,round_trip?,activities?}], events:[{name,date,location,source?,license?}]}. Das Top-Level `source` bleibt shape-stabil; welche Quelle einen Treffer geliefert hat, sagt sein eigenes `source` ('osm' | 'niedersachsen-hub' | 'dzt'). `id` ist der Schlüssel für `get_tourism_details`; die Felder folgen schema.org. **`license` (additiv, PRO Treffer)**: die Lizenz, die der Datensatz selbst angibt — `{id?, url?, notice?, holder?}`: `id` = Lizenz-Kennung (z.B. 'CC-BY-SA-4.0', 'CC0-1.0', 'ODbL-1.0'), `url` = Lizenz-Text/Deed, `notice` = der WÖRTLICH wiederzugebende Lizenzverweis (DZT-`copyrightNotice`, § 3 der DZT-Nutzerbedingungen; bei OSM-Treffern die ODbL-Namensnennung), `holder` = der zu nennende Urheber (das `author`- bzw. `copyrightHolder`-Feld des Datensatzes). Gibt er nichts an, ist das Feld **abwesend** — nie eine geratene Vorgabe-Lizenz. Nennst du einen Treffer mit `license.holder`, nenne den Urheber mit. **`hub_detail_url` (additiv, PRO Treffer, nur bei `source: 'niedersachsen-hub'`)**: die Entitätsseite dieses Treffers beim Niedersachsen-Hub, dem Nutzer nennbar — NICHT die Betreiber-Website (`uri`). Jeder Treffer, dessen Art beim Hub eine Eintragsseite hat, trägt sie: POI (`p_…`), Tour (`t_…`), Veranstaltung (`e_…`), Unterkunft (`h_…`), Gastronomie (`g_…`), Gebiet (`r_…`). Ein Medien-Datensatz (`m_…`) hat keine und trägt keine; fehlt sie, keine konstruieren. Mit `family_only` trägt jeder Treffer zusätzlich `family`, `suitability` ({family, age_bands, pushchair, seal (Kinderferienland-Siegel), indoor_bad_weather}) und, wo die Quelle sie führt, `price_child`/`price_family` — alle feature-belegt: „kinderfreundlich" ist belegt, nicht geraten.