Overview
Port: 4002 The Bot Service handles agent CRUD operations, AI chat via OpenRouter/LangChain, RAG context retrieval from linked knowledge bases, prompt configuration, conversation management, and credit billing.Endpoints
Agent CRUD
Chat
Prompt Configuration
Variables and Context Tokens
Models and Files
Knowledge Base Readiness Gate
All paths that make an agent publicly or organizationally “live” verify KB readiness before proceeding:POST /botswithisDraft: falsePUT /bots/:idwhen settingisDraft: falsePOST /bots/:id/publishPOST /bots/:id/approvePOST /bots/:botId/distribution/publish
GET /bots/:id/indexing-status endpoint proxies GET /knowledge/agents/:id/indexing-status and returns:
If the knowledge service is unreachable, the check is fail-closed and publishing is blocked.
Chat Flow Pipeline
The core chat endpoint (POST /bots/:id/chat) follows this pipeline:
Provider Error Handling
Provider-level failures are mapped to user-friendly messages before reaching the UI. The mapping is centralized inservices/bot/src/utils/error-utils.ts via mapProviderError().
The raw provider error message — including any API key URLs — is sanitized by
sanitizeProviderMessage() before logging. Streaming chat emits error events as data: { "type": "error", "message": "...", "code": "..." }. Non-streaming chat returns { "error": "...", "code": "..." } when a provider-level failure occurs. Public widget chat and chat-core headless consumers receive the same codes.
Welcome Message Flow
When a conversation is created (POST /bots/:id/conversations):
1
Create Conversation
Create conversation record in database.
2
Resolve Variables
Merge variables from context_token, request body, and agent defaults.
3
Resolve Welcome Config
Welcome is read from
bots.widget_config.welcome (web-widget-scoped), not via prompt-resolution. If absent or disabled, the conversation returns with no welcome message.4
Render and Generate
- If no config or
enabled=false: return conversation with no welcome message. - If
mode='fixed': render content with variables, return directly. - If
mode='generated': render prompt template, call LLM, optionally stream response.
5
Save and Return
Save welcome message as first assistant message. Return
{ conversationId, welcomeMessage }.Fixed mode has no cost. Generated mode calls
record_external_cost_event() with operation welcome_message_generation.Prompt Resolution Flow
All prompts resolve via the same three-tier chain:RAG Quality Controls
Core Services
Database Tables
External Integrations
Critical Patterns
Authentication
Authentication
Use
request.user.organizationId / request.user.id from JWT middleware. NEVER read raw headers.Billing
Billing
Every chat MUST call
record_external_cost_event() with provider, operation, cost, orgId, userId. Generated-mode welcome messages also bill.KB Linking
KB Linking
On bot update,
knowledgeBaseIds array replaces all links in kb_agent_links. If frontend sends [], all links are deleted.RBAC
RBAC
checkResourceAccess() before all bot operations.Graceful Degradation
Graceful Degradation
KB retrieval failures do not block chat — response continues without context.
Prompt Resolution
Prompt Resolution
NEVER read
bots.system_prompt directly in new code. Always go through prompt-resolution.service.ts.Sensitive Variables
Sensitive Variables
NEVER return
conversation_variables.sensitive_variables in any API response.Streaming
Streaming
Check
bot.streaming_enabled AND request.stream === true before streaming any response.
