AI Property Assistant
Per-listing chat assistant with two specialized agents and server-side memory.
Two Agents
| Agent | Handles | Context |
|---|---|---|
| LISTING | Amenities, pitch advice, objection handling, comparisons | Property details, tags, location, sales intelligence |
| PRICING | Price justification, offer explanation, value comparison, cancellation plans | All of LISTING + full price breakdown, bank offers, nightly rates |
Routing
The router picks the agent based on keywords:
"How should I pitch this to a family?" → LISTING agent
"Why is it priced at ₹16,400?" → PRICING agent
"What if they say it's too expensive?" → PRICING agent (has "expensive")
"What amenities does it have?" → LISTING agent
"What cancellation options are available?" → PRICING agent (has "cancellation")
Server-Side Memory
Conversations are stored in PostgreSQL via Spring AI's JdbcChatMemoryRepository. Frontend just sends conversationId + message — no history to maintain.
POST /api/v1/crs/listings/assistant/{listingId}/chat
{
"conversationId": "conv_abc123",
"message": "How should I pitch this to a family?"
}
Follow-up with same conversationId:
{
"conversationId": "conv_abc123",
"message": "What if they say it's too expensive?"
}
The assistant remembers the previous question about families and connects it to the pricing response.
Response
{
"listingId": "lst_abc",
"message": "Start with the private pool and game room...",
"agent": "LISTING"
}
agent field tells the frontend which agent answered.
Quick Suggestions
GET /assistant/{listingId}/start returns contextual suggestions based on listing data:
{
"suggestions": [
"Why is it priced at ₹16,400?",
"How should I pitch this to a family?",
"What objections might a client raise?",
"How does this compare to similar villas?",
"What cancellation options are available?",
"What bank offers apply here?"
]
}