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_insurance_renewal

Intent Spec — auto.book_insurance_renewal

FULL ID:       auto.book_insurance_renewal
VERSION:       v1.0.0
STATUS:        draft
LAST UPDATED:  2026-05-12
DOMAIN:        auto
PRIMARY AGENT: AutoServicesAgent
TTBS WEIGHTS:  time=0.20 taste=0.20 budget=0.30 safety=0.30

User renews their vehicle insurance (third-party-only, comprehensive, zero-dep, or own-damage standalone). Covers IDV declaration, NCB transfer, add-ons (engine protect, RSA, return-to-invoice), instant policy issuance, IRDAI-compliant disclosures. Distinct from new-policy purchase in v1.1+ (auto.buy_new_insurance).

Partner exemplars: Policybazaar, Acko, Digit, Bajaj Allianz, ICICI Lombard, HDFC ERGO, Tata AIG, GoMechanic Insurance, OEM-branded insurance (Maruti Insurance, Hyundai Assurance), authorised agents.


SECTION 1 — INTENT IDENTITY

User wants to renew an existing motor insurance policy on their vehicle. Distinct from:

  • New policy on a newly-purchased vehicle (out of scope v1; v1.1+ auto.buy_new_insurance)
  • finance.buy_motor_insurance — overlaps if classified there in the finance domain (see DOMAIN_AGENT_MAP); this intent is the auto-domain handler with vehicle-context bias
  • Policy claim filing (out of scope v1; v1.1+ auto.file_insurance_claim)
  • Third-party-only renewal that has lapsed >90 days (RTO inspection required; partner may decline)

Single intent per renewal. Multi-vehicle households fire one intent per vehicle.


SECTION 2 — NATURAL LANGUAGE COVERAGE

CLASSIFIES IN

  • "Renew my car insurance"
  • "Bike insurance is expiring next week, renew it"
  • "Comprehensive policy renewal for Innova Crysta"
  • "Zero-dep cover for my Honda City"
  • "Add engine protect to my renewal"
  • "Cheapest motor insurance for my Activa"
  • "Transfer my NCB from last year"
  • "Insurance lapsed 2 months ago, what now?"
  • "Online insurance renewal, no agent"
  • "Maruti Insurance renewal for my Swift"

CLASSIFIES OUT — BORDERLINE NO

  • "Just bought a car, need first insurance" → v1.1+ auto.buy_new_insurance
  • "Help me file a claim" → v1.1+ auto.file_insurance_claim
  • "Insurance for my health" → finance.buy_health_insurance
  • "What's the IDV of my car?" — non-transactional; surfaces in research path

MULTI-INTENT TRIGGERS

  • "Renew insurance + pollution check" → auto.book_insurance_renewal + auto.book_pollution_check
  • "Renew insurance + RC transfer (just bought used)" → auto.book_insurance_renewal + auto.book_rc_transfer
  • "Renew insurance + service due" → auto.book_insurance_renewal + auto.book_general_service

SECTION 3 — INPUT (TOMO → PROVIDER)

