T
TOMO
Developer Docs
BETA These docs are under partner review. Some features described are roadmap items, not yet shipped. Verify against your sandbox before relying on any contract.
● DRAFTv1.0.0auto.book_tyre_alignment

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 step
  • auto.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_priority
  • kickback_amount, referral_fee_kickback, _partner_revenue_share
  • artificial_urgency_text
  • ai_generated_photo for shop / tyre imagery
  • commission_padded_price
  • unnecessary_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.