Intent Spec — auto.book_tyre_alignment
FULL ID: auto.book_tyre_alignment
VERSION: v1.0.0
STATUS: draft
LAST UPDATED: 2026-05-11
DOMAIN: auto
PRIMARY AGENT: AutoServicesAgent
TTBS WEIGHTS: time=0.30 taste=0.10 budget=0.30 safety=0.30
User books wheel alignment / balancing / tyre rotation — any combination. Often standalone ("car pulls to one side"), often paired with new-tyre fitment. Distinct from a full general service. Quick turnaround (45min–2h).
Partner exemplars: TyrePlus, MRF Tyredrome, Apollo Tyres dealers, JK Tyre Steel Wheels, GoMechanic Wheel Care, Carnation Auto, OEM-authorised workshops with alignment bay.
SECTION 1 — INTENT IDENTITY
This intent fires when a user wants alignment, balancing, or rotation. Distinct from:
auto.book_general_service— periodic service that may include alignment as one stepauto.book_breakdown_assist— emergency, vehicle stranded- New-tyre purchase (currently bundled here when alignment_after_new_tyres=true; v1.1 may split to
auto.book_tyre_replacement)
Single intent fires per booking. New tyres bundled within this intent's scope when partner offers and user opts in.
SECTION 2 — NATURAL LANGUAGE COVERAGE
CLASSIFIES IN
- "Book wheel alignment"
- "Car pulls to the left, need alignment"
- "Wheel balancing for my Swift"
- "Alignment and balancing combo"
- "Tyre rotation due"
- "I want to get new tyres + alignment"
- "Steering wheel vibrates at speed, alignment problem?"
- "Front-end alignment near me"
- "Cheapest 4-wheel alignment in Hyderabad"
- "Computerised wheel alignment"
CLASSIFIES OUT — BORDERLINE NO
- "My car broke down on the road, tyre punctured" →
auto.book_breakdown_assist - "Service my car" →
auto.book_general_service - "Car wash and tyre clean" →
auto.book_car_wash - "Suspension overhaul" →
auto.book_major_service
MULTI-INTENT TRIGGERS
- "Alignment + car wash" →
auto.book_tyre_alignment+auto.book_car_wash - "New tyres, alignment, and full service" →
auto.book_tyre_alignment(with new-tyre scope) +auto.book_general_service
SECTION 3 — INPUT (TOMO → PROVIDER)
{
"intent": "auto.book_tyre_alignment",
"request_id": "req_01J9Z...",
"user_locale": "en-IN",
"user_currency": "INR",
"user_location": { "lat": 17.4475, "lng": 78.3563, "max_radius_km": 10, "city": "Hyderabad" },
"vehicle": {
"type": "car",
"make": "Maruti Suzuki",
"model": "Swift",
"variant": "VXi",
"fuel_type": "petrol",
"year_of_manufacture": 2021,
"registration_number_last4": "1234",
"current_odometer_km": 42500,
"wheel_count": 4, // STRICT ENUM via integer: 2 | 4
"tyre_size": "185/65R15" // user-declared; partner may verify
},
"service_scope": {
"alignment": true,
"balancing": true,
"rotation": true,
"alignment_type":
"four_wheel_computerised", // STRICT ENUM §6
"new_tyres_required": false,
"tyre_brand_preference": "any" // STRICT ENUM §6, used only when new_tyres_required=true
},
"service_preferences": {
"preferred_window": {
"start": "2026-05-13T10:00:00+05:30",
"end": "2026-05-13T19:00:00+05:30"
},
"while_you_wait_acceptable": true
},
"ttbs_user_band": {
"time": "balanced",
"taste": "balanced",
"budget": "ok",
"safety": "good"
},
"session_context": {
"tomo_session_id": "ses_01J9Z...",
"user_dna_hash": "dna_v3_a7c9..."
}
}
| Field | Type | Constraint | Notes |
|---|---|---|---|
intent |
string | REQUIRED, STRICT ENUM | Always auto.book_tyre_alignment |
vehicle.wheel_count |
int | REQUIRED, 2 or 4 | |
vehicle.tyre_size |
string | REQUIRED, ISO size format | Partner may re-verify physically |
service_scope.alignment |
bool | REQUIRED | At least one of alignment/balancing/rotation MUST be true |
service_scope.balancing |
bool | REQUIRED | |
service_scope.rotation |
bool | REQUIRED | |
service_scope.alignment_type |
enum | REQUIRED, STRICT ENUM §6 | Only relevant when alignment=true |
service_scope.new_tyres_required |
bool | REQUIRED | TRUE expands scope to include tyre fitment |
service_scope.tyre_brand_preference |
enum | REQUIRED, STRICT ENUM §6 | Relevant only when new_tyres_required=true |
service_preferences.while_you_wait_acceptable |
bool | REQUIRED |
Anti-fabrication preamble: Provider may not steer toward higher-margin tyre brands when user wants any-brand. Alignment-type recommendations must be technical, not commercial.
SECTION 4 — PROVIDER TOOLS
Tool 1: search_alignment_slots
PURPOSE: Return up to 15 slots matching window + location + scope
INPUT: §3
OUTPUT: array<AlignmentSlot> per §5
SLA: p50 ≤ 500ms, p95 ≤ 1500ms, p99 ≤ 3000ms
RATE LIMIT: 60 req/min
IDEMPOTENCY: request_id; 60s cache
RETRY: 1 on 429, 2 on 5xx
Tool 2: create_alignment_booking
PURPOSE: Confirm slot + scope
INPUT: { request_id, slot_id, vehicle.*, service_scope.*, contact_phone, selected_tyre_skus[]? }
OUTPUT: AlignmentBooking per §5
SLA: p50 ≤ 1200ms, p95 ≤ 3500ms
RATE LIMIT: 30 req/min
IDEMPOTENCY: request_id
RETRY: No retry
Tool 3: cancel_alignment_booking
PURPOSE: Cancel pre-arrival
INPUT: { request_id, booking_id, reason_code }
OUTPUT: CancellationResult per §5
SLA: p50 ≤ 600ms, p95 ≤ 1500ms
RATE LIMIT: 30 req/min
RETRY: 1 on 5xx
SECTION 5 — RESPONSE SHAPE
AlignmentSlot
AlignmentSlot:
slot_id: { type: string, constraint: REQUIRED }
provider:
provider_id: { type: string, constraint: REQUIRED }
name: { type: string, constraint: REQUIRED }
provider_type:
type: enum
constraint: REQUIRED, STRICT ENUM §6
values: [tyre_brand_outlet, oem_authorised, multi_brand_garage, dedicated_alignment_shop]
address: { type: string, constraint: REQUIRED }
location: { type: object, shape: { lat, lng }, constraint: REQUIRED }
distance_from_user_km: { type: float, constraint: REQUIRED, 0-25 }
equipment:
alignment_machine_type:
type: enum
constraint: REQUIRED, STRICT ENUM §6
values: [manual_gauge, computerised_3d, computerised_laser, mobile_unit]
balancer_type:
type: enum
constraint: REQUIRED, STRICT ENUM §6
values: [static, dynamic, road_force]
slot_window:
start: { type: string, constraint: REQUIRED, ISO_DATETIME }
end: { type: string, constraint: REQUIRED, ISO_DATETIME }
typical_duration_minutes: { type: int, constraint: REQUIRED, 30-240 }
service_offered:
alignment_supported: { type: boolean, constraint: REQUIRED }
balancing_supported: { type: boolean, constraint: REQUIRED }
rotation_supported: { type: boolean, constraint: REQUIRED }
new_tyre_fitment_supported: { type: boolean, constraint: REQUIRED }
pricing:
alignment_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0, semantics: "0 if not in scope" }
balancing_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
rotation_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
combo_discount_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0, semantics: "applied when ≥2 services together" }
gst_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
total_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
fixed_price_guaranteed: { type: boolean, constraint: REQUIRED }
new_tyres:
available_skus:
type: array<TyreSku>
constraint: REQUIRED when service_scope.new_tyres_required=true, may be empty otherwise
shape:
sku: { type: string, constraint: REQUIRED }
brand: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
pattern_name: { type: string, constraint: REQUIRED, e.g. "MRF ZLX" }
size_string: { type: string, constraint: REQUIRED, matches vehicle.tyre_size }
treadwear_rating: { type: int, constraint: REQUIRED, 100-800 }
load_index: { type: int, constraint: REQUIRED, 60-130 }
speed_rating: { type: enum, constraint: REQUIRED, STRICT ENUM §6, values: [S, T, H, V, W, Y] }
per_tyre_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
warranty_months: { type: int, constraint: REQUIRED, 0-72 }
logistics:
while_you_wait_available: { type: boolean, constraint: REQUIRED }
drop_off_pickup_available: { type: boolean, constraint: REQUIRED }
free_wifi_lounge: { type: boolean, constraint: REQUIRED }
ratings:
avg_rating: { type: float, constraint: REQUIRED, 0-5 }
review_count: { type: int, constraint: REQUIRED, ≥0 }
return_visit_rate_pct: { type: int, constraint: REQUIRED, 0-100, semantics: "alignment-redo rate within 30 days; lower = better" }
partner_reference:
source: { type: string, constraint: REQUIRED }
deeplink: { type: string, constraint: REQUIRED, HTTPS URL }
AlignmentBooking
AlignmentBooking:
booking_id: { type: string, constraint: REQUIRED, immutable }
slot_id: { type: string, constraint: REQUIRED }
scheduled_start: { type: string, constraint: REQUIRED, ISO_DATETIME }
estimated_completion: { type: string, constraint: REQUIRED, ISO_DATETIME }
scope_confirmed:
type: array<string>
constraint: REQUIRED, ≥1
example: ["alignment", "balancing", "rotation"]
selected_tyres:
type: array<string>
constraint: REQUIRED, list of sku from new_tyres.available_skus, may be empty
total_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
alignment_report_promised: { type: boolean, constraint: REQUIRED, semantics: "before/after measurements report" }
payment_due_at:
type: enum
constraint: REQUIRED, STRICT ENUM §6
values: [now, on_arrival, on_completion]
service_advisor_phone: { type: string, constraint: REQUIRED, E.164 }
CancellationResult
CancellationResult:
booking_id: { type: string, constraint: REQUIRED }
cancelled_at: { type: string, constraint: REQUIRED, ISO_DATETIME }
cancellation_fee_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
refund_amount_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
refund_eta_days: { type: int, constraint: REQUIRED, 0-7 }
FORBIDDEN FIELDS
paid_placement_score,ad_bid,sponsored_rank,promotion_prioritykickback_amount,referral_fee_kickback,_partner_revenue_shareartificial_urgency_textai_generated_photofor shop / tyre imagerycommission_padded_priceunnecessary_alignment_recommendation— partner may not recommend alignment when measurements within spec
SECTION 6 — CONTROLLED VOCABULARIES
service_scope.alignment_type:
values:
two_wheel_basic: "Two-wheel alignment (front only)"
four_wheel_basic: "Four-wheel non-computerised"
four_wheel_computerised: "Four-wheel computerised alignment (modern standard)"
laser_3d: "Laser / 3D camera-based alignment (premium)"
service_scope.tyre_brand_preference:
values:
any: "Open to any brand"
mrf: "MRF"
apollo: "Apollo Tyres"
jk: "JK Tyre"
ceat: "CEAT"
bridgestone: "Bridgestone"
michelin: "Michelin"
yokohama: "Yokohama"
continental: "Continental"
goodyear: "Goodyear"
provider_type:
values:
tyre_brand_outlet: "Brand-owned tyre outlet (TyrePlus, Apollo etc.)"
oem_authorised: "Vehicle OEM authorised workshop with alignment bay"
multi_brand_garage: "Independent multi-brand garage"
dedicated_alignment_shop: "Specialist alignment shop"
equipment.alignment_machine_type:
values:
manual_gauge: "Manual measurement gauges (older; less precise)"
computerised_3d: "Computerised 3D measurement"
computerised_laser: "Laser-based computerised"
mobile_unit: "Mobile alignment unit (doorstep)"
equipment.balancer_type:
values:
static: "Static balancer (basic)"
dynamic: "Dynamic / on-vehicle balancer"
road_force: "Road-force balancer (premium; for vibration diagnostics)"
new_tyres.speed_rating:
values:
S: "Up to 180 km/h"
T: "Up to 190 km/h"
H: "Up to 210 km/h"
V: "Up to 240 km/h"
W: "Up to 270 km/h"
Y: "Up to 300 km/h"
payment_due_at:
values:
now: "Pay at booking"
on_arrival: "Pay at workshop check-in"
on_completion: "Pay at handover"
SECTION 7 — TTBS DIMENSIONS
TIME (weight = 0.30):
signals_used:
- provider.distance_from_user_km
- slot_window.start vs user window center
- typical_duration_minutes
- logistics.while_you_wait_available (boost if user opted in)
weighting:
distance: 0.25
slot_fit: 0.35
duration: 0.25
wait_friendly: 0.15
user_band_handling:
fast: prefer while_you_wait + short duration
balanced: standard
flexible: any in window
TASTE (weight = 0.10):
signals_used:
- provider_type vs user DNA (brand_outlet vs multi_brand)
- equipment.alignment_machine_type matching scope (computerised vs manual)
- tyre brand preference when new tyres in scope
weighting:
type: 0.35
equipment: 0.40
brand: 0.25
user_band_handling: standard
BUDGET (weight = 0.30):
signals_used:
- pricing.total_inr (with combo_discount_inr factored)
- new_tyres.per_tyre_inr × wheel_count when new tyres in scope
weighting:
service_price: 0.60
tyre_price: 0.40
user_band_handling:
ok: prefer cheapest with computerised alignment minimum
good: balance price vs equipment tier
great: prefer laser_3d + road_force balancer even at premium
SAFETY (weight = 0.30):
signals_used:
- equipment.alignment_machine_type (computerised/laser ranked higher; manual penalised)
- ratings.return_visit_rate_pct (lower = better — well-aligned vehicles don't need redos)
- alignment_report_promised on AlignmentBooking
- ratings.avg_rating
weighting:
equipment_tier: 0.35
return_rate: 0.30
report: 0.15
rating: 0.20
user_band_handling:
fast: relax equipment tier
balanced: standard
flexible: prefer lowest return_visit_rate
SECTION 8 — COMPLETION CONTRACT
POST /api/v1/cpc/mcp_provider/<your_partner_id>
Body:
{
"intent": "auto.book_tyre_alignment",
"external_id": "<booking_id>",
"request_id": "<request_id>",
"amount_inr": 1800, // NET (service charges + supplier-margin on tyres if sold, supplier-kept)
"gst_inr": 324, // government
"tips_inr": 0,
"pass_through_inr": 0,
"closed_at": "2026-05-13T15:20:00+05:30",
"status": "completed", // STRICT ENUM: completed | cancelled_by_user | cancelled_by_partner | no_show
"scope_actually_performed": ["alignment", "balancing"], // may differ from requested if partner found rotation unnecessary
"new_tyres_fitted_count": 0,
"alignment_report_url": "https://partner.example.com/reports/abc123.pdf"
}
HMAC, 5-min replay, NET-only commission.
SECTION 9 — WIDGET
TyreAlignmentWidget (planned). Interim: generic ListingsWidget.
Field mapping:
- AlignmentSlot.provider.name → header
- AlignmentSlot.provider_type + distance_from_user_km → subline 1
- AlignmentSlot.slot_window.start + typical_duration_minutes + while_you_wait_available → subline 2
- AlignmentSlot.pricing.total_inr (combo_discount strikethrough when applies) → price row
- AlignmentSlot.equipment.alignment_machine_type + balancer_type → "Computerised 3D · Road-force" pill
- AlignmentSlot.ratings.return_visit_rate_pct → "X% return rate" pill (lower=better, color-coded)
When new_tyres_required=true:
- AlignmentSlot.new_tyres.available_skus rendered as expandable tyre-picker
SECTION 10 — CACHING POLICY
| Call | TTL | Rationale |
|---|---|---|
search_alignment_slots |
60s | Slot churn moderate |
create_alignment_booking |
NO CACHE | Idempotent by request_id |
cancel_alignment_booking |
NO CACHE | — |
| Provider static (equipment, accreditations) | 6h | Static |
| Tyre catalog (skus, sizes, treadwear) | 24h | Static |
SECTION 11 — ERROR CODES
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
INVALID_REQUEST |
400 | Payload malformed | No |
INVALID_AUTH |
401 | Bad creds | No |
RATE_LIMITED |
429 | Throttle | 1, 2s |
INTERNAL_ERROR |
500 | Partner failure | 2, exp |
IDEMPOTENCY_VIOLATION |
409 | request_id reused | No |
SIGNATURE_INVALID |
401 (webhook) | HMAC fail | No |
TYRE_SIZE_INVALID |
422 | tyre_size not parseable / not in partner's standard set | No |
NO_SLOTS_IN_WINDOW |
200 (empty) | Valid, no matches | n/a |
SLOT_GONE |
409 (create) | Slot taken | No |
TYRE_SKU_OUT_OF_STOCK |
409 (create) | Selected new tyre SKU unavailable | No; UI re-prompts |
WHEEL_COUNT_INCOMPATIBLE |
422 | wheel_count not supported (e.g. partner doesn't service 2-wheelers) | No |
EQUIPMENT_UNDER_MAINTENANCE |
422 | Alignment machine down at requested slot | No |
CANCELLATION_FEE_DUE |
200 (cancel) | Non-zero fee returned | n/a |
SECTION 12 — SANDBOX → PRODUCTION CHECKLIST
[ ] All three tools implemented; shapes per §5
[ ] Multiple equipment tiers offered (at least one computerised, one manual or laser_3d)
[ ] Tyre catalog populated when new_tyres_required=true (at least 3 brands for common sizes)
[ ] All controlled vocabularies respected (alignment_type, brand, speed_rating)
[ ] HMAC signing verified
[ ] amount_inr is NET in CPC payload
[ ] alignment_report_url returns valid PDF/JSON with before/after measurements when alignment_report_promised=true
[ ] scope_actually_performed in CPC may differ from requested (partner found rotation unnecessary)
[ ] No forbidden fields
[ ] SLA p95 met: search ≤1500ms, create ≤3500ms
[ ] Idempotency tested
[ ] return_visit_rate_pct computed from real data (not flat marketing value)
[ ] Compliance docs: GSTIN, brand authorisation (when claimed), privacy policy URL live
SECTION 13 — ANTI-FABRICATION RULES
RULE 1: No paid_placement / ad / kickback fields. Single occurrence rejects response.
Partners may not surface higher-margin tyre brands first when user
explicitly chose tyre_brand_preference != any.
RULE 2: equipment.alignment_machine_type claims must match the actual equipment
on premises. Claiming computerised_3d when only manual_gauge is on
floor is grounds for immediate suspension. TOMO inspects via on-site
photo verification during compliance review.
RULE 3: alignment_report_promised=true means partner must provide a real
before/after measurement report (PDF or structured JSON). Issuing
a placeholder report is grounds for review.
RULE 4: ratings.return_visit_rate_pct must reflect real alignment redos
within 30 days (same vehicle returning for the same complaint).
TOMO maintains its own ratio from CPC re-bookings; >10% deviation
flags review.
RULE 5: new_tyres.treadwear_rating, load_index, speed_rating, warranty_months
must match the tyre manufacturer's published spec. Inflating any
of these to win rank is forbidden.
RULE 6: combo_discount_inr must be a real discount applied when ≥2 services
booked together. Partners cannot inflate individual service prices
and call the "regular price" a discount.
RULE 7: unnecessary_alignment_recommendation forbidden. If partner's
measurements show alignment is within manufacturer spec, partner
must say so and not perform / bill alignment. Sustained "found
out-of-spec on every vehicle" patterns flag review.
RULE 8: AI-generated shop / tyre photos forbidden. Real imagery required.
RULE 9: No "Top Pick" / "TOMO Recommended" badges. TTBS source-blind.
RULE 10: Tyre SKU pricing must match (or be less than) MRP. Above-MRP
pricing is illegal and grounds for immediate suspension.
RULE 11: artificial_urgency_text forbidden ("Your tyres won't last another
month!" without odometer-based wear evidence).
VERSION HISTORY
v1.0.0 — 2026-05-11 — Initial spec. NET commission base in §8.