# Travel Brief

> Turn flight and hotel search results into a client-ready travel brief - a one-line recommendation first, then a markdown comparison table, the low|typical|high verdict read from price_range_in_relation_to_other_periods against the price_insights_low/price_insights_high band, the buy_link and hotel booking links, and a prices-checked-at timestamp - re-fetching under one fresh timestamp instead of reformatting fares quoted earlier. Use when the user asks to write this up for a client or customer, make it presentable, client-facing or shareable, format, reformat, polish or tidy these results into something I can send, draft the email, the itinerary summary, a proposal, a quote or a one-pager, put these flights and hotels in a table, summarize the trip options, give me a recommendation not a list, which of these should I book, or refresh these prices before the quote goes out - "write up the BER-CDG options and the Hilton Paris rate for my client". Returns markdown - recommendation, table, verdict with Google's h

- Skill: `mtnrabi/travel-brief` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add mtnrabi/travel-brief`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mtnrabi/travel-brief/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: mtnrabi (https://skillmd.com/u/mtnrabi)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mtnrabi/travel-brief

---


# Travel Brief

## Overview

This skill is the presentation layer: it re-runs the search itself under one fresh timestamp — rather than reformatting numbers quoted earlier in the conversation — and lays the results out the way a human travel agent would send them to a client: recommendation first, then a comparison table, then the price verdict, then the links, then the timestamp. Use `travel-data-api` for auth, base URL, and endpoint details, and prefer the hosted MCP tools when a client is configured. Both trip types carry `buy_link`, `price_range_in_relation_to_other_periods`, `price_insights_low`, and `price_insights_high`. The rest of the table is built from different keys per trip type: one-way items give `price` / `price_as_number`, `airline`, `stops`, `duration`, `departure_description`, and `arrival_description`; round-trip items give `total_price` / `total_price_as_number`, `total_stops`, `total_duration_seconds`, and per-leg fields such as `departure_flight_airline`, `departure_flight_stops`, `departure_flight_duration`, `departure_flight_departure_description`, and their `return_flight_*` counterparts. Hotel shortlist items from `POST /search` give `name`, `price_string`, `price`, `review_score`, `review_count`, `room_type`, `location`, `image_url`, and `link`; `POST /hotel_by_name` returns those for a single property plus `available` and `nights`.

## Sources for a Brief

| Section of the brief | REST endpoint | MCP tool |
|---|---|---|
| Flight options, one-way | `POST /api/google_flights/oneway/v1` | `search_oneway_flights` |
| Flight options, round-trip | `POST /api/google_flights/roundtrip/v1` | `search_roundtrip_flights` |
| Hotel shortlist at a destination | `POST /search` | n/a |
| One named property's price and availability | `POST /hotel_by_name` | n/a |

Flights host: `google-flights-live-api.p.rapidapi.com`. Hotels host: `booking-live-api.p.rapidapi.com`.

## Workflow

1. **Refetch, never reformat old data.** If the results are more than a few minutes old, or came from an earlier message, run the search again. A brief is a document someone will act on, so it must carry a fresh fetch and the moment it happened.
2. **Stamp the fetch time before you call**, in UTC, and carry that one timestamp through the whole brief.
3. **Pick the recommendation yourself.** Choose one option and say why in one sentence — cheapest, shortest, non-stop, best value against the historical band. A list with no pick is not a brief.
4. **Build the comparison table** from at most 3–5 options, sorted client-side on `price_as_number` or `total_price_as_number`.
5. **Read the verdict** off the recommended item: `price_range_in_relation_to_other_periods` plus the `price_insights_low`–`price_insights_high` band, and put it in its own line.
6. **Close with the links, the checked-at line, and the non-affiliation line.**

## Fetching the Brief's Data

Substitute your own key for `YOUR_RAPIDAPI_KEY`; nothing else needs editing.

```bash
export RAPIDAPI_KEY="YOUR_RAPIDAPI_KEY"
CHECKED_AT="$(date -u +'%Y-%m-%d %H:%M UTC')"

curl -sS -X POST 'https://google-flights-live-api.p.rapidapi.com/api/google_flights/roundtrip/v1' \
  -H "x-rapidapi-key: $RAPIDAPI_KEY" \
  -H 'x-rapidapi-host: google-flights-live-api.p.rapidapi.com' \
  -H 'Content-Type: application/json' \
  -d '{
        "from_airport": "BER",
        "to_airport": "CDG",
        "departure_date": "2026-11-12",
        "return_date": "2026-11-16",
        "currency": "USD",
        "limit": 5
      }'

