Swiss public-transport connections

The Web Search module includes SwissTransport, a set of agent tools that read Swiss train, tram, bus and boat connections from the official timetable, including real-time estimates. They use the Open Journey Planner (OJP 2.0) service of opentransportdata.swiss (MeshWeaver.Plugins#2782). The tools are read-only: they never book, buy or reserve anything.

The owner approved it on 2026-10-09: "yes — a read-only Swiss public-transport connections skill (opentransportdata.swiss; its API key provisioned like other provider keys — never handle secret values; declare the key reference)."

What ships

Piece What it does
FindSwissConnections(from, to, departure?, count?) Resolves both endpoints by name (or takes a stop reference), then sends one OJPTripRequest. It returns the trips with their legs: line, direction, platform, timetabled and estimated times, and walking legs.
FindSwissStops(name, count?) Sends an OJPLocationInformationRequest restricted to stops and returns the candidates with their references (ch:1:sloid:…).
/swiss-transport skill Tells the agent how to ask and how to answer, in Swiss local time. It ships under WebSearch/Skill and is copied into each installer's {you}/Skill.

The built-in Assistant and the Voice agent declare SwissTransport. Any other agent gets the tools by adding SwissTransport to its plugins: front matter.

Provisioning the key

The service needs a per-consumer API key from the API manager (subscribe to the OJP 2.0 API). The platform never stores, reads or prints the value. It declares a reference:

Where Name
Configuration key the module binds SwissTransport:ApiKey
Environment / Key Vault reference key SwissTransport__ApiKey
Vault object (prefix + name, by the usual convention) <prefix>-SwissTransport-ApiKey

On a hosted deployment:

  1. Add { "key": "SwissTransport__ApiKey", "vaultSecret": "<prefix>-SwissTransport-ApiKey" } to the deployment record's keyVaultSecrets.secrets.
  2. Open Deployments/<name> → Integrations → Set Key Vault secrets…, then write the value there. The Integrations app claims every SwissTransport__ key.
  3. Run the governed Reconcile and Restart. The CSI driver reads the vault only at pod start.

The optional settings are SwissTransport:Endpoint (default https://api.opentransportdata.swiss/ojp20), SwissTransport:RequestorRef (default MeshWeaver_prod; the service asks for an environment suffix), and SwissTransport:TimeZone (default Europe/Zurich, used to read a departure given without an offset).

How it fails

The tools fail loudly. They never return an empty result in place of an answer:

Tests

src/MeshWeaver.AI.WebSearch.Test/SwissTransportPluginTest.cs runs the request shape and the parsing against fixtures in the cookbook's documented response shape. No network is used. The negative control checks that with no key nothing goes on the wire and the refusal names the key. The fixtures follow the published cookbook examples. They are not recorded from a live keyed call, so the first live call after provisioning is the end-to-end check.