{
  "intent": "auto.book_insurance_renewal",
  "request_id": "req_01J9Z...",
  "user_locale": "en-IN",
  "user_currency": "INR",
  "user_location": { "lat": 17.4475, "lng": 78.3563, "city": "Hyderabad" },
  "vehicle": {
    "type": "car",
    "make": "Toyota",
    "model": "Innova Crysta",
    "variant": "GX",
    "fuel_type": "diesel",
    "year_of_manufacture": 2019,
    "registration_number_last4": "1234",
    "registration_state": "TS",                   // STRICT ENUM §6 (Indian state codes)
    "rto_office": "TS09",                         // STRICT ENUM §6 nullable
    "current_odometer_km": 78000
  },
  "current_policy": {
    "expiry_date": "2026-06-12",                  // ISO_DATE
    "policy_type": "comprehensive",               // STRICT ENUM §6
    "insurer_name": "ICICI Lombard",              // free-text but should match an IRDAI-registered insurer
    "claims_filed_last_year": 0,
    "ncb_pct_carry_forward": 25,                  // 0-50 per IRDAI scale
    "has_lapsed": false,
    "lapse_days": null
  },
  "renewal_preferences": {
    "target_policy_type": "comprehensive",        // STRICT ENUM §6
    "idv_preference": "market_value",             // STRICT ENUM §6
    "addons_required": ["zero_dep", "engine_protect", "rsa_24x7"],   // STRICT ENUM §6
    "preferred_tenure_years": 1,                  // 1 | 2 | 3 (multi-year covers)
    "instant_issuance_required": true,
    "preferred_insurers": []                       // empty = open to all
  },
  "ttbs_user_band": {
    "time":   "fast",                              // user often renews close to expiry
    "taste":  "balanced",
    "budget": "good",
    "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_insurance_renewal
vehicle.registration_state enum REQUIRED, STRICT ENUM §6 Indian state codes only (v1 India-only)
vehicle.rto_office string REQUIRED nullable Drives state-specific premium calculation
current_policy.expiry_date string REQUIRED, ISO_DATE Drives urgency + NCB carry rules
current_policy.policy_type enum REQUIRED, STRICT ENUM §6
current_policy.ncb_pct_carry_forward int REQUIRED, 0-50 IRDAI scale: 0/20/25/35/45/50
current_policy.has_lapsed bool REQUIRED TRUE blocks instant_issuance and may require inspection
current_policy.lapse_days int REQUIRED nullable Required when has_lapsed=true
renewal_preferences.target_policy_type enum REQUIRED, STRICT ENUM §6
renewal_preferences.idv_preference enum REQUIRED, STRICT ENUM §6 market_value / max / custom
renewal_preferences.addons_required array REQUIRED, STRICT ENUM §6 May be empty

Anti-fabrication preamble: Provider may not quote a premium below the IRDAI third-party floor for the vehicle. NCB transfer requires verifiable past-policy claim history. All disclosures must conform to IRDAI's prescribed format.


SECTION 4 — PROVIDER TOOLS

Tool 1: search_insurance_quotes

PURPOSE:      Up to 12 quotes across insurers matching vehicle + policy_type + addons
SLA:          p50 ≤ 800ms, p95 ≤ 2500ms, p99 ≤ 5000ms
RATE LIMIT:   60 req/min
IDEMPOTENCY:  request_id; 30s cache (premiums fluctuate)
RETRY:        1 on 429, 2 on 5xx

Tool 2: confirm_quote_and_kyc

PURPOSE:      Lock chosen quote + collect IRDAI-required KYC
SLA:          p50 ≤ 1500ms, p95 ≤ 4000ms
RATE LIMIT:   30 req/min
IDEMPOTENCY:  request_id
RETRY:        No retry

Tool 3: issue_policy

PURPOSE:      Issue policy after KYC clear + payment confirmation
SLA:          p50 ≤ 2500ms, p95 ≤ 7000ms, p99 ≤ 15000ms (insurer downstream)
RATE LIMIT:   30 req/min
IDEMPOTENCY:  request_id; same id returns same policy
RETRY:        No retry on issuance

Tool 4: cancel_or_freelook

PURPOSE:      15-day IRDAI free-look cancellation OR pre-issuance cancellation
SLA:          p50 ≤ 1500ms, p95 ≤ 4000ms
RATE LIMIT:   30 req/min
IDEMPOTENCY:  policy_id
RETRY:        1 on 5xx

SECTION 5 — RESPONSE SHAPE

InsuranceQuote

InsuranceQuote:
  quote_id: { type: string, constraint: REQUIRED, opaque }
  insurer:
    insurer_id: { type: string, constraint: REQUIRED }
    name: { type: string, constraint: REQUIRED }
    irdai_registration_number: { type: string, constraint: REQUIRED }
    claim_settlement_ratio_pct: { type: float, constraint: REQUIRED, 0-100, semantics: "IRDAI-published latest year" }
    solvency_ratio: { type: float, constraint: REQUIRED, 1.0-5.0, semantics: "IRDAI-published" }

  policy_type:
    type: enum
    constraint: REQUIRED, STRICT ENUM §6
    values: [third_party_only, comprehensive, own_damage_only, standalone_od_with_separate_tp]

  idv_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0, semantics: "Insured Declared Value at this premium" }
  idv_basis:
    type: enum
    constraint: REQUIRED, STRICT ENUM §6
    values: [market_value, depreciated, declared_max, custom]

  premium_breakdown:
    own_damage_premium_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
    third_party_premium_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0, semantics: "IRDAI-tariff floor enforced" }
    addons_premium_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
    ncb_discount_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
    gst_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0, semantics: "18% on premium" }
    total_payable_inr: { type: int, constraint: REQUIRED, INR_INTEGER }

  ncb_applied_pct: { type: int, constraint: REQUIRED, 0-50 }

  tenure_years: { type: int, constraint: REQUIRED, 1-3 }
  policy_start_date: { type: string, constraint: REQUIRED, ISO_DATE }
  policy_end_date: { type: string, constraint: REQUIRED, ISO_DATE }

  addons_included:
    type: array<Addon>
    constraint: REQUIRED, may be empty
    shape:
      code: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
      label: { type: string, constraint: REQUIRED }
      premium_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }

  cashless_garage_count_in_state: { type: int, constraint: REQUIRED, ≥0 }
  cashless_garage_count_in_city: { type: int, constraint: REQUIRED, ≥0 }

  inspection_required: { type: boolean, constraint: REQUIRED, semantics: "TRUE when policy lapsed >90 days or claim history flags" }
  instant_issuance_possible: { type: boolean, constraint: REQUIRED }
  estimated_issuance_minutes: { type: int, constraint: REQUIRED, 1-2880 }

  policy_wording_url: { type: string, constraint: REQUIRED, HTTPS URL, semantics: "IRDAI-compliant policy document" }

  partner_reference:
    source: { type: string, constraint: REQUIRED }
    deeplink: { type: string, constraint: REQUIRED, HTTPS URL }

