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_premiumartificial_urgency_text(no "Premium goes up in 6 hours!" without actual rate-change basis)ai_generated_photofor insurer logos / certificate previewsbelow_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.