Generate neighbourhood guides with Exa's answer endpoint and keep the output display-only
Decision
Generate neighbourhood overviews with Exa's answer endpoint. The server sends a query with a JSON output schema, grounds it on the destination's Wikivoyage text, and gets back structured neighbourhoods with citations. The server stores the result on the destination as an enrichment effect, so viewing a trip reads the effect and never calls Exa.
Treat the output as untrusted and display-only. Wikivoyage is an openly editable wiki, so anyone can plant instructions in the grounding text. The server never feeds the generated copy into its own model calls, into intent parsing or into an effect that changes a trip. With no private data in the prompt and no consequential action downstream, the flow holds only one leg of the lethal trifecta: untrusted input. The worst a prompt injection can then do is put bad copy on screen.
Defend structure and leave content alone. The server wraps the grounding in a delimited source block and replaces angle brackets inside it, so the untrusted text cannot close the delimiter. It then strips markdown links and bare URLs from every generated field, so a planted phishing link never becomes tappable.
Routing enrichment output into anything that acts would void this decision.
Why
People want to know a city's neighbourhoods before they book a place to stay: which district has the nightlife, which is old and walkable, where the museums are. That content has to exist for any city a user picks, on demand. Exa searches recent travel writing and returns cited, schema-shaped answers from one call, which suits a feature we want for every destination without curation.
Rejected alternatives
- Wikipedia alone. Free, but generic and not written for travellers.
- Google Places. Priced per request and built around businesses rather than the character of an area.
- Hand curation. It does not scale to arbitrary cities.
- A denylist of dangerous content. It can never be complete, and while the output is only displayed it protects nothing the structural defences don't.
Consequences
Any destination gets cited, travel-focused content. Every generation is a paid API call, and quality varies because a model writes it.
Clients cannot write enrichment effects. The server rejects them from a client's modification, so only the server authors this text.
The MCP neighbourhood discovery tool returns the generated text to the calling client as data. Keeping it display-only there is the client's job.