KYCResult

KYCResult:
  kyc_id: { type: string, constraint: REQUIRED }
  quote_id: { type: string, constraint: REQUIRED }
  kyc_status:
    type: enum
    constraint: REQUIRED, STRICT ENUM §6
    values: [verified_aadhaar, verified_pan, verified_dl, pending_manual, failed]
  documents_required:
    type: array<string>
    constraint: REQUIRED, may be empty
    semantics: any pending docs partner needs (e.g. previous policy copy if NCB transfer)
  ckyc_id: { type: string, constraint: REQUIRED nullable, semantics: "Central KYC reference if available" }
  expires_at: { type: string, constraint: REQUIRED, ISO_DATETIME, ≤24h }

IssuedPolicy

IssuedPolicy:
  policy_id: { type: string, constraint: REQUIRED, immutable }
  policy_number: { type: string, constraint: REQUIRED, semantics: "insurer-issued formal number" }
  insurer_id: { type: string, constraint: REQUIRED }
  policy_type: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
  policy_start_date: { type: string, constraint: REQUIRED, ISO_DATE }
  policy_end_date: { type: string, constraint: REQUIRED, ISO_DATE }
  total_paid_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
  policy_pdf_url: { type: string, constraint: REQUIRED, HTTPS URL, semantics: "signed URL ≥30 days validity" }
  certificate_of_insurance_url: { type: string, constraint: REQUIRED, HTTPS URL }
  freelook_period_days: { type: int, constraint: REQUIRED, 7-30, semantics: "IRDAI-mandated free-look (default 15)" }
  freelook_ends_at: { type: string, constraint: REQUIRED, ISO_DATE }
  claim_helpline_phone: { type: string, constraint: REQUIRED, E.164 }

CancellationResult

CancellationResult:
  policy_id: { type: string, constraint: REQUIRED }
  cancelled_at: { type: string, constraint: REQUIRED, ISO_DATETIME }
  refund_amount_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
  refund_method: { type: enum, constraint: REQUIRED, STRICT ENUM §6, values: [original_payment, bank_transfer, cheque] }
  refund_eta_days: { type: int, constraint: REQUIRED, 0-30 }
  is_freelook_cancellation: { type: boolean, constraint: REQUIRED }

FORBIDDEN FIELDS

  • paid_placement_score, ad_bid, sponsored_rank, promotion_priority, kickback_amount, commission_padded_premium
  • artificial_urgency_text (no "Premium goes up in 6 hours!" without actual rate-change basis)
  • ai_generated_photo for insurer logos / certificate previews
  • below_irdai_floor_premium (any premium below IRDAI tariff floor is per-se invalid)
  • inflated_claim_settlement_ratio (must match IRDAI-published value)

SECTION 6 — CONTROLLED VOCABULARIES

vehicle.registration_state:
  values:
    AP, AR, AS, BR, CG, GA, GJ, HR, HP, JH, KA, KL, MP, MH, MN, ML, MZ, NL, OD,
    PB, RJ, SK, TN, TS, TR, UP, UK, WB,
    AN, CH, DN, DD, DL, JK, LA, LD, PY

vehicle.rto_office:
  values: { semantics: "any RTO code e.g. TS09, MH12; partner accepts free-text within state" }

current_policy.policy_type:
  values:
    third_party_only:   "TP-only (legal minimum)"
    comprehensive:      "TP + Own Damage"
    own_damage_only:    "OD only (TP held separately or expiring vehicle in last year)"
    standalone_od_with_separate_tp: "Standalone OD + separately purchased TP"

