Multi-component single transaction agent
Updated: Sep 10, 2026
Copy for LLM
Some purchases are made of parts that only make sense together. A trip is a flight, a hotel, and a car hire for one set of dates: the buyer chooses each one, sees a single total, and commits once. This guide covers the connector tools that make that work — a search across every component, a quote that prices them as a set, and a booking that writes them together.
This guide is deliberately narrow. It does not repeat the agent setup that every use case shares; see Before you start for where that lives.
Who this guide is for
The example is a travel seller, but the pattern fits any organization selling several components as one transaction.
| Organization type | Components | What the agent submits |
|---|---|---|
Travel sellers and tour operators | Flight, hotel, vehicle | One booking covering every component |
Event and conference organizers | Pass, workshops, accommodation | One registration with every add-on |
Home services and installers | Appliance, delivery slot, installation, disposal | One job with every line included |
Vehicle dealers | Vehicle, finance term, extras, delivery | One order with every option priced in |
Venue and equipment hire | Space, equipment, staffing hours | One contract covering the booking |
Two patterns look similar. Pick the right one.
| If the buyer | Use |
|---|---|
Chooses components that depend on each other, sees one total, commits once | This guide |
Reserves one thing against limited capacity for a date range |
The distinction that matters is where the price comes from. A cart totals its lines. A set is priced as a set, because a discount or supplement may apply only when the components are bought together.
Before you start
You need an onboarded and enabled Meta Business Agent, a valid access token, and a connector pointing at the system that holds your live inventory. This guide assumes all three already exist.
| For | See |
|---|---|
Onboarding, tokens, and webhooks | |
An end-to-end walkthrough of agent setup | |
Agent instructions | |
FAQs, files, and website knowledge | |
Creating a connector |
One instruction is worth adding to your agent instructions for this use case: tell the agent to present the components together with one total, name every component when it confirms, collect a full name for every person in the party before booking, and never book before the buyer agrees to that total.
How the three tools fit together
A single-component sale needs two tools — check availability, then commit. A multi-component sale needs three, and the middle one is the reason this guide exists.
| Tool | Returns | Called |
|---|---|---|
search_trip_options | Options for every component, each with an offer id | Once the buyer has given dates and a party size |
price_trip | One total plus a quote_id | Once the buyer has chosen an option per component |
book_trip | A booking reference | Only after the buyer confirms the total |
Never let the agent add the prices up. If it sums three option prices itself, any set discount, supplement, or tax rule your pricing engine applies is lost, and the total the buyer agrees to is not the total you charge. The quote tool exists so the number comes from the system that owns pricing.
Search across every component
One call returns options for all three components, so the agent can present a complete trip rather than interviewing the buyer three times.
curl -X POST "https://api.facebook.com/{entity_id}/agent_connectors/{connector_id}/tools" \
-H "Authorization: Bearer {ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-H "X-API-Version: 2.0.0" \
-d '{
"name": "search_trip_options",
"description": "Returns available flights, hotels, and vehicles for a route and date range. Call this once the customer has given an origin, a destination, both dates, and the number of people. Returns an offer id for each option, which price_trip requires.",
"user_auth_required": false,
"request_definition": {
"method": "GET",
"path": "/trips/options",
"query_parameters": {
"origin": {
"type": "string",
"description": "The departure airport or city, for example BOS or Boston."
},
"destination": {
"type": "string",
"description": "The arrival airport or city, for example LIS or Lisbon."
},
"depart_date": {
"type": "string",
"description": "The outbound date in YYYY-MM-DD format."
},
"return_date": {
"type": "string",
"description": "The return date in YYYY-MM-DD format."
},
"party_size": {
"type": "string",
"description": "The number of people traveling, as a whole number."
}
}
}
}'
Price the components as a set
The quote is the authoritative total. Make
vehicle_offer_id optional so a buyer who declines the car still gets a correct price for the rest.curl -X POST "https://api.facebook.com/{entity_id}/agent_connectors/{connector_id}/tools" \
-H "Authorization: Bearer {ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-H "X-API-Version: 2.0.0" \
-d '{
"name": "price_trip",
"description": "Prices the chosen flight, hotel, and vehicle together and returns one total plus a quote id. Call this after the customer has chosen an option for every component they want. Never add up the individual option prices yourself, because the set price may include a discount or a supplement.",
"user_auth_required": false,
"request_definition": {
"method": "POST",
"path": "/trips/quote",
"body": {
"content_type": "application/json",
"params": {
"flight_offer_id": {
"type": "string",
"description": "The offer id of the chosen flight, from search_trip_options."
},
"hotel_offer_id": {
"type": "string",
"description": "The offer id of the chosen hotel, from search_trip_options."
},
"vehicle_offer_id": {
"type": "string",
"description": "The offer id of the chosen vehicle, from search_trip_options. Omit if the customer does not want a car."
}
},
"required": ["flight_offer_id", "hotel_offer_id"]
}
}
}'
Commit the whole set in one write
The booking call takes the
quote_id and nothing else about the components. That keeps the write single and idempotent: the quote already holds what was agreed.curl -X POST "https://api.facebook.com/{entity_id}/agent_connectors/{connector_id}/tools" \
-H "Authorization: Bearer {ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-H "X-API-Version: 2.0.0" \
-d '{
"name": "book_trip",
"description": "Books every component in a quote as one transaction. Call this only after the customer has confirmed each component and the total from price_trip. Do not call this tool speculatively, and never call it more than once for the same quote id.",
"user_auth_required": false,
"request_definition": {
"method": "POST",
"path": "/bookings",
"body": {
"content_type": "application/json",
"params": {
"quote_id": {
"type": "string",
"description": "The quote id returned by price_trip. The quote holds every component, so no component ids are sent again here."
},
"traveler_names": {
"type": "array",
"items": {
"type": "string"
},
"description": "The full name of every traveler, one entry per person in the party, each matching the travel document for that traveler. The number of entries must equal the party_size used in search_trip_options."
},
"customer_phone": {
"type": "string",
"description": "The customer WhatsApp phone number."
}
},
"required": ["quote_id", "traveler_names", "customer_phone"]
}
}
}'
Make the booking idempotent on
quote_id. The agent retries after a timeout. If a second call for the same quote creates a second booking, the buyer pays twice for one trip. Return the existing booking instead.Between the quote and the booking, a component can sell out. Decide which behavior your endpoint implements and say so in the
book_trip description, so the agent can explain it rather than guess.| Behavior | When it suits | What the agent must say |
|---|---|---|
Fail the whole booking | Components are useless apart, such as a flight and the hotel at the destination | Nothing was booked, and the other components are still available to rebook |
Book what is available, report the rest | Components stand alone, such as a car that can be added later | Exactly which components were booked and which were not, with the revised total |
Never let a partial booking succeed silently. The buyer finds out at the counter, and the conversation that follows is not one an agent can rescue.
Because the set price may depend on all three components, a partial booking usually reprices the remainder. Return the new total rather than the quoted one, and have the agent state it.
Example conversation
Customer: We want to go to Lisbon in October, two of us, about a week.
Agent: Happy to put that together. Which airport are you flying from, and which dates in October suit you?
Customer: Boston, 4th to the 11th. We will want a car too.
Agent:(calls
search_trip_options)Here is what is available for Boston to Lisbon, 4 to 11 October, for two people:
- Flight — nonstop out 18:40, returning 11:25. Checked bag included.
- Hotel — Baixa district, twin room with breakfast, seven nights.
- Car — compact, collected at the airport, unlimited mileage.
Shall I price those three together?
Customer: Yes please.
Agent:(calls
price_trip)That comes to $2,860 for everything — flights, the seven nights, and the car for the full week. Booking the three together saves $145 against the separate prices.
Customer: Why is it cheaper together?
Agent: The car is discounted when it is booked with a flight and hotel on the same dates. If you drop the car later the other two stay at their original prices, so the saving goes away rather than moving across.
Customer: Makes sense. Let us do it.
Agent: To confirm before I book: Boston to Lisbon, out 4 October 18:40, back 11 October 11:25, twin room with breakfast in Baixa for seven nights, and a compact car from the airport. Total $2,860. I need both travelers’ full names as they appear on their passports. Shall I go ahead?
Customer: Yes. Dana Whitfield and Marco Whitfield.
Agent:(calls
book_trip)Booked — reference AGT-482913. The flight, hotel, and car are all on that one reference, and confirmation is on its way to you now.
What to test
The failures specific to a multi-component sale do not show up in a single-component test plan.
| Scenario | Sample message |
|---|---|
All components | “Flight, hotel, and a car for two, Boston to Lisbon, 4 to 11 October” |
A component declined up front | “Same trip but we do not need a car” |
A component dropped after quoting | “Actually, skip the hotel, we are staying with family” |
A component sells out before booking | Make the vehicle class unavailable between the quote and the confirmation |
The total questioned | “Why is that more than the three prices added up?” |
Confirmation declined | “No, not the early flight” |
A retry after a timeout | Send the confirmation twice and check only one booking exists |
The last one is the one teams skip, and it is the one that charges a customer twice.
Tips for this use case
Price with a quote tool, never in the agent. A total assembled by the agent ignores set discounts, supplements, and tax rules, so it will not match what you charge.
Name every component when quoting and again when confirming. The most common complaint in a multi-component sale is a part the buyer thought was included.
Alert on each tool separately.
search_trip_options is called far more often than the other two, so it dominates the connector totals and will mask a failing book_trip. See Monitor connector health for the logs call and an alerting script.Keep component terms in FAQs. Per-component cancellation rules are the question buyers ask most, and the answer only changes when a policy changes.
Summary checklist
- Defined
search_trip_optionsreturning an offer id per component - Defined
price_tripreturning one total and aquote_id - Defined
book_triptaking only thequote_id, plus a name per traveler and a phone number - Confirmed
book_tripis idempotent onquote_id - Chose a behavior for a component becoming unavailable, and described it in the tool
- Instructed the agent to name every component when quoting and confirming
- Tested a dropped component, a sold-out component, a challenged total, and a retry