Route Ingredient Planning
Use when
Use before generation when the request combines named roads, mandatory POIs, stop cadence, multiple anchors, exclusions, or segment-specific qualities.
Do not use when
Do not use for a simple single-anchor loop, a single parking/start-anchor search, or an ordinary point-to-point request with no mandatory ingredients.
Do not use this as the primary skill for regional climb counts, climb extrema, selected-climb detail, or a route defined by catalog climbs. Use climb-route-intelligence, which passes its selected climb ids into this shared planner contract.
Prefer an explicit ingredient plan before trying a large generation.
Workflow
- Resolve every explicit named start, end, and intermediate anchor with
route.geocode_locations. For an area-only loop such as "around Madison," pass the geocoded area and use its center as the planning start; the backend also infers this anchor when only area.center is supplied.
- Plain explicit/geocoded anchors do not need POI or road discovery. Put them in user-requested order and call
route.generate_multi_point_route exactly once with count: 1 unless alternatives were requested. mode and generation_mode are compatibility aliases; the ordered waypoints determine the geometry. Obey the returned completion.follow_up_policy: a successful route is terminal for this response, so report its actual distance instead of tuning it with a second generation call.
- For a brand-new route with any mandatory support stop, cadence, named road, or mixed discoverable ingredient constraint, call
route.plan_ingredient_options before generation.
For an area route with a stop count but no user-specified cadence, use route_mode: "loop", the target distance, and a count-only need such as {"class":"water","target_count":3}. Do not invent spacing_m or min_spacing_m; the planner distributes repeated stops across even interior route slots. Supply spacing only when the user actually requested an interval or minimum gap.
- Use the planner's recommended pack when the user delegated the choice. The planner may rerank its sidecar packs with cached shortest-path feasibility checks before choosing it. An unresolved mandatory ingredient always makes the pack non-executable: a partial pack with one water stop is never a valid recommendation for a three-water-stop request, even when the user delegated stop choice. If the planner reports a meaningful compromise, network-feasibility risk, or no executable pack, explain it before generating.
- Inspect
generation_contract before generation. Continue only when recommended_next_call is present and external_generation_call_budget is 1; copy its compact {ingredient_plan_ref: ...} arguments verbatim into exactly one route.generate_multi_point_route call. Do not expand the reference or add waypoints, distance, generation_mode, variants, or other fields. The server owns the canonical plan. If the call is null or the budget is 0, do not copy candidates or option-pack waypoints by hand and do not call any generation tool. Correct a missing area/start input once or explain the reported shortfall.
- Treat bounded fallback and distance calibration behind an ordinary plan reference as transparent server-side recovery; they must not be called manually by the model. The server may use up to two internal same-pack calibration passes when all ingredients were reached but distance alone missed tolerance. A climb-only
distance_fill plan is different: preserve the single ranked climb need and its min/max/tolerance fields, then let the server choose a target-fitting CH chain with zero expensive generation jobs. Never synthesize a second waypoint plan, generate a baseline route first, expand one ranked need into several climb ids, or add planned ingredients one at a time.
- Use the returned default 3D profile artifact as the route visual. It should contain normal climb callouts and the verified support-stop POI markers; do not make an extra render call unless the user requests another view or the default artifact is missing.
- Report the selected ingredients and the returned
ingredient_verification, including partial, missed, substituted, and co-satisfied roles. If verification is verified, report the route as complete and do not offer a distance retry merely because the actual distance differs within the accepted tolerance. Keep route/workspace IDs as plain identifiers, never fabricated sandbox: or file links.
Use these exact tool paths; do not invent intermediate planner names:
- New loop or point-to-point route with water, fuel, cafes, restrooms, parks, parking, named roads, or mixed mandatory ingredients:
route.geocode_locations when needed -> route.plan_ingredient_options -> exactly one route.generate_multi_point_route.
- Three or more explicit named/geocoded anchors with no discoverable road or POI requirement:
route.geocode_locations for each unresolved place -> exactly one route.generate_multi_point_route; do not call route.plan_ingredient_options.
- Existing stored route that needs support stops planned along its current corridor:
route.plan_water_stops or route.plan_poi_stops.
- Existing stored route that needs one confirmed stop inserted: search the local cache, then use
route.add_poi_stop.
- Required named roads without other mandatory POIs may use
route.plan_ingredient_options followed by the returned generation call. Use route.generate_named_road_route only when the planner explicitly recommends that specialized path.
route.plan_water_stops and route.plan_poi_stops require an existing stored route. They are follow-up tools, not pre-generation planners.
For requests such as "three water stops, one of them a park", encode the requirements together in poi_needs. One selected stop may co-satisfy multiple roles. Do not search water and parks independently and hope the results line up.
Do not use live Overpass before the ingredient planner. The planner owns cache-first candidate selection and reports whether a fallback is needed.
Use references/agent-recipes.md for multi-stop and desired-road flows.
Postconditions
- The plan reports resolved, partial, substituted, and missing ingredients.
- Mandatory anchors are ordered before route generation and represented by locked waypoints or a stable ingredient pack id.
- Generation starts only when the returned plan is feasible or the user accepts a stated compromise.
- A new-route request performs at most one expensive route-generation job after planning; a climb
distance_fill plan instead performs zero expensive jobs and reports its bounded cheap CH legs separately.
- The MCP tool may make one bounded internal fallback attempt for a clearly infeasible primary pack, but the model still makes exactly one external generation call.
- The final response identifies any co-satisfied role, such as which water stop is also the park.
- Treat a verified stop within the returned waypoint tolerance (normally at most about 100 m) as part of the route. Describe that small access offset as on-route access, not as a reason to offer another full reroute. Offer a corrective edit only when verification marks the stop missed/partial or the offset is materially larger.
1---2name: route-ingredient-planning3description: Multi-ingredient planning for routes that must combine named roads, desired road classes, repeated water/fuel cadence, multiple POIs, exclusions, or several mandatory anchors. Use for "must ride", "avoid", repeated stops, fuel-stop tours, or complex ingredient ordering before generation; use route-poi-stops for a single parking/start-anchor search.4---56# Route Ingredient Planning78## Use when910Use before generation when the request combines named roads, mandatory POIs, stop cadence, multiple anchors, exclusions, or segment-specific qualities.1112## Do not use when1314Do not use for a simple single-anchor loop, a single parking/start-anchor search, or an ordinary point-to-point request with no mandatory ingredients.1516Do not use this as the primary skill for regional climb counts, climb extrema, selected-climb detail, or a route defined by catalog climbs. Use climb-route-intelligence, which passes its selected climb ids into this shared planner contract.1718Prefer an explicit ingredient plan before trying a large generation.1920## Workflow21221. Resolve every explicit named start, end, and intermediate anchor with `route.geocode_locations`. For an area-only loop such as "around Madison," pass the geocoded area and use its center as the planning start; the backend also infers this anchor when only `area.center` is supplied.232. Plain explicit/geocoded anchors do not need POI or road discovery. Put them in user-requested order and call `route.generate_multi_point_route` exactly once with `count: 1` unless alternatives were requested. `mode` and `generation_mode` are compatibility aliases; the ordered waypoints determine the geometry. Obey the returned `completion.follow_up_policy`: a successful route is terminal for this response, so report its actual distance instead of tuning it with a second generation call.243. For a brand-new route with any mandatory support stop, cadence, named road, or mixed discoverable ingredient constraint, call `route.plan_ingredient_options` before generation.25 For an area route with a stop count but no user-specified cadence, use `route_mode: "loop"`, the target distance, and a count-only need such as `{"class":"water","target_count":3}`. Do not invent `spacing_m` or `min_spacing_m`; the planner distributes repeated stops across even interior route slots. Supply spacing only when the user actually requested an interval or minimum gap.264. Use the planner's recommended pack when the user delegated the choice. The planner may rerank its sidecar packs with cached shortest-path feasibility checks before choosing it. An unresolved mandatory ingredient always makes the pack non-executable: a partial pack with one water stop is never a valid recommendation for a three-water-stop request, even when the user delegated stop choice. If the planner reports a meaningful compromise, network-feasibility risk, or no executable pack, explain it before generating.275. Inspect `generation_contract` before generation. Continue only when `recommended_next_call` is present and `external_generation_call_budget` is `1`; copy its compact `{ingredient_plan_ref: ...}` arguments verbatim into exactly one `route.generate_multi_point_route` call. Do not expand the reference or add waypoints, distance, `generation_mode`, `variants`, or other fields. The server owns the canonical plan. If the call is null or the budget is `0`, do not copy candidates or option-pack waypoints by hand and do not call any generation tool. Correct a missing area/start input once or explain the reported shortfall.286. Treat bounded fallback and distance calibration behind an ordinary plan reference as transparent server-side recovery; they must not be called manually by the model. The server may use up to two internal same-pack calibration passes when all ingredients were reached but distance alone missed tolerance. A climb-only `distance_fill` plan is different: preserve the single ranked climb need and its min/max/tolerance fields, then let the server choose a target-fitting CH chain with zero expensive generation jobs. Never synthesize a second waypoint plan, generate a baseline route first, expand one ranked need into several climb ids, or add planned ingredients one at a time.297. Use the returned default 3D profile artifact as the route visual. It should contain normal climb callouts and the verified support-stop POI markers; do not make an extra render call unless the user requests another view or the default artifact is missing.308. Report the selected ingredients and the returned `ingredient_verification`, including partial, missed, substituted, and co-satisfied roles. If verification is `verified`, report the route as complete and do not offer a distance retry merely because the actual distance differs within the accepted tolerance. Keep route/workspace IDs as plain identifiers, never fabricated `sandbox:` or file links.3132Use these exact tool paths; do not invent intermediate planner names:3334- New loop or point-to-point route with water, fuel, cafes, restrooms, parks, parking, named roads, or mixed mandatory ingredients: `route.geocode_locations` when needed -> `route.plan_ingredient_options` -> exactly one `route.generate_multi_point_route`.35- Three or more explicit named/geocoded anchors with no discoverable road or POI requirement: `route.geocode_locations` for each unresolved place -> exactly one `route.generate_multi_point_route`; do not call `route.plan_ingredient_options`.36- Existing stored route that needs support stops planned along its current corridor: `route.plan_water_stops` or `route.plan_poi_stops`.37- Existing stored route that needs one confirmed stop inserted: search the local cache, then use `route.add_poi_stop`.38- Required named roads without other mandatory POIs may use `route.plan_ingredient_options` followed by the returned generation call. Use `route.generate_named_road_route` only when the planner explicitly recommends that specialized path.3940`route.plan_water_stops` and `route.plan_poi_stops` require an existing stored route. They are follow-up tools, not pre-generation planners.4142For requests such as "three water stops, one of them a park", encode the requirements together in `poi_needs`. One selected stop may co-satisfy multiple roles. Do not search water and parks independently and hope the results line up.4344Do not use live Overpass before the ingredient planner. The planner owns cache-first candidate selection and reports whether a fallback is needed.4546Use [references/agent-recipes.md](references/agent-recipes.md) for multi-stop and desired-road flows.4748## Postconditions4950- The plan reports resolved, partial, substituted, and missing ingredients.51- Mandatory anchors are ordered before route generation and represented by locked waypoints or a stable ingredient pack id.52- Generation starts only when the returned plan is feasible or the user accepts a stated compromise.53- A new-route request performs at most one expensive route-generation job after planning; a climb `distance_fill` plan instead performs zero expensive jobs and reports its bounded cheap CH legs separately.54- The MCP tool may make one bounded internal fallback attempt for a clearly infeasible primary pack, but the model still makes exactly one external generation call.55- The final response identifies any co-satisfied role, such as which water stop is also the park.56- Treat a verified stop within the returned waypoint tolerance (normally at most about 100 m) as part of the route. Describe that small access offset as on-route access, not as a reason to offer another full reroute. Offer a corrective edit only when verification marks the stop missed/partial or the offset is materially larger.