Database Models

Notification

The main notification model representing a request for merchant admin input.

class Notification(Base):
    __tablename__ = "notifications"

    id: Mapped[int]
    notification_type: Mapped[str]  # NotificationType enum value
    status: Mapped[str]  # NotificationStatus enum value
    created_at: Mapped[datetime]
    updated_at: Mapped[datetime]
    conversation_id: Mapped[int]  # FK to conversations
    context: Mapped[Dict]  # JSON field with notification details
    answer_model_json_schema: Mapped[Dict]  # JSON schema for answer validation
    answer: Mapped[Dict]  # Deprecated - answers stored in context instead

Relationships: - conversation: Many-to-one with Conversation

Field Details:

notification_type

Stored as string (enum value). Must be one of: - "user_question_request": Customer question notification - "user_support_request": Customer support ticket - "driver_order_request": Driver delivery request (future use)

status

Current notification state: - "requested": Sent to merchant admins, awaiting response - "answered": Merchant admin has responded

context

JSON field containing notification-specific data. Common fields: - allow_multiple_answers: bool - Whether notification can be answered multiple times - notification_id: int - Self-reference for propagation to messages - notification_id_prefixed: str - Prefixed ID (e.g., "NOTIF_123") - merchant_user_conversation_user_ids: List[int] - Recipients for closure notifications - lead_phone: str - Customer phone number

Type-Specific Context Fields:

user_question_request: - question: str - Customer's question text - document_id: int - Associated Document ID for Q&A storage

user_support_request: - support_request_reason: str - Why customer needs support - support_request_type: str - AI-classified type (Sales, Returns, Billing, etc.)

answer_model_json_schema

JSON schema defining expected answer structure. Generated from Pydantic models: - UserQuestionAnswerSchema for questions - UserSupportRequestAnswerSchema for support tickets

Used by AnswerNotificationTool to validate admin responses.

answer

Deprecated field. Answer data now stored in context instead to avoid redundancy.


Enums

NotificationType

class NotificationType(str, Enum):
    user_question_request = "user_question_request"
    user_support_request = "user_support_request"
    driver_order_request = "driver_order_request"  # Future use

Values:

user_question_request

Customer asked a question that Cosmo cannot answer from existing knowledge.

Trigger: RequestNotificationTool when knowledge base search fails

Target: Merchant admins

Expected Answer: Plain text answer to the question

user_support_request

Customer requested live agent support or escalated an issue.

Trigger: Customer explicitly requests agent or support flow determines escalation needed

Target: Merchant admins (classified by type: sales, support, returns, etc.)

Expected Answer: Response to customer + optional internal resolution notes

driver_order_request

Request for driver to accept delivery.

Status: Defined but not yet implemented

Future Use: Local delivery notifications


NotificationStatus

class NotificationStatus(str, Enum):
    requested = "requested"
    answered = "answered"

Values:

requested

Notification sent to merchant admins, awaiting response.

State: Initial state when notification created

Transitions to: answered when admin responds

answered

Merchant admin has responded to the notification.

State: Final state (currently no further transitions)

Behavior: - If allow_multiple_answers=False, prevents additional answers - Triggers closure notifications to other admins


Configuration Constants

NOTIFICATION_CONFIG

Defined in service.py, this dictionary maps each notification type to its configuration:

NOTIFICATION_CONFIG = {
    NotificationType.<type>: {
        "requested_fields": List[str],
        "requested_campaign": CommerceDefaultCampaigns,
        "requested_to": "merchant_user" | "conversation_user",
        "answered_fields": List[str],
        "answered_campaign": CommerceDefaultCampaigns,
        "answered_to": "merchant_user" | "conversation_user",
        "answer_schema": BaseModel,
        "allow_multiple_answers": bool,
    }
}

Field Descriptions:

  • requested_fields: Required fields in context when creating notification
  • requested_campaign: Campaign template to send to recipients when requesting
  • requested_to: Whether to send request to merchant_user or conversation_user
  • answered_fields: Required fields in answer context
  • answered_campaign: Campaign template to send when answering (>24h only)
  • answered_to: Whether to send answer to merchant_user or conversation_user
  • answer_schema: Pydantic model for answer validation
  • allow_multiple_answers: Whether notification can be answered multiple times

Document (for user_question_request)

Questions create documents in the knowledge base:

document = Document(
    merchant_id=merchant_id,
    title=question,  # Question text
    content=answer,  # Populated when answered
    category=DocumentCategory.UserQuestion,
    source_type=DocumentSource.FreeInput,
    source="conversation_user"
)

See Document Models for details.

ConversationUser (for merchant routing)

Merchant admin phone numbers are converted to ConversationUser records to enable campaign delivery:

conversation_user = ConversationUser(
    phone_number=merchant_user.phone_number
)

Created automatically if doesn't exist. See User Models for details.


Database Schema Notes

Indexes

  • conversation_id: Indexed for fast lookup by conversation
  • Primary key id: Used with NOTIFICATION_PREFIX for external references

Relationships

  • Conversation.notifications: One-to-many relationship
  • Cascading delete: Notifications deleted when conversation deleted

JSON Fields

Both context and answer_model_json_schema use PostgreSQL JSON type: - Queryable via JSON operators (context['field'].astext) - No schema enforcement at database level (handled by Pydantic) - Default value {} for context

Timestamp Behavior

  • created_at: Set once at creation (default: datetime.utcnow)
  • updated_at: Auto-updated on every modification (onupdate=datetime.utcnow)
  • Both are timezone-aware (DateTime(timezone=True))

Migration Notes

The notification schema was added via Alembic migration a2e7d947fc09_add_notification_schema.py.

Key Changes: - Added notifications table - Added answer_model_json_schema field for dynamic validation - Deprecated answer field in favor of storing answers in context