idv_preference / idv_basis:
  values:
    market_value:  "Standard market value (default)"
    depreciated:   "Depreciated per IRDAI scale"
    declared_max:  "Max IDV permissible"
    custom:        "User-declared (within IRDAI bounds)"

addons.code:
  values:
    zero_dep:           "Zero depreciation cover"
    engine_protect:     "Engine protection"
    rsa_24x7:           "24x7 roadside assistance"
    return_to_invoice:  "Return-to-invoice cover"
    consumables:        "Consumables cover"
    ncb_protect:        "NCB protection"
    key_replacement:    "Key replacement cover"
    passenger_cover:    "Passenger PA cover"
    tyre_protect:       "Tyre protection"

renewal_preferences.target_policy_type:
  values: { third_party_only, comprehensive, own_damage_only }

kyc_status:
  values: { verified_aadhaar, verified_pan, verified_dl, pending_manual, failed }

refund_method: { values: { original_payment, bank_transfer, cheque } }

SECTION 7 — TTBS DIMENSIONS

TIME (weight = 0.20):
  signals_used:
    - instant_issuance_possible
    - estimated_issuance_minutes
    - inspection_required (FALSE preferred)
  weighting:
    instant: 0.50
    minutes: 0.30
    inspection_avoided: 0.20

TASTE (weight = 0.20):
  signals_used:
    - insurer matches preferred_insurers (if set)
    - insurer matches user DNA history
    - cashless_garage_count_in_city
  weighting:
    preferred_insurer: 0.40 (when preference set)
    dna_familiarity: 0.30
    cashless_in_city: 0.30

BUDGET (weight = 0.30):
  signals_used:
    - premium_breakdown.total_payable_inr
    - addons_included matching addons_required exactly (avoid over-bundling)
  weighting:
    total: 0.75
    addon_fit: 0.25

SAFETY (weight = 0.30):
  signals_used:
    - insurer.claim_settlement_ratio_pct
    - insurer.solvency_ratio
    - cashless_garage_count_in_state
    - policy_wording_url (IRDAI-compliant)
  weighting:
    csr: 0.40
    solvency: 0.25
    cashless_state: 0.25
    wording_compliant: 0.10
  user_band_handling:
    fast: relax CSR floor to 90%
    balanced: floor 92%
    flexible: prefer CSR ≥95% even at higher premium

SECTION 8 — COMPLETION CONTRACT

POST /api/v1/cpc/mcp_provider/<your_partner_id>
Body:
{
  "intent":           "auto.book_insurance_renewal",
  "external_id":      "<policy_id>",
  "request_id":       "<request_id>",
  "amount_inr":       2400,    // NET partner commission revenue (typically 5-15% of premium)
  "gst_inr":          432,
  "tips_inr":         0,
  "pass_through_inr": 18000,   // premium amount remitted to insurer — NOT supplier revenue
  "closed_at":        "2026-05-30T11:20:00+05:30",
  "status":           "completed",
  "insurer_id": "icici_lombard",
  "policy_type": "comprehensive",
  "policy_tenure_years": 1,
  "addons_count": 3
}

Important: For motor insurance, the customer pays the FULL premium (e.g. ₹18,000), but only the partner's commission (~₹2,400) is partner revenue. amount_inr reflects ONLY the partner's commission. The remitted premium goes in pass_through_inr. TOMO charges 10% × amount_inr = ₹240 — not 10% of ₹18,000.

HMAC, 5-min replay, NET-only commission.


SECTION 9 — WIDGET

InsuranceRenewalWidget (planned). Interim: comparison ListingsWidget.

Field mapping:
  - InsuranceQuote.insurer.name + logo → header
  - claim_settlement_ratio_pct → CSR pill (color-coded by ≥95 / 92-95 / <92)
  - premium_breakdown.total_payable_inr → big price
  - ncb_applied_pct → "NCB X%" pill
  - addons_included.length → "X add-ons" pill
  - cashless_garage_count_in_city → "X cashless garages" pill
  - instant_issuance_possible → green instant badge
  - policy_wording_url → "Read the wording" link

SECTION 10 — CACHING POLICY

