Hayley.AAI
by hyly.AI
Live
⚠ This version contains breaking changes. See Changelog β†’
⌘K
Overview✦Hayley Features
Microservices
SMS AdapterChat AdapterMail AdapterVoice Adapter
Node RetrievalRAG RetrievalFixed Response
Agent OrchestratorHayley EngineTranslate to Human
SPF GeneratorOMC-KgProperty KG
Resources
All ServicesChangelog
APIs
APIsBenchmarksTesting Properties
Tools
Knowledge GraphLogs & AccessHelp & Tools
Microservices β€Ί Adapter β€Ί SMS Adapter

SMS Adapter

v1.0AdapterPublished
Updated 7d ago
v1.0 β€” Published
SMS Adapter β€” Message Lifecycle

Hayley SMS Adapter


Overview

The Hayley Chat Adapter Microservice is an orchestration layer that processes conversational AI queries for property management platforms. It acts as the central hub between the Hayley AI Engine (ML/NLP) and all downstream services.

Core responsibilities:

  • Route and validate chat queries from property management platforms
  • Forward requests to Hayley Engine for intent classification and response generation
  • Format responses based on retrieval type (node,Β rag,Β fixed,Β adapter,Β spf)
  • Persist messages via GraphQL for conversation history
  • Extract contact information (name, phone, email) for agent escalation
  • Support multi-language responses (English / Spanish)
  • Track distributed traces and latency metrics via Langfuse + OpenTelemetry

  • Architecture

    High-Level Flow

    kotlin
    1 2 3 4 5 6 7
    Client
      └─► FastAPI Server (Port 6000)
            └─► Hayley Chat Adapter
                  β”œβ”€β–Ί Hayley Engine (ML/NLP)
                  β”œβ”€β–Ί Translate to Human (Spanish)
                  β”œβ”€β–Ί Agent Handoff Service
                  └─► GraphQL API (Message Persistence)

    Tech Stack

    LayerTechnologyVersion
    Web FrameworkFastAPIβ‰₯ 0.111.0
    ASGI ServerUvicorn0.30.1
    ValidationPydanticlatest
    HTTP Clientrequests, aiohttplatest
    NLPspaCy + en_core_web_mdβ‰₯ 3.7.0
    Phone Parsingphonenumbersβ‰₯ 8.13.0
    Cachingfastapi-cache2 (InMemory)latest
    Token Countingtiktoken (cl100k_base)latest
    Logginglogurulatest
    LLM ObservabilityLangfuseβ‰₯ 3.11.2
    Distributed TracingOpenTelemetryβ‰₯ 1.28.0
    ConfigPyYAMLlatest

    Directory Structure

    markdown
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
    hayley-chat-adapter-microservice/
    β”œβ”€β”€ app.py                        ← FastAPI entrypoint, endpoints, Langfuse init
    β”œβ”€β”€ config.yaml                   ← Environment-specific service URLs
    β”œβ”€β”€ requirements.txt              ← Python dependencies
    β”œβ”€β”€ Dockerfile                    ← Docker build (exposes port 6000)
    β”œβ”€β”€ .env                          ← Secrets and environment variables
    β”‚
    β”œβ”€β”€ bean/
    β”‚   └── chat_adapter_response.py ← Pydantic response model
    β”‚
    β”œβ”€β”€ utils/
    β”‚   β”œβ”€β”€ chat_adapter.py          ← Core orchestration logic
    β”‚   β”œβ”€β”€ utils.py                 ← GraphQL, caching, contact extraction
    β”‚   β”œβ”€β”€ arguments.py             ← Constants and defaults
    β”‚   └── constants.py             ← System-wide constants
    β”‚
    └── deployments/
        β”œβ”€β”€ qa/Jenkinsfile
        β”œβ”€β”€ stg/Jenkinsfile
        └── prod/Jenkinsfile

    Request Processing Flow

    plain text
    1 2 3 4 5 6 7 8 9 10 11 12 13
    1.  POST /chat_adapter received
    2.  Pydantic validates request          β†’ 400 on failure
    3.  Trim history to last 4 messages
    4.  Call Hayley Engine
    5.  Format response by retrieval_type:
          "node" + "neighborhood_summary"  β†’ verbose response
          "node"                           β†’ format_node_response_to_markdown()
          "rag|fixed|adapter|spf"          β†’ concise response
    6.  Extract contact info (if sub_intent matches)
    7.  createHayleyMessage [question] via GraphQL
    8.  Fire async agent handoff (non-blocking)
    9.  createHayleyMessage [answer] via GraphQL
    10. Return assembled response with trace_id

    API Contract

    GET /heartbeat

    Health check β€” no request body required.

    Response

    { "success": 200 }


    POST /chat_adapter

    Request

    graphql
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
    {
      "propertyId": "1234567890123456789",
      "message": "Show me available 2-bedroom apartments",
      "orgId": "9876543210987654321",
      "session_id": "aaaabbbbccccddddeeeeffffgggghhhh",
      "conversation_id": "1111111111111111111",
      "graphql_api_key": "Rjp3U6OfhyuxMVSYHCJErDlFeZamWs5QwIX4dKik",
      "tourScheduleEnabled": true,
      "history": [
        { "role": "user", "content": "Hello" },
        { "role": "assistant", "content": "Hi! How can I help?" }
      ],
      "entry_id": "optional-entry-id",
      "booking_id": "optional-booking-id",
      "reschedule_information": {},
      "schedule_information": {},
      "spanish_support_enabled": false,
      "spanish_toggle": false,
      "is_first_entry": false
    }

    Field Validation Rules

    FieldFormatRequired
    propertyId19-digit string or Base64Yes
    orgId19-digit string or Base64Yes
    session_idMD5 hash, UUID v4, orΒ fake_hyly_session_idYes
    conversation_id19-digit string or Base64Yes
    graphql_api_keyBase64URLΒ ^[A-Za-z0-9_-]+$Yes
    tourScheduleEnabledbooleanYes
    historyarray ofΒ { role, content }Yes
    entry_idstringNo
    booking_idstringNo
    reschedule_informationobjectNo
    schedule_informationobjectNo
    spanish_support_enabledboolean (default: false)No
    spanish_toggleboolean (default: false)No
    is_first_entryboolean (default: false)No

    Response

    graphql
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
    {
      "response": "Here are available 2-bedroom units at...",
      "intent": "property_search",
      "sub_intent": "unit_availability",
      "message_id": "1709542253522009420",
      "retrieval_type": "node",
      "orchestrator_level1_details": {},
      "orchestrator_level2_details": {},
      "keyword_cache": { "bedrooms": 2 },
      "not_available": [],
      "context": null,
      "follow_up": "Would you like to schedule a tour?",
      "latency": {
        "hayley_engine_latency": 1234,
        "chat_adapter_latency": 2456,
        "extract_and_update_contact_latency": 45,
        "create_message_latency": 312
      },
      "language": "en",
      "agent_handoff": null,
      "memory": null,
      "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
    }

    Error Responses

    graphql
    1 2 3 4 5 6 7 8
    // 400 β€” Validation error
    { "detail": { "message": "Invalid propertyId format", "trace_id": "4bf92f35..." } }
    
    // 500 β€” Internal error
    { "detail": { "message": "Unexpected error", "trace_id": "4bf92f35..." } }
    
    // 503 β€” Downstream unavailable
    { "detail": "Service temporarily unavailable" }

    Environment URLs

    EnvironmentBase URLHealth Check
    QAhttp://0.0.0.0:6000http://0.0.0.0:6000/heartbeat
    STGhttps://stg2-ml.hyly.ushttps://stg2-ml.hyly.us/.../heartbeat
    Prodhttps://ml2.hy.lyhttps://ml2.hy.ly/.../heartbeat

    Downstream Services by Environment

    ServiceQASTGProd
    Hayley Enginehttp://0.0.0.0:2600/hayley_enginehttps://stg2-ml.hyly.us/hayley_engine_microservice/hayley_enginehttps://ml2.hy.ly/hayley_engine_microservice/hayley_engine
    Translate to Humanhttp://0.0.0.0:7500/tthhttps://stg2-ml.hyly.us/hayley_translate_to_human_microservice/tthhttps://ml2.hy.ly/hayley_translate_to_human_microservice/tth
    Agent Handoffhttps://qa.hyly.us/leads_api/v1/hayley/agent_handoffhttps://my.hyly.us/leads_api/v1/hayley/agent_handoffhttps://my.hy.ly/leads_api/v1/hayley/agent_handoff
    GraphQL APIhttps://qa.hyly.us/graphqlhttps://my.hyly.us/graphqlhttps://my.hy.ly/graphql

    Dependencies

    Internal Microservices

    ServicePurpose
    Hayley EngineML/NLP β€” intent classification and response generation
    Translate to HumanSpanish translation whenΒ spanish_toggle=true
    Agent HandoffHuman escalation β€” async fire-and-forget viaΒ hyly_agent_handoffΒ package
    GraphQL APIMessage persistence β€”Β createHayleyMessage,Β updateHayleyConversation

    External Property Management APIs

    EndpointPurpose
    /api/v1/unitsRetrieve property unit data
    /api/v1/floor_plans/Fetch floor plan information
    /api/v1/apartments/all_type_available_time_slotsGet available tour time slots
    /api/v1/hayley/google_queryExtract neighborhood keywords
    /api/v1/properties/api_tokenFetch GraphQL API token

    Python Packages

    PackageVersionPurpose
    fastapiβ‰₯ 0.111.0Web framework
    uvicorn0.30.1ASGI server
    spacy + en_core_web_mdβ‰₯ 3.7.0Named entity recognition
    phonenumbersβ‰₯ 8.13.0Phone number parsing
    langfuseβ‰₯ 3.11.2LLM observability
    opentelemetry-api/sdkβ‰₯ 1.28.0Distributed tracing
    fastapi-cache2latestIn-memory caching
    tiktokenlatestToken counting
    logurulatestStructured logging
    hyly_agent_handoffgit (main)Agent handoff client

    Configuration

    Environment Variables

    graphql
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
    # Deployment target
    ENVIRONMENT="qa|staging|prod"
    
    # Langfuse β€” LLM Observability
    LANGFUSE_PUBLIC_KEY="pk-lf-..."
    LANGFUSE_SECRET_KEY="sk-lf-..."
    LANGFUSE_BASE_URL="https://langfuse.hyly.us"
    LANGFUSE_DEBUG="false"
    
    # GraphQL API Keys (per environment)
    graphql_api_key="..."          # QA
    graphql_api_key_stg="..."      # Staging
    graphql_api_key_prod="..."     # Prod
    
    # GraphQL Endpoint URLs
    GRAPHQL_QA_URL="https://qa.hyly.us/graphql"
    GRAPHQL_STG_URL="https://my.hyly.us/graphql"
    GRAPHQL_PROD_URL="https://my.hy.ly/graphql"
    
    # GraphQL Authorization Headers
    GRAPHQL_KEY_QA="userid___1709542253522009420"
    GRAPHQL_KEY_STAGING="userid___1777464981952577365"
    GRAPHQL_KEY_PROD="myhyly-hyblast-sync"
    
    # Tracing
    DISABLE_TRACING="false"

    Key Constants

    ConstantValueDescription
    CACHE_TIMEOUT7200Session cache TTL in seconds (2 hours)
    cache_retrieve_threshold0.98Cache similarity threshold
    Max history (cache)8Max messages kept per session
    Max history (engine call)4Messages forwarded to Hayley Engine
    Contact extraction triggerscustomer_info,Β contact,Β complaint_filing,Β agent_hand_off,Β emergency_maintenanceSub-intents that trigger NER extraction

    Running Locally

    graphql
    1 2 3
    pip install -r requirements.txt
    export ENVIRONMENT=qa
    uvicorn app:app --reload --host 0.0.0.0 --port 6000

    Docker

    graphql
    1 2
    docker build -t hayley-chat-adapter .
    docker run -p 6000:6000 --env-file .env hayley-chat-adapter

    Changelog

    CommitDescription
    540102dMerge PR #159 from munishgandhi/DEV
    04ed59cMerge PR #158 β€” observability v3
    a32ec34File set for chat adapter
    c2ec4f8Observability clean of traces
    2d8fd23Add logger for create message API latency
    On this page
    Hayley SMS AdapterOverviewArchitectureHigh-Level FlowTech StackDirectory StructureRequest Processing FlowAPI ContractGET /heartbeatPOST /chat_adapterEnvironment URLsDependenciesInternal MicroservicesExternal Property Management APIsPython PackagesConfigurationEnvironment VariablesKey ConstantsRunning LocallyDockerChangelog
    Copy Page