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:
- Add
{ "key": "SwissTransport__ApiKey", "vaultSecret": "<prefix>-SwissTransport-ApiKey" }to the deployment record'skeyVaultSecrets.secrets. - Open
Deployments/<name>→ Integrations → Set Key Vault secrets…, then write the value there. The Integrations app claims everySwissTransport__key. - 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:
- No key. Both tools stay advertised and answer with a refusal that names
SwissTransport:ApiKeyand says that no request was sent. A missing tool would be silent, and an empty list would read as "there is no connection". Neither is true. - An OJP
ErrorCondition(for exampleTRIP_NOTRIPFOUND), a non-success HTTP status, or an unreadable answer comes back as "could not answer: …" with the reason. - An unreadable departure time is refused before any request is sent.
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.