Skip to main content

RFC Summary: Consistent Deal & Ticket Creation Experience — Phase 1: Bot & AI Creation Parity

Full RFC: see docs/rfcs/consistent-deal-ticket-creation/bot-ai-creation-parity.md Status: IDEA (draft) | Type: backend / enhancement Author: Alma Syafira (PM) · rfc-starter (agent draft) | Target: 2026-Q3 PRD: Phase 1: Bot & AI Creation Parity Related repos: chatbot (producer BE) · hub-core / hub-chat (Omnichannel) · crm-fe-v3 (CRM FE)


Problem

Deals and tickets created by Chatbot or Agentic AI don't behave like manually-created ones: the Omnichannel infobar keeps showing the "Create Deal" CTA even after a record exists, the CRM record has no conversation contact or origin context, and there's no timeline entry showing how the deal originated. Agents lose trust in automation and waste time manually hunting for records they can't see.


What's Being Built

  • CRM backend (qontak.com) persists a creator_flag ("bot"/"agentic_ai") on deals and tickets so the Creator field can read "Bot"/"AI".
  • CRM emits create + update + delete events to Omnichannel for bot/AI records that carry a chat-room id, so the infobar shows a live deal/ticket preview that stays fresh.
  • CRM auto-associates the conversation contact at creation time (reusing existing logic).
  • CRM auto-creates a chat-history timeline note (lightweight preview + room deeplink) on the deal/ticket detail.
  • Chatbot BE (chatbot) — the upstream producer — extends the create body it already sends to /api/v3.1/deals|tickets with room_id, contact, and creator_flag.
  • Omnichannel (hub-core/hub-chat) renders the preview + new-tab navigation; crm-fe-v3 renders the timeline entry + creator label (UI embed pre-baked to crm-fe-v3).

Component Architecture

flowchart TB
subgraph clients[Actors]
AGENT[Sales/CS Agent browser]
end
subgraph bot[chatbot — Chatbot BE]
BFLOW[Flow / node executor<br/>mekari_qontak_crm/execute.rb]
BHTTP[CrmHttpClient<br/>company-token auth + 401 refresh]
end
AI[Agentic AI / Airene<br/>producer — repo TBD]
LB[(ALB / nginx ingress)]
subgraph crm[qontak.com — CRM BE - MAIN]
WEB[Rails web pods]
SK[Sidekiq workers]
REDIS[(Redis)]
DBP[(Postgres primary)]
DBR[(Postgres replica)]
end
subgraph hub[hub-core — Omnichannel BE]
HWEB[Rails web pods]
HDB[(Postgres: qontak_crm_objects / room_tickets)]
ES[(Elasticsearch)]
end
subgraph fe[Frontends]
HUBFE[hub-chat]
CRMFE[crm-fe-v3]
end
BFLOW --> BHTTP -->|POST /api/v3.1/deals,/tickets| LB
AI -.->|POST create| LB
LB --> WEB
WEB --> DBP
WEB --> SK
SK -->|webhook + chat history| HWEB
HWEB --> HDB
HWEB --> ES
AGENT --> HUBFE -->|read preview| HWEB
AGENT --> CRMFE -->|read timeline/creator| WEB
WEB -->|reads| DBR

Repo Map (files touched)

flowchart LR
subgraph CB[BE: chatbot READ-ONLY]
CEX[execute.rb<br/>add room_id/contact/creator_flag]
CHC[crm_http_client.rb<br/>company-token]
end
subgraph CRM[BE: qontak.com MAIN]
DS[crm/deals/create_service.rb<br/>modified]
TC[ticket/create.rb<br/>modified]
PB[webhook entities<br/>modified]
NW[timeline-note worker<br/>new]
MIG[migrate creator_flag<br/>new]
end
subgraph HUB[BE: hub-core READ-ONLY]
DR[deal_receiver.rb<br/>add update]
TR[ticket_receiver.rb<br/>add create/update]
end
subgraph FE[FE READ-ONLY]
HD[hub-chat preview]
CT[crm-fe-v3 timeline]
end
CEX --> CHC
CHC -.POST /api/v3.1/deals.-> DS
DS --> MIG
DS --> NW
DS --> PB
PB -.webhook.-> DR
PB -.webhook.-> TR
DR --> HD
NW --> CT

Infobar Preview State Machine

stateDiagram-v2
[*] --> CTA: no record
CTA --> Preview: create event received
Preview --> Preview: update event (latest fields) / newer record (latest-wins)
Preview --> CTA: delete event
Preview --> Error: hub cannot reach CRM (CDTC-S01 ERR-2)
Error --> Preview: retry/reload

