Skip to main content

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 (not implemented)

None of these routes exist. They are the designed write paths for sensitive variables and signed context tokens, kept here for the planned verified-variables work (see docs/agentic-development/CHORES.md C-210). Today variables arrive only as variables on POST /bots/:id/chat and the conversation-create routes; contextToken is accepted by the conversation-create schemas but has no effect.

Models and Files

Knowledge Base Readiness Gate

All paths that make an agent publicly or organizationally “live” verify KB readiness before proceeding:
  • POST /bots with isDraft: false
  • PUT /bots/:id when setting isDraft: false
  • POST /bots/:id/publish
  • POST /bots/:id/approve
  • POST /bots/:botId/distribution/publish
The 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 in services/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 the request body and agent defaults. (contextToken is accepted by the schema but has no effect; context tokens are not implemented — C-210.)
3

Resolve Welcome Config

Welcome is read from bots.widget_config.welcome, not via prompt-resolution. Despite the field’s name it is channel-wide: every channel’s conversation start reads it. 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

Use request.user.organizationId / request.user.id from JWT middleware. NEVER read raw headers.
Every chat MUST call record_external_cost_event() with provider, operation, cost, orgId, userId. Generated-mode welcome messages also bill.
On bot update, knowledgeBaseIds array replaces all links in kb_agent_links. If frontend sends [], all links are deleted. Every id is validated first (utils/kb-link-validation.ts): it must exist, be in the agent’s organization, and — when its link changes — be editable by the caller, as the knowledge service’s POST /knowledge/kb-access decides. A failure is 400 invalid_knowledge_base_ids and writes nothing; a check that cannot complete is a 503. At most 100 ids per request.
Every call goes through utils/knowledge-client.ts (knowledgeFetch with a KnowledgeCaller, or knowledgeInternalFetch for /internal/*). It sends the caller’s x-org-role and signs any bearer it mints. CI’s check-knowledge-client.js fails on a KNOWLEDGE_SERVICE_URL/_HOST/_PORT reference, a hard-coded :4005, or a raw fetch/axios call to a /knowledge/ URL anywhere else.
checkResourceAccess() before all bot operations.
KB retrieval failures do not block chat — response continues without context.
NEVER read bots.system_prompt directly in new code. Always go through prompt-resolution.service.ts.
NEVER return conversation_variables.sensitive_variables in any API response.
Check bot.streaming_enabled AND request.stream === true before streaming any response.