-
Notifications
You must be signed in to change notification settings - Fork 1
features ai agent
Active contributors: Saksham, Ravi
The AI agent is a conversational real estate concierge built on Pydantic AI. It streams responses to the client over SSE, calls into the same shared tool layer as the MCP servers, persists full conversation history (including tool calls and results), and supports both authenticated and guest modes with role-aware tool sets and system prompts.
app/api/api_v1/endpoints/
└── agent_chat.py # /agent/chat, /agent/chat-public, conversations CRUD
app/services/ai_agent/
├── __init__.py
├── agent_service.py # Agent instance, stream_response, message history builder
├── conversation_store.py # get_or_create_conversation, add_message, get_history, list
├── system_prompt.py # role-aware prompts (guest, user, admin)
├── tool_bridge.py # deprecated shim re-exporting from tools/
└── tools/
├── __init__.py # USER_TOOLS, ADMIN_TOOLS, GUEST_TOOLS, get_tools_for_role
├── discovery.py # guest_property_search, guest_property_details, guest_property_recommendations
├── owner.py # owner_* and agent_* tools (676 lines)
├── tenant.py # tenant_* tools
├── booking.py # bookings_* and agent_bookings_* tools
├── helpers.py # AgentDeps, _user_schema
└── visits.py # visits re-exports
app/models/
└── ai_conversations.py # AIConversation, AIConversationMessage
| Abstraction | File | Role |
|---|---|---|
Agent |
app/services/ai_agent/agent_service.py |
Pydantic AI Agent built on OpenAIChatModel via OpenAIProvider
|
stream_response |
app/services/ai_agent/agent_service.py |
Async generator yielding SSE events for model deltas + tool calls |
_build_message_history |
app/services/ai_agent/agent_service.py |
Reconstructs ModelMessage list including ToolCallPart / ToolReturnPart pairs |
get_tools_for_role |
app/services/ai_agent/tools/__init__.py |
Returns GUEST_TOOLS, USER_TOOLS, or USER_TOOLS + ADMIN_TOOLS
|
get_system_prompt |
app/services/ai_agent/system_prompt.py |
Assembles BASE_PROMPT + role-specific section |
get_or_create_conversation |
app/services/ai_agent/conversation_store.py |
Loads or creates an AIConversation row |
add_message |
app/services/ai_agent/conversation_store.py |
Persists messages with role, content, tool_name, tool_args, tool_result |
AgentDeps |
app/services/ai_agent/tools/helpers.py |
Dependency container passed to Pydantic AI tools |
The agent is constructed with OpenAIChatModel (configured via settings) and OpenAIProvider. Each chat request resolves the user's role, calls get_tools_for_role(role) to pick the tool set, calls get_system_prompt(role) to build the prompt, loads conversation history via conversation_store.get_history, and runs Agent.run_stream with the reconstructed ModelMessage history. The streaming response yields Pydantic AI events (PartStartEvent, PartDeltaEvent, FunctionToolCallEvent, FunctionToolResultEvent) which the service formats into SSE events (text_delta, tool_call, tool_result, done, error).
graph TD
Client -->|POST /agent/chat| EP[app/api/.../agent_chat.py]
EP -->|release main pool| DBClose[db.close]
DBClose --> Stream[StreamingResponse event_stream]
Stream --> BG[AsyncSessionLocalBG background pool]
BG --> SVC[agent_service.stream_response]
SVC --> Role[resolve role: guest/user/agent/admin]
Role --> Tools[get_tools_for_role]
Role --> Prompt[get_system_prompt]
SVC --> Hist[conversation_store.get_history]
Hist --> Build[_build_message_history]
Build --> Run[Agent.run_stream]
Run -->|PartDeltaEvent| SSE1[event: text_delta]
Run -->|FunctionToolCallEvent| SSE2[event: tool_call]
Run -->|tool execution| ToolFn[tools/owner.py / tenant.py / booking.py / discovery.py]
ToolFn --> OPS[shared logic with MCP tool_ops]
Run -->|FunctionToolResultEvent| SSE3[event: tool_result]
SVC --> Persist[conversation_store.add_message]
Persist --> Conv[(AIConversation, AIConversationMessage)]
Client -->|POST /agent/chat-public| Pub[agent_chat_public]
Pub -->|no persistence| Guest[guest-only tools, no history]
Tool execution is shared with the MCP servers. The tools/ package re-implements the tool functions as Pydantic AI tools (not MCP wire calls), but they delegate to the same app/mcp/tool_ops/ and app/services/* layer. USER_TOOLS covers owner, tenant, booking, and system tools. ADMIN_TOOLS adds agent-scoped property, lease, rent, maintenance, booking, and dashboard tools. GUEST_TOOLS exposes only guest_property_search, guest_property_details, and guest_property_recommendations.
The system prompt is role-aware. BASE_PROMPT sets the persona ("360Ghar AI Assistant, a helpful real estate concierge") and guidelines (use tools, no fabrication, markdown formatting, short answers, confirm writes). USER_TOOLS_SECTION lists owner, tenant, booking, and system capabilities. ADMIN_TOOLS_SECTION adds managed properties, lease management, rent collection, maintenance management, booking management, and dashboard capabilities. GUEST_TOOLS_SECTION plus GUEST_FOOTER instruct the agent to offer sign-in for authenticated features but never refuse property search.
Conversation persistence stores every turn in AIConversationMessage rows with role (user, assistant, tool_call, tool_result), content, tool_name, tool_args, and tool_result. _build_message_history reconstructs the full Pydantic AI ModelMessage list including ToolCallPart / ToolReturnPart pairs so the LLM retains tool context across turns. The first user message auto-generates a conversation title (truncated to 60 chars).
Guest mode (/agent/chat-public) is rate-limited at 10 requests per 60 seconds per IP via EndpointRateLimiter and uses no conversation persistence — each request is stateless with an empty history. Both endpoints release the main-pool DB session before streaming and use AsyncSessionLocalBG for tool calls, matching the SSE session-hygiene pattern.
-
MCP tool_ops: tools delegate to
app/mcp/tool_ops/andapp/services/*, sharing logic with the MCP servers. -
Widget metadata:
agent_serviceimportsget_widget_name_for_toolfromapp/mcp/chatgptso tool calls can include widget hints in their SSE events. -
Service layer: all tools ultimately call
app/services/*functions for Ghar Core, 360 Stays, and Property Management operations. - DB session hygiene: streaming endpoints release the main pool and use the background pool, per the infrastructure pattern.
-
Auth:
/agent/chatrequiresget_current_active_user;/agent/chat-publicis unauthenticated but rate-limited.
Add a new agent tool by implementing it in app/services/ai_agent/tools/, registering it in the appropriate USER_TOOLS / ADMIN_TOOLS / GUEST_TOOLS list in tools/__init__.py, and updating the relevant section of system_prompt.py so the model knows the capability exists. New tools should delegate to app/mcp/tool_ops/ to avoid duplicating MCP logic. The tool_bridge.py shim is deprecated — import from tools/ directly.
| File | Purpose |
|---|---|
app/api/api_v1/endpoints/agent_chat.py |
Chat + conversation CRUD endpoints (300 lines) |
app/services/ai_agent/agent_service.py |
Agent instance + streaming (381 lines) |
app/services/ai_agent/conversation_store.py |
Conversation persistence |
app/services/ai_agent/system_prompt.py |
Role-aware prompts |
app/services/ai_agent/tools/__init__.py |
Tool registration + get_tools_for_role
|
app/services/ai_agent/tools/owner.py |
Owner + agent tools (676 lines) |
app/services/ai_agent/tools/tenant.py |
Tenant tools |
app/services/ai_agent/tools/booking.py |
Booking tools |
app/services/ai_agent/tools/discovery.py |
Guest discovery tools |
app/services/ai_agent/tools/helpers.py |
AgentDeps dependency container |
app/services/ai_agent/tool_bridge.py |
Deprecated re-export shim |
app/models/ai_conversations.py |
AIConversation, AIConversationMessage
|
app/mcp/tool_ops/ |
Shared business logic with MCP servers |
- Features overview
- Ghar Core (marketplace)
- 360 Stays (bookings)
- 360 Flatmates
- Property Management
- 360 Virtual Tours
- 360 Data Hub
- MCP servers and widgets
- AI agent
- Blog and SEO
- Notifications
- Vastu analyzer