printf '\nPrices checked at %s — fares go stale in minutes.\n' "$CHECKED_AT"
```

## Refreshing a Brief Before You Send It

Re-run flights and the hotel line together, under one timestamp, right before the brief goes out. Two billed requests — say that before running it.

```bash
export RAPIDAPI_KEY="YOUR_RAPIDAPI_KEY"
CHECKED_AT="$(date -u +'%Y-%m-%d %H:%M UTC')"

curl -sS -X POST 'https://google-flights-live-api.p.rapidapi.com/api/google_flights/roundtrip/v1' \
  -H "x-rapidapi-key: $RAPIDAPI_KEY" \
  -H 'x-rapidapi-host: google-flights-live-api.p.rapidapi.com' \
  -H 'Content-Type: application/json' \
  -d '{"from_airport":"BER","to_airport":"CDG","departure_date":"2026-11-12","return_date":"2026-11-16","currency":"USD","limit":5}'

curl -sS -X POST 'https://booking-live-api.p.rapidapi.com/hotel_by_name' \
  -H "x-rapidapi-key: $RAPIDAPI_KEY" \
  -H 'x-rapidapi-host: booking-live-api.p.rapidapi.com' \
  -H 'Content-Type: application/json' \
  -d '{"hotel_name":"Hilton","area":"Paris","checkin_date":"2026-11-12","checkout_date":"2026-11-16","adults":2,"currency":"USD"}'

printf '\nPrices checked at %s — fares go stale in minutes.\n' "$CHECKED_AT"
```

On the hosted MCP, one user intent is one tool call: pass `departure_date_from` / `departure_date_to` and a list of destinations rather than looping a date at a time.

## Common Pitfalls

- **An empty array is not an error — but say which kind of empty it is.** The flights endpoints return `[]` with HTTP 200. When `X-Search-Status` is `ok` or `empty`, write "no flights returned for this route and date" into the brief as a real finding, without retrying in a loop. When it is `degraded`, the search did not complete: that option is *unchecked*, not unavailable, and a brief that silently downgrades it to "no options" is telling the client something untrue.
- **A sold-out hotel is `available: false` with null price fields**, which is a valid answer from `POST /hotel_by_name`. Put it in the table as "sold out for these dates" rather than dropping the row silently — the client asked about that property.
- **Never let API result order become the table order.** `sort_type` is honoured on both endpoints, but a brief almost always merges several searches, and nothing sorts across them. Sort on `price_as_number` / `total_price_as_number` yourself, or the "cheapest" row in the brief will be wrong.
- **`use_fallback` currently does nothing** — it is accepted but selects a data source that is not switched on for this API. Before writing "no options exist", check `X-Search-Status` instead.
- **Every combination is a billed request.** One route × one date × one cabin × one passenger set = one request, and each hotel in the shortlist is another. Give the request count before rebuilding a brief, never after.
- **Never rebuild a brief from prices quoted earlier in the conversation.** Fares go stale in minutes; a reformatted old number reads as a live quote and is the one failure a client will notice.

## Output Standards

- Fixed order, every time: **recommendation → comparison table → price verdict → booking links → checked-at line → non-affiliation line.** One sentence of recommendation, naming the option and the reason, before any table.
- Flight table columns: Option | Price | Airline | Stops | Duration | Departs / Arrives — filled from `airline` / `stops` / `duration` on one-way items and from the `departure_flight_*` and `return_flight_*` fields on round-trip items, one row per leg or a combined row, never by reading one-way key names off a round-trip item. Hotel table columns: Property | Price for stay | Review score (count) | Room type | Status. 3–5 rows maximum; mark the recommended row.
- The verdict gets its own line and uses the API's own words, not a guess: "$209 round-trip is **typical** for this route and period — Google's historical range here is $180–$260." If the verdict is `high`, say so even when it is the cheapest option found.
- Booking links go in full as `buy_link` (flights) and `link` (hotels). Never describe a link as a held, locked, or guaranteed fare, and never present the brief as a booking.
- Close with the literal line **"Prices checked at YYYY-MM-DD HH:MM UTC — fares go stale in minutes."** using the timestamp from the fetch, followed by: this brief uses an independent API that returns publicly available flight and hotel pricing; it is not affiliated with, endorsed by, or sponsored by Google or Booking.com.

