Intent Spec — auto.book_paint_job
FULL ID: auto.book_paint_job
VERSION: v1.0.0
STATUS: draft
LAST UPDATED: 2026-05-12
DOMAIN: auto
PRIMARY AGENT: AutoServicesAgent
TTBS WEIGHTS: time=0.15 taste=0.30 budget=0.25 safety=0.30
User books paint repair, panel respray, or full-body paint job — scratch repair, accident paint repair, full repaint, denting + painting combo, custom colour. Distinct from detailing's paint correction (which polishes existing paint without repainting). Higher safety weight because mismatched colour or poor body-prep work surfaces 6-12 months later.
Partner exemplars: 3M Body Shop, ASA Body Shops, OEM-authorised body shops (Maruti Service / Hyundai Body Shop), Carnation Auto, GoMechanic Body, local specialist body shops.
SECTION 1 — INTENT IDENTITY
User wants actual paint applied (not polish/correction) to a vehicle panel or whole body. Distinct from:
auto.book_detailing— paint correction polishes existing paint; this intent applies new paintauto.book_major_service— major mechanical work; may include body repair as separate sub-jobauto.book_breakdown_assist— emergency- Wrap install (vinyl) — separate intent in v1.1+ (
auto.book_wrap)
Single intent per booking. Multi-panel jobs (e.g. both doors + bumper) are one intent. Denting + painting combo is in-scope (most India body shops bundle).
SECTION 2 — NATURAL LANGUAGE COVERAGE
CLASSIFIES IN
- "Repaint my bumper"
- "Scratch on the door, need touch-up"
- "Full body respray for my Innova"
- "Accident repair — bonnet + fender need painting"
- "Match the colour for my Hyundai Verna"
- "Pearl white paint job estimate"
- "Denting + painting for rear quarter panel"
- "Repaint over rust spot"
- "Insurance claim — body shop authorised by Bajaj Allianz"
- "Quote for repainting the whole car"
CLASSIFIES OUT — BORDERLINE NO
- "Polish the paint" →
auto.book_detailing - "PPF / film install" →
auto.book_detailing(current scope) or v1.1+auto.book_wrap - "Touch-up pen for tiny scratches" → not in scope (DIY)
- "Engine work after accident" →
auto.book_major_service
MULTI-INTENT TRIGGERS
- "Paint job + general service" →
auto.book_paint_job+auto.book_general_service - "Body work + insurance claim assistance" →
auto.book_paint_job+auto.book_insurance_renewal(latter handles claim filing in v1.1+) - "Repaint before selling" →
auto.book_paint_job+auto.book_rc_transfer
SECTION 3 — INPUT (TOMO → PROVIDER)
{
"intent": "auto.book_paint_job",
"request_id": "req_01J9Z...",
"user_location": { "lat": 17.4475, "lng": 78.3563, "max_radius_km": 25, "city": "Hyderabad" },
"vehicle": {
"type": "car",
"size_class": "sedan",
"make": "Hyundai",
"model": "Verna",
"variant": "SX",
"year_of_manufacture": 2020,
"registration_number_last4": "1234",
"paint_code": "PGU", // OEM paint code; user may not know
"paint_color_name": "Polar White Pearl",
"current_color_changed": false, // user repainted away from OEM colour previously
"panel_count": 4 // size proxy for full-body estimates
},
"job_scope": {
"scope_type": "panel_repair", // STRICT ENUM §6
"panels_to_paint": ["front_bumper", "left_front_door"], // STRICT ENUM §6
"denting_required": true,
"damage_severity": "moderate", // STRICT ENUM §6
"match_oem_color_exactly": true,
"preferred_paint_brand": "any", // STRICT ENUM §6
"insurance_claim_intended": true,
"insurer_name": "Bajaj Allianz" // free-text when insurance_claim_intended=true
},
"service_preferences": {
"preferred_window": {
"earliest_drop_off": "2026-05-16T09:00:00+05:30",
"latest_pickup": "2026-05-25T18:00:00+05:30"
},
"max_acceptable_cost_inr": 25000,
"loaner_vehicle_required": true,
"oem_authorised_only": false // user open to multi-brand if quality verified
},
"ttbs_user_band": { "time": "flexible", "taste": "great", "budget": "good", "safety": "great" },
"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_paint_job |
vehicle.paint_code |
string | REQUIRED nullable | When null, body shop colour-matches from VIN |
vehicle.paint_color_name |
string | REQUIRED nullable | Human-readable fallback |
vehicle.current_color_changed |
bool | REQUIRED | TRUE means VIN colour ≠ actual colour; impacts insurance |
job_scope.scope_type |
enum | REQUIRED, STRICT ENUM §6 | |
job_scope.panels_to_paint |
array |
REQUIRED when scope_type=panel_repair, STRICT ENUM §6 | |
job_scope.denting_required |
bool | REQUIRED | TRUE bundles denting labour into quote |
job_scope.damage_severity |
enum | REQUIRED, STRICT ENUM §6 | |
job_scope.match_oem_color_exactly |
bool | REQUIRED | TRUE means partner uses VIN-matched paint mix |
job_scope.insurance_claim_intended |
bool | REQUIRED | Steers cashless workflow |
Anti-fabrication preamble: Provider may not claim OEM-matched paint without using the actual VIN-mixed code. Body-prep skipping (no primer, no rust treatment) cannot be hidden by promised warranty.
SECTION 4 — PROVIDER TOOLS
Tool 1: search_body_shops
PURPOSE: Up to 10 body shops capable of scope
SLA: p50 ≤ 700ms, p95 ≤ 1800ms, p99 ≤ 3500ms
RATE LIMIT: 60 req/min
IDEMPOTENCY: request_id; 120s cache
RETRY: 1 on 429, 2 on 5xx
Tool 2: book_assessment
PURPOSE: Book mandatory in-person damage assessment for fixed quote
SLA: p50 ≤ 1000ms, p95 ≤ 3000ms
RATE LIMIT: 30 req/min
IDEMPOTENCY: request_id
RETRY: No retry
Tool 3: get_assessment_quote
PURPOSE: Post-assessment itemized quote
SLA: p50 ≤ 600ms, p95 ≤ 1800ms
RATE LIMIT: 60 req/min
RETRY: 1 on 5xx
Tool 4: confirm_paint_booking
PURPOSE: Lock paint job after quote approval
SLA: p50 ≤ 1500ms, p95 ≤ 4000ms
RATE LIMIT: 30 req/min
IDEMPOTENCY: request_id
RETRY: No retry
Tool 5: cancel_paint_booking
SLA: p50 ≤ 700ms, p95 ≤ 2000ms
RATE LIMIT: 30 req/min
RETRY: 1 on 5xx
SECTION 5 — RESPONSE SHAPE
BodyShop
BodyShop:
shop_id: { type: string, constraint: REQUIRED }
name: { type: string, constraint: REQUIRED }
shop_type:
type: enum
constraint: REQUIRED, STRICT ENUM §6
values: [oem_authorised_body_shop, multi_brand_premium, brand_authorised_paint, independent_specialist]
authorised_paint_brands:
type: array<enum>
constraint: REQUIRED, may be empty
values: [3m, axalta, ppg, glasurit, dupont, du_pont, asian_paints_auto, indigo_paints]
cashless_insurance_partners:
type: array<string>
constraint: REQUIRED, may be empty
semantics: insurer names this shop has cashless agreements with
address: { type: string, constraint: REQUIRED }
location: { type: object, shape: { lat, lng }, constraint: REQUIRED }
distance_from_user_km: { type: float, constraint: REQUIRED, 0-30 }
indoor_paint_booth: { type: boolean, constraint: REQUIRED, semantics: "climate-controlled spray booth" }
capabilities:
handles_color_matching_from_vin: { type: boolean, constraint: REQUIRED }
handles_full_body_repaint: { type: boolean, constraint: REQUIRED }
handles_pearl_metallic: { type: boolean, constraint: REQUIRED }
handles_custom_colors: { type: boolean, constraint: REQUIRED }
handles_denting_bundled: { type: boolean, constraint: REQUIRED }
capacity:
earliest_assessment_slot: { type: string, constraint: REQUIRED, ISO_DATETIME }
typical_turnaround_days:
single_panel: { type: int, constraint: REQUIRED, 1-4 }
multi_panel: { type: int, constraint: REQUIRED, 3-10 }
full_body: { type: int, constraint: REQUIRED, 7-21 }
loaner_vehicle_available: { type: boolean, constraint: REQUIRED }
estimated_cost_range_inr:
low: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
high: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
semantics: { type: string, constraint: REQUIRED }
warranty:
paint_warranty_months: { type: int, constraint: REQUIRED, 6-60, semantics: "against peel/fade" }
workmanship_warranty_months: { type: int, constraint: REQUIRED, 3-24 }
color_match_guarantee: { type: boolean, constraint: REQUIRED, semantics: "shop redos if mismatch visible at delivery" }
warranty_terms_url: { type: string, constraint: REQUIRED, HTTPS URL }
process_disclosures:
primer_layer_count: { type: int, constraint: REQUIRED, 1-4 }
clearcoat_layer_count: { type: int, constraint: REQUIRED, 1-3 }
rust_treatment_included: { type: boolean, constraint: REQUIRED }
bake_oven_used: { type: boolean, constraint: REQUIRED }
before_after_gallery_url: { type: string, constraint: REQUIRED, HTTPS URL, semantics: "real photo gallery" }
ratings:
avg_rating: { type: float, constraint: REQUIRED, 0-5 }
review_count: { type: int, constraint: REQUIRED, ≥0 }
rework_rate_pct_last_90d: { type: int, constraint: REQUIRED, 0-100 }
partner_reference:
source: { type: string, constraint: REQUIRED }
deeplink: { type: string, constraint: REQUIRED, HTTPS URL }
AssessmentBooking
AssessmentBooking:
assessment_id: { type: string, constraint: REQUIRED, immutable }
shop_id: { type: string, constraint: REQUIRED }
scheduled_at: { type: string, constraint: REQUIRED, ISO_DATETIME }
assessor_name: { type: string, constraint: REQUIRED }
assessor_phone: { type: string, constraint: REQUIRED, E.164 }
assessment_fee_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
fee_waived_if_repair_proceeds: { type: boolean, constraint: REQUIRED }
PaintQuote
PaintQuote:
quote_id: { type: string, constraint: REQUIRED }
assessment_id: { type: string, constraint: REQUIRED }
validity_until: { type: string, constraint: REQUIRED, ISO_DATETIME, ≥7d }
damage_assessment:
type: array<DamageItem>
constraint: REQUIRED, ≥1
shape:
panel: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
damage_type: { type: enum, constraint: REQUIRED, STRICT ENUM §6, values: [scratch, dent, dent_and_scratch, rust, crack, full_repaint_needed] }
severity: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
photo_url: { type: string, constraint: REQUIRED, HTTPS URL }
labour_hours: { type: float, constraint: REQUIRED, 0.5-40 }
line_items:
type: array<LineItem>
constraint: REQUIRED, ≥1
shape:
sku: { type: string, constraint: REQUIRED }
description: { type: string, constraint: REQUIRED }
category: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
total_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
necessity: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
insurance_handling:
cashless_eligible: { type: boolean, constraint: REQUIRED }
insurer_pre_approval_required: { type: boolean, constraint: REQUIRED }
estimated_deductible_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
estimated_depreciation_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
estimated_out_of_pocket_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
totals:
subtotal_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
gst_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
total_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
PaintBooking
PaintBooking:
booking_id: { type: string, constraint: REQUIRED, immutable }
quote_id: { type: string, constraint: REQUIRED }
drop_off_at: { type: string, constraint: REQUIRED, ISO_DATETIME }
estimated_pickup: { type: string, constraint: REQUIRED, ISO_DATETIME }
loaner_arranged: { type: boolean, constraint: REQUIRED }
total_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
insurance_path:
type: enum
constraint: REQUIRED, STRICT ENUM §6
values: [cashless, reimbursement, no_claim]
service_advisor_phone: { type: string, constraint: REQUIRED, E.164 }
payment_due_at: { type: enum, constraint: REQUIRED, STRICT ENUM §6, values: [50_percent_now_balance_on_pickup, on_pickup, insurance_cashless_then_deductible] }
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-21 }
FORBIDDEN FIELDS
paid_placement_score,ad_bid,sponsored_rank,promotion_priority,kickback_amountartificial_urgency_textai_generated_photofor before/after / damage assessment imagery (CRITICAL — real photos only)commission_padded_pricepaint_warranty_inflatedfalse_oem_match_claim
SECTION 6 — CONTROLLED VOCABULARIES
job_scope.scope_type:
values:
scratch_only: "Single scratch repair (clearcoat only or single layer)"
panel_repair: "1-4 specific panels"
multi_panel: "5+ panels"
full_body: "Entire vehicle"
custom_color_change: "Repaint to non-OEM colour"
job_scope.panels_to_paint:
values:
front_bumper, rear_bumper,
bonnet, boot,
left_front_door, left_rear_door, right_front_door, right_rear_door,
left_front_fender, right_front_fender,
left_rear_quarter, right_rear_quarter,
roof,
left_running_board, right_running_board
job_scope.damage_severity:
values:
minor: "Surface scratch, no dent"
moderate: "Scratch + minor dent OR deep scratch"
major: "Significant denting + paint loss"
severe: "Panel replacement may be required"
job_scope.preferred_paint_brand:
values: { any, 3m, axalta, ppg, glasurit, dupont, asian_paints_auto, indigo_paints }
shop_type:
values:
oem_authorised_body_shop: "Vehicle OEM authorised body shop"
multi_brand_premium: "Premium multi-brand body shop"
brand_authorised_paint: "Paint brand authorised applicator (3M / PPG etc.)"
independent_specialist: "Independent body shop"
damage_assessment.damage_type:
values: { scratch, dent, dent_and_scratch, rust, crack, full_repaint_needed }
line_item.category:
values: { labour, paint, primer, clearcoat, panel_replacement, denting, rust_treatment, masking, sublet }
line_item.necessity:
values: { mandatory_for_safety, mandatory_for_warranty, recommended, optional }
insurance_path:
values:
cashless: "Insurer pays partner directly; user pays deductible only"
reimbursement: "User pays partner; user files claim for refund"
no_claim: "User pays out of pocket; no claim filed"
payment_due_at:
values: { 50_percent_now_balance_on_pickup, on_pickup, insurance_cashless_then_deductible }
SECTION 7 — TTBS DIMENSIONS
TIME (weight = 0.15):
signals_used: [distance, earliest_assessment_slot, typical_turnaround_days]
TASTE (weight = 0.30):
signals_used:
- shop_type matching oem_authorised_only filter
- authorised_paint_brands matching preferred_paint_brand
- capabilities.handles_pearl_metallic / handles_color_matching_from_vin matching scope
weighting:
type: 0.30
brand: 0.35
capability: 0.35
BUDGET (weight = 0.25):
signals_used:
- estimated_cost_range_inr
- insurance_handling.cashless_eligible (TRUE bonus — lower out-of-pocket)
weighting:
cost: 0.70
cashless_bonus: 0.30
SAFETY (weight = 0.30):
signals_used:
- warranty.paint_warranty_months
- warranty.workmanship_warranty_months
- warranty.color_match_guarantee
- process_disclosures.bake_oven_used (TRUE preferred for durability)
- process_disclosures.rust_treatment_included (when damage_type includes rust)
- ratings.rework_rate_pct_last_90d (LOWER better)
weighting:
paint_warranty: 0.25
workmanship_warranty: 0.15
color_match: 0.20
bake_oven: 0.15
rework_rate: 0.25
SECTION 8 — COMPLETION CONTRACT
POST /api/v1/cpc/mcp_provider/<your_partner_id>
Body:
{
"intent": "auto.book_paint_job",
"external_id": "<booking_id>",
"request_id": "<request_id>",
"amount_inr": 6400, // NET (supplier-kept labour + paint margin)
"gst_inr": 1152,
"tips_inr": 0,
"pass_through_inr": 0, // none typically; sublet may apply rarely
"closed_at": "2026-05-22T15:00:00+05:30",
"status": "completed",
"scope_performed": "panel_repair",
"panels_painted_count": 2,
"insurance_settled": true,
"color_match_signed_off": true,
"warranty_card_issued": true
}
HMAC, 5-min replay, NET-only commission.
SECTION 9 — WIDGET
PaintJobWidget (planned).
Field mapping:
- BodyShop.name → header
- shop_type + paint brand badges → subline 1
- distance + typical_turnaround_days[scope] → subline 2
- estimated_cost_range_inr → range pill
- warranty.paint_warranty_months + color_match_guarantee → warranty badges
- cashless_insurance_partners (when insurance_claim_intended) → cashless badges
- before_after_gallery_url → expandable gallery
- ratings.rework_rate_pct_last_90d → "X% rework rate" pill (lower=green)
SECTION 10 — CACHING POLICY
| Call | TTL |
|---|---|
| search_body_shops | 120s |
| book_assessment | NO CACHE |
| get_assessment_quote | 5min |
| confirm_paint_booking | NO CACHE |
| cancel_paint_booking | NO CACHE |
| Shop static (paint brands, cashless partners, warranties) | 6h |
SECTION 11 — ERROR CODES
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
INVALID_REQUEST |
400 | Malformed | No |
RATE_LIMITED |
429 | Throttle | 1, 2s |
INTERNAL_ERROR |
500 | Partner failure | 2, exp |
SIGNATURE_INVALID |
401 (webhook) | HMAC fail | No |
NO_SHOPS_IN_AREA |
200 (empty) | Valid, no matches | n/a |
PAINT_CODE_NOT_AVAILABLE |
422 | OEM paint code not in shop's stocked range | No |
PANEL_REPLACEMENT_NEEDED |
200 (advisory in quote) | Damage too severe; line item flags panel_replacement | n/a |
INSURER_NOT_PARTNERED |
422 | Cashless not possible; UI offers reimbursement path | No |
ASSESSMENT_FEE_DUE_FIRST |
402 | User must pay assessment fee before scheduling | No |
QUOTE_EXPIRED |
410 (confirm) | quote.validity_until passed | No |
INSURANCE_PRE_APPROVAL_FAILED |
422 | Insurer rejected cashless pre-approval | No |
CANCELLATION_FEE_DUE |
200 (cancel) | Non-zero fee | n/a |
SECTION 12 — SANDBOX → PRODUCTION CHECKLIST
[ ] All five tools implemented
[ ] At least 3 body shops covering different paint brands
[ ] handles_color_matching_from_vin verifiable via test VIN lookup
[ ] indoor_paint_booth claims backed by uploaded shop photos
[ ] cashless_insurance_partners list backed by uploaded MOU letters
[ ] All controlled vocabularies respected
[ ] HMAC signing verified
[ ] amount_inr is NET in CPC
[ ] color_match_signed_off in CPC reflects real user sign-off (not auto-set)
[ ] No forbidden fields
[ ] SLA p95 met
[ ] before_after_gallery_url returns real customer photos (not stock)
[ ] paint_warranty_months matches paint brand's published warranty
[ ] Compliance docs: GSTIN, shop license, paint brand authorisations, insurer cashless MOUs, privacy policy URL
SECTION 13 — ANTI-FABRICATION RULES
RULE 1: No paid_placement / ad / kickback. Rejects response.
RULE 2: authorised_paint_brands and cashless_insurance_partners claims
require uploaded current-year authorisation/MOU documents.
False claims = immediate suspension + brand/insurer relationship breach.
RULE 3: paint_warranty_months MUST match the paint brand's published warranty.
Inflating to win rank = suspension after 2 incidents.
RULE 4: color_match_guarantee=true means partner redos colour at no charge if
user signs off on mismatch at delivery. Declining a colour-match redo
within window = suspension. TOMO requires color_match_signed_off in
CPC; FALSE there → user filed grievance → opens warranty case.
RULE 5: before_after_gallery_url MUST contain real customer photos. Stock or
AI-generated images = immediate suspension. TOMO field-tests via
reverse image search on a sample.
RULE 6: estimated_cost_range_inr must reflect realistic bounds for the
scope. Padding the high end to make low end look competitive,
then quoting at the high end at assessment, = suspension.
RULE 7: damage_assessment.damage_type and severity must match real damage.
Inflating severity to bill more = customer-harm + insurance-fraud
risk = immediate suspension.
RULE 8: process_disclosures.primer_layer_count / clearcoat_layer_count /
bake_oven_used must reflect actual process. Skipping primer layers
and claiming 2-coat is grounds for immediate suspension when
verified via partner audit.
RULE 9: rust_treatment_included=true requires actual rust converter / primer
application when damage includes rust. TOMO samples user photos
post-delivery vs partner's process record.
RULE 10: false_oem_match_claim — partners claiming OEM colour match while
using close-but-not-exact paint mix is grounds for suspension.
TOMO audits via spectrophotometer reading on a sample.
RULE 11: No artificial_urgency_text. Body work is rarely time-critical.
RULE 12: No "Top Pick" / "TOMO Recommended" badges. Source-blind TTBS only.
RULE 13: line_item.necessity must be honest. Marking optional cosmetic work
as mandatory_for_safety = suspension.
VERSION HISTORY
v1.0.0 — 2026-05-12 — Initial spec. NET commission base. TASTE-dominant
(0.30) — brand & quality matter; SAFETY (0.30) catches
process-skipping (primer skip, no bake oven).