Sequence Diagrams

Happy path — bot/AI creates deal → preview + timeline

sequenceDiagram
participant BOT as chatbot BE (execute.rb)
participant LB
participant WEB as CRM web
participant DBP as PG primary
participant SK as Sidekiq
participant HUB as hub-core
BOT->>BOT: build body (room_id, contact, creator_flag)
BOT->>LB: POST /api/v3.1/deals (company token)
LB->>WEB: route
WEB->>DBP: INSERT deal (room_id, creator_flag) + contact assoc
WEB-->>BOT: 201 Created
WEB->>SK: enqueue SendWebhookWorker + TimelineNoteWorker
SK->>HUB: POST qontak.crm.deal.create
HUB->>HUB: upsert QontakCrmObject (latest-wins)
SK->>HUB: GET chat history (room_id)
SK->>DBP: INSERT Crm::Note (preview + deeplink)

Failure path — chatbot CRM create token expired (producer side)

sequenceDiagram
participant BOT as chatbot CrmHttpClient
participant WEB as CRM web
BOT->>WEB: POST /api/v3.1/deals (Bearer access_token)
WEB-->>BOT: 401 Unauthorized
Note over BOT: request_with_auth retries once
BOT->>WEB: POST /api/v3.1/teams/company_token (sso_id + X-Crm-Api-Key)
WEB-->>BOT: new token
BOT->>WEB: POST /api/v3.1/deals (new token)
Note over BOT: on refresh fail → no deal created; Rollbar

Key Technical Decisions

#DecisionChosenRationale
1CRM UI embedcrm-fe-v3pre-baked by author; timeline component already exists there
2CRM→Omnichannel transportReuse existing webhook pipelinecreate/delete already work end-to-end; "new API" = additive event actions
3Preview freshnessEmit update events tooPRD AC-4 requires latest Name/Stage/Status (conditional on OQ-1)
4Bot/AI actor storageNew nullable creator_flag columncreator_id is a User FK; data_source already means transport
5Timeline entryLightweight Crm::Note + deeplink, asyncreuse existing note types; no new schema; PRD rejected full transcript
6Multiple records per roomLatest-wins by CRM created_atdeterministic vs non-deterministic receipt time
7Chatbot producerExtend existing CRM node executor bodyexecutor + company-token auth + retry already exist; add 3 fields

APIs at a Glance

MethodEndpointStatusOwner
POST/api/v3.1/deals (add room_id/contact/creator_flag)extend bodyChatbot Squad (chatbot)
POST/api/v3.1/tickets (add room_id/creator_flag)extend bodyChatbot Squad (chatbot)
POSTqontak.crm.deal.create webhookexists (reused)CRM (qontak.com)
POSTqontak.crm.deal.update webhookneeds receiver branchCRM emit / hub-core receive
POSTticket create / update webhookneeds-buildingCRM + hub-core
GET/api/open/v1/messages/rooms/:id (chat history)exists (reused)hub-core

Open Blockers

#BlockerOwnerBlocks
OQ-1How hub-chat sources deal Name/Stage/Pipeline (live fetch vs stored)Omnichannel Engupdate-sync design
OQ-2No sender/receiver path for bot/AI ticket create+update todayCRM + Omnichannel Engticket preview
OQ-4Exact hub-chat room deeplink URL pattern (none found in repo)Omnichannel Engtimeline → room nav
OQ-10Contact contract mismatch: chatbot sends crm_lead_ids, PRD/CRM uses contact_idChatbot + CRM Engcontact auto-association
InfoSec approver + feature flag name + discussion link requiredCRM Eng / PM§7 sign-off

Rollout

StageAudienceGo/No-go evidence
Internal AlphaQontak internal accounts (Chatbot + AI + CRM + Omni)all deps integrated; bidirectional nav works; timeline log for ≥95% creates
Closed Beta5–10 CSM-nominated customerspreview success ≥95%; no critical defects; no room-load latency regression
GAAll Chatbot/Agentic AI plan accountsbeta gates sustained ≥2 weeks; PMM approval

Stop conditions: deal_preview_displayed drops to 0 while creates >0 for 15 min; timeline_log_creation_failed > 5%/1h; P95 room load > baseline + 200ms.

Rollback: toggle the per-account feature flag OFF → bot/AI events stop emitting; creator_flag column is inert when unread (no down-migration needed); confirm preview rate + P95 latency recover; revert PR only if necessary.


Generated from RFC: Consistent Deal & Ticket Creation Experience — Phase 1: Bot & AI Creation Parity · 2026-06-30