Skip to main content

Communication: hbf-bot

Inbound webhooks, outbound service calls, and message-bus usage. Full platform topology: docs/architecture/deployment.md

Inbound Webhooks

All routes are registered by app/system/HBFEndpointSystem.ts and handled by BaseChannel.process(). No inbound auth guards on these routes -- each upstream platform validates its own payload.

MethodRouteChannel classNotes
GET/POST/api/fb-eventsFacebookChannelGET = hub verification; POST = events
GET/POST/api/instagram-eventsInstagramChannelGET = hub verification; POST = events
POST/api/whatsapp-eventsWhatsAppChannelValidation token check in channel
POST/api/viber-events/ViberChannelRaw body preserved for HMAC; trailing slash required
GET/POST/api/slack-eventsSlackChannelGET = challenge; POST = events
POST/api/msteams-eventsMicrosoftChannelTeams
POST/api/webchat-eventsMicrosoftChannelWeb Chat (OBF)
POST/api/livechat-events/LiveChatGatewayChannelLCG agent messages
POST/api/unity-eventsUnityChannelUnity game channel
POST/api/eventsApiChannelGeneric REST channel
POST/api/monitoring-eventsMonitoringChannelUptimeRobot health probes
POST/api/post-eventsPostChannelPOST channel
POST/api/zendesk-eventsZendeskChannelZendesk

Management (shared-secret protected, see docs/auth.md):

MethodRouteHandler
POST/api/tenantsTenantsController -- reload/force-reload a tenant
DELETE/api/tenants/cacheTenantsController -- evict one tenant or flush all
GET/api/statusStatusController -- loaded tenant count + list
GET/Homepage -- status page (CORS-restricted by homePageAllowedOrigin)

Outbound Calls

hbf-core (via @helvia/hbf-core-api)

Client: HBFCoreApi (instantiated in multiple places with HBFCoreAuth DI token: CORE_BASEURL / CORE_TOKEN).

OperationClientCalled from
Fetch BotDeployment (full graph)BotDeploymentClientHBFCoreBotDeploymentStorage
Fetch tenant timestamp for cache validationBotDeploymentClient.getTenantTimestampByHandleHBFCoreBotDeploymentStorage
Find fallback deployment via MessagingAppMessagingAppsClient.findByAppIdHBFCoreBotDeploymentStorage
Get/create/update Subscriber blackboardSubscribersClientCoreSubscribersStorage
Create/update ChatSession, batch messages, variablesChatSessionsClientChatSessionsRepository
Update message tagsAnalyticsClient.updateMessageTagsChatSessionsRepository
NLU process (HBF_CORE pipeline mode)NlpPipelinesClient.processExternalNLU
Group CRUDGroupsClientHBFCoreGroupRepository
HandoverHandoverClientHandoverRepository

hbf-nlp

Direct HTTP via HttpRequest.post (no retry wrapper at the client level).

EndpointPurposeCalled from
POST /tenants/{tenantId}/processNLU intent detectionExternalNLU
POST /v2/generationLLM generation (LLMNode)GenerationRequestHandler
POST /llm-requestLLM request (built-in function path)buildInFunctions

Auth: Bearer CORE_TOKEN on all NLP calls.

hbf-lcg (via LiveChatGatewayClient)

File: app/clients/livechat/LiveChatGatewayClient.ts DI token: LiveChatGatewayAuth (LCG_BASEURL / LCG_TOKEN or falls back to CORE_TOKEN).

All calls are plain HttpRequest with no built-in retry. Errors are logged and re-thrown.

EndpointPurpose
POST /requestsCreate a new live chat request
POST /requests/{id}/closeClose a live chat request
GET /requests/{id}/availabilityCheck agent availability
GET /requests/{id}/stateGet subscriber state
GET /requests/{id}/metricsGet queue metrics
POST /messagesSend message to live chat

helvia-rag-pipelines (via RagPipelinesClient)

File: app/clients/rag/RagPipelinesClient.ts Static class, no DI. URL and per-pipeline bearer token come from the conversation node action params at runtime.

EndpointPurpose
POST /pipelines/{pipelineId}:searchSemantic search in a RAG pipeline

On failure: logs error, returns undefined (silent). See docs/resilience.md.

hbf-event-publisher (via EventPublisherClient)

File: app/util/EventPublisherClient.ts DI token: EventPublisherOptions (env: EVENT_PUBLISHER_BASEURL). Auth: passthrough CORE_TOKEN as Bearer.

EndpointTrigger typeWhen
POST /connectors/flows:triggerautomated-answer-triggeredAfter automated answer with an activity set
POST /connectors/flows:triggerlivechat-request-missedLCG missed request
POST /connectors/flows:triggerlivechat-conversation-finishedLCG conversation closed
POST /connectors/flows:triggersurvey-completedSurvey finished
POST /connectors/flows:triggerchat-session-completedChat session closed

If baseUrl is empty, all publisher calls are silently skipped.

Kafka (KafkaEventPublisher)

File: app/kafka/KafkaEventPublisher.ts DI token: KafkaConfig.

Publishes InteractionMetadata events (LLM, HTTP, SEMANTIC_SEARCH, VARIABLE, TAG actions) per inbound message.

Config keyEnv varDefault
kafka.enabledKAFKA_ENABLEDfalse
kafka.brokersKAFKA_BROKERS(none)
kafka.topicKAFKA_TOPIChbf.interaction.metadata
kafka.clientIdKAFKA_CLIENT_IDhbf-bot
kafka.sslKAFKA_SSLfalse
kafka.sasl.mechanismKAFKA_SASL_MECHANISM(none)

Producer is idempotent. Connection is lazy (established on first publish attempt). Kafka errors do not bubble; they are logged and the publish is skipped.

Kafka message format:

key:     sessionId
value: JSON(MetadataEvent)
headers: tenantId, organizationId, eventType

AWS S3 (AwsS3FileUploader)

File: app/util/AwsS3FileUploader.ts DI token: AWSS3FileUploadOptions.

Used for file upload actions in conversation flows (e.g., user-submitted images). SDK: @aws-sdk/client-s3 + @aws-sdk/lib-storage.

Config keyEnv var
aws.s3.region(static config)
aws.s3.bucketName(static config)
aws.s3.bucketDomain(static config)
aws.accessKeyID(static config)
aws.secretAccessKey(static config)

Redis

Client: ioredis (BotDeploymentCache, app/system/storage/BotDeploymentCache.ts). DI token: RedisConfigurations.

Env varDefaultDescription
REDIS_HOST127.0.0.1Redis hostname
REDIS_PORT6379Redis port
REDIS_PASSWORD(empty)Redis password
REDIS_TLSfalseTLS flag
REDIS_TENANT_TTL604800 (7 days)TTL for cached BotDeployment keys

Key Patterns

PatternTypeWritten byRead byTTL
<deployment-handle>String (JSON)BotDeploymentCache.replaceCachedBotDeploymentCache.getCachedREDIS_TENANT_TTL

BotDeploymentCache stores a serialised { data: BotDeployment, timestamp: Date } envelope. Cache validity is checked by comparing the stored timestamp against the tenant's updatedAt timestamp fetched live from hbf-core.

Subscriber blackboard state is stored in hbf-core (not Redis directly). Redis is used only for the BotDeployment config cache. There is no pub/sub usage.

Dependency Diagram