Call TTL Rationale
search_insurance_quotes 30s Premiums fluctuate; insurer APIs price live
confirm_quote_and_kyc NO CACHE Idempotent by request_id
issue_policy NO CACHE Idempotent; never retry
cancel_or_freelook NO CACHE
Insurer static (CSR, solvency, logos) 24h IRDAI publishes annually

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
VEHICLE_NOT_FOUND_IN_VAHAN 422 Registration not found in govt VAHAN database No
POLICY_NOT_RENEWABLE 422 Past 90-day lapse + claim flag No (UI suggests new-policy intent)
KYC_FAILED 422 PAN / Aadhaar mismatch No (user re-submits)
IDV_OUT_OF_RANGE 422 Declared IDV outside permissible band No
ADDON_INCOMPATIBLE 422 Requested addon unavailable for policy_type No (UI re-prompts)
INSPECTION_REQUIRED 200 (advisory) Returns inspection_required=true in quote n/a
PAYMENT_FAILED 402 Gateway declined No (user re-tries)
INSURER_DOWN 503 Insurer API unavailable 1 retry, 2s
FREELOOK_WINDOW_EXPIRED 410 (cancel) Past free-look period No

SECTION 12 — SANDBOX → PRODUCTION CHECKLIST

[ ] All four tools implemented
[ ] At least 5 insurers in catalog (covering ICICI Lombard / Bajaj Allianz / HDFC ERGO / Tata AIG / Acko or similar)
[ ] All insurer IRDAI registration numbers verifiable on irdai.gov.in
[ ] claim_settlement_ratio_pct and solvency_ratio match latest IRDAI annual publication
[ ] All controlled vocabularies respected
[ ] HMAC signing verified
[ ] amount_inr in CPC is partner COMMISSION only (NET), NOT total premium
[ ] pass_through_inr correctly captures premium remitted to insurer
[ ] policy_wording_url returns IRDAI-compliant policy document
[ ] policy_pdf_url returns valid issued policy
[ ] freelook_period_days ≥ 7 (IRDAI minimum, default 15)
[ ] inspection_required correctly TRUE for lapsed >90 days policies
[ ] No forbidden fields anywhere
[ ] SLA p95 met (policy issuance can be slow due to insurer downstream)
[ ] IRDAI POSP / corporate agent license uploaded
[ ] Compliance docs: GSTIN, IRDAI license, privacy policy URL

SECTION 13 — ANTI-FABRICATION RULES

RULE 1: No paid_placement / ad / kickback. Sustained promotion of higher-
        commission insurers irrespective of TTBS = suspension.

RULE 2: claim_settlement_ratio_pct MUST match IRDAI's latest annual
        publication. Inflating CSR to win rank = brand-relationship breach +
        immediate suspension. TOMO audits quarterly against IRDAI data.

RULE 3: solvency_ratio MUST match IRDAI publication. Same enforcement.

RULE 4: third_party_premium_inr cannot be below the IRDAI tariff floor for
        the vehicle (cc-banded). Below-floor quotes are per-se invalid and
        rejected by ingest.

RULE 5: ncb_applied_pct must reflect verifiable past claim history. Awarding
        NCB to a user with claims = customer-harming fraud + insurer-relationship
        breach. TOMO requires partner to record past-policy verification trail
        and audits on a sample basis.

RULE 6: irdai_registration_number must be the insurer's actual current
        registration. Mock / expired numbers = immediate suspension.

RULE 7: policy_wording_url must be IRDAI-compliant. Linking to a marketing
        page rather than the actual policy document = customer-harm + IRDAI
        regulatory risk + suspension.

RULE 8: Addon premium must match insurer-published rate cards. Padding addon
        prices to inflate commission = suspension after 2 incidents.

RULE 9: artificial_urgency_text forbidden ("Renew in 6 hours or lose your
        NCB!"). NCB rules are time-bound (90-day grace) but specific countdown
        copy must be factually accurate per IRDAI.

RULE 10: No AI-generated insurer logos or policy preview imagery. Real
         insurer brand assets only, under brand-use agreements.

RULE 11: amount_inr in CPC is partner's NET commission only — NEVER the
         total premium remitted to insurer. Partners falsely reporting
         premium as their revenue to inflate commission base = suspension.
         TOMO audits via partner's IRDAI-filed accounts.

RULE 12: No "Top Pick" / "Editor's Choice" / "TOMO Recommended" badges.
         Insurance recommendation is regulated; TOMO does not advise — it
         orchestrates source-blind ranking via TTBS.

RULE 13: cashless_garage_count_in_state and _in_city must reflect insurer's
         actual published network for that geography. Stale or fabricated
         numbers = customer-harm risk.

VERSION HISTORY

v1.0.0 — 2026-05-12 — Initial spec. NET commission base in §8 (partner
                       commission only, not premium remitted). IRDAI-floor
                       enforcement + CSR/solvency anti-fabrication rules.
                       Free-look mandated per regulator.