LiteBot

Bot configuration reference

This chapter lists every key a bot accepts, with its type, default, allowed values and what LiteBot does with it. Use it when you write a bot JSON file or a POST /api/bots body, or when a bot is skipped at load. How bots are loaded and edited is explained in Bots.

How to read this reference

The authority is the Joi schema botConfigSchema in src/core/bot-manager.js. Every bot, from a file, from Mongo or from the API, passes through it.

  • A key that is not listed here is rejected, and the bot is skipped or the API call fails with 400 ("<key>" is not allowed).
  • "Default" is the value Joi fills in when you leave the key out. "none" means the key stays absent.
  • "Runtime effect" says what reads the key. Some keys are stored and returned by the API but change nothing at runtime; the tables say so.
  • A nested object with a default of {} gets its inner defaults only when you include the object. Left out, it stays {}.

Identity and tenancy

Key Type Default Meaning
id string, required none Unique bot id. Used in chat requests (botId), file names (<id>.json, <id>.txt) and every analytics record. Cannot be changed by PUT
name string, required none Display name. Also used in the generic handoff message and the flow-bot prompt
description string none Shown in lists. Flow bots put it in each step prompt (You are <name>. <description>.)
tenantId string matching ^[a-z0-9][a-z0-9-]{1,39}$ default Owning tenant. Scopes dashboard access, tool resolution and tenant LLM keys. On the API a tenant user's bots are always in their own tenant
isActive boolean true false hides the bot from lists, and chat to it fails with Bot is not active. Mongo bots with false are not loaded at all

Model and provider

Key Type Default Meaning
provider string groq LLM provider name: groq, openrouter, openai, gemini, gemini-vertex, sarvam, ollama. The schema accepts any string; an unconfigured name fails at chat time. See LLM providers
model string none Model id for that provider. Unset uses the provider's default model
temperature number, 0–2 0.7 Sampling temperature sent to the provider
maxTokens number, 1–8000 1000 Output token limit for each model call

Set provider explicitly. The groq default fails on a server without a Groq key.

Prompt and variables

Key Type Default Meaning
systemPrompt string, required none The system prompt. For a file bot it may be omitted from the JSON when config/prompts/<id>.txt exists; the loader fills it in before validation
variables object of string, number or boolean values {} Values for {{name}} placeholders. Replaced at file load and at voice session start, not for Mongo or API bots in text chat. See Variables
injectContext boolean true Adds the session context (keys not starting with _) as a Current session context: system message on each text turn. Voice sessions add caller context to the prompt when this is true
language string en Stored and listed only. Not sent to the model; put language rules in the prompt
responseFormat object { "type": "text" } Stored only. No runtime effect
responseFormat.type text, json, markdown text Stored only
responseFormat.schema object none Stored only

Tools

Key Type Default Meaning
tools array of strings [] Tool names. In text chat an empty list offers every tool visible to the tenant; in voice it offers none. Unknown names are dropped. See Tools and Tools

Routing and handoff

These keys drive the keyword intent router and in-session bot switching described in Routing and bot switching.

Key Type Default Meaning
intentThreshold number, 0–1 0.3 Minimum score for this bot to be picked for a new session sent without botId. 0 is treated as 0.3
switchingThreshold number, 0–1 0.4 Minimum score another bot needs to take a session away from this bot. 0 is treated as 0.4. Set 1 to make switching away rare
handoffMessages object, bot id → string {} Message added when this bot hands a session to the named bot. Without an entry a generic message names the target's department or name

Metadata

metadata is a free-form object (default {}): any keys are accepted. These are read by code:

Key Type Default Meaning
metadata.keywords array of strings none Intent-router keywords. Phrase match adds 0.8, each word match 0.3. A bot without keywords or patterns is never routed or switched to
metadata.patterns array of regex strings none Case-insensitive patterns; each match adds 0.7
metadata.priority number none Adds priority / 10 to the bot's score when it has at least one match
metadata.department string none Shown in analytics and intent results; used in the generic handoff message
metadata.isVisualBuilder boolean none With a non-empty _visualFlow, makes this a flow bot (Visual flows)
metadata.flowVersion string none Written by the visual editor; informational

Escalation

escalationRules (default {}) decides when a reply carries shouldEscalate: true. LiteBot only sets the flag; see Escalation rules.

Key Type Default Meaning
escalationRules.keywords array of strings [] Escalate when the user message contains one (case-insensitive)
escalationRules.maxAttempts number, ≥ 1 3 when escalationRules is present Escalate when the session holds maxAttempts × 2 stored messages. Absent when escalationRules is left out
escalationRules.sentimentThreshold number, -1 to 1 none Accepted, not used

A tool result with escalated: true also sets the flag, whatever the rules say. Flow bots never set it.

Session-end hooks

onSessionEnd (default []) lists tools run once when the session ends, without a model call. Details and template values are in Session-end hooks.

Key Type Default Meaning
onSessionEnd[].tool string, required none Tool name
onSessionEnd[].params object {} Tool parameters. Strings may use {{sessionId}}, {{botId}}, {{userId}}, {{reason}}, {{messageCount}}, {{transcript}} and {{context.<key>}}
onSessionEnd[].reasons array of remote_hangup, transfer, llm_hangup, idle_timeout, api none Run only for these end reasons. Absent or empty runs for every reason

Voice

voice is optional. Without it, or with voice.enabled not true, a /voice session for the bot fails with VOICE_NOT_ENABLED. When you include voice, the defaults below are filled in. These keys apply only to Gemini Live sessions on /voice (Voice).

Key Type Default Meaning
voice.enabled boolean false Allows /voice sessions for this bot
voice.model string GEMINI_LIVE_MODEL at start-up, else gemini-3.1-flash-live-preview Gemini Live model. A models/ prefix is added if missing
voice.voiceName string Aoede Gemini prebuilt voice
voice.languageCode string en-US Speech language sent to Gemini
voice.responseModality AUDIO, TEXT AUDIO Reply type when the client does not send mode
voice.speechConfig.speakingRate number, 0.25–4.0 1.0 Accepted but not sent to Gemini Live: no effect
voice.speechConfig.pitch number, -20–20 0.0 Accepted but not sent to Gemini Live: no effect
voice.interruption.enabled boolean true false stops the caller from cutting the bot off (NO_INTERRUPTION)
voice.turnCoverage TURN_INCLUDES_ONLY_ACTIVITY, TURN_INCLUDES_ALL_INPUT none What audio counts as the user turn. Unset uses VOICE_TURN_COVERAGE, then Gemini's default (only activity)
voice.inputMimeType string matching audio/pcm;rate=<n> none Input audio format. Unset uses VOICE_INPUT_MIME_TYPE, then audio/pcm;rate=16000

voice.vad

Voice activity detection. Each field falls back to its environment variable, then to Gemini's own default.

Key Type Default Meaning
voice.vad.silenceDurationMs integer, 100–5000 VOICE_VAD_SILENCE_MS Silence that ends the caller's turn
voice.vad.prefixPaddingMs integer, 0–5000 VOICE_VAD_PREFIX_PADDING_MS Audio kept before detected speech
voice.vad.startOfSpeechSensitivity START_SENSITIVITY_LOW, START_SENSITIVITY_HIGH, START_SENSITIVITY_UNSPECIFIED VOICE_VAD_START_SENSITIVITY How easily speech start is detected
voice.vad.endOfSpeechSensitivity END_SENSITIVITY_LOW, END_SENSITIVITY_HIGH, END_SENSITIVITY_UNSPECIFIED VOICE_VAD_END_SENSITIVITY How easily speech end is detected
voice.vad.disabled boolean VOICE_VAD_DISABLED true turns off automatic detection; the other VAD fields are then not sent and the client marks turns

Visual flow

Key Type Default Meaning
_visualFlow object none Flow graph saved by the visual editor
_visualFlow.nodes array of objects, required none Nodes. Contents are not checked by the schema
_visualFlow.edges array of objects, required none Edges. Contents are not checked by the schema
_visualFlow.metadata object none Editor timestamps and version

A bot runs as a flow bot only when _visualFlow.nodes is non-empty and metadata.isVisualBuilder is true. Node types and runtime behaviour are in Visual flows.

Keys the loader reads but the schema rejects

Key Read by What happens
promptFile File loader (would load config/prompts/<file>) The bot is skipped with "promptFile" is not allowed. Use config/prompts/<id>.txt instead
voice.thinkingBudget Voice handler The bot is skipped with "voice.thinkingBudget" is not allowed. Set VOICE_THINKING_BUDGET instead; the default is 0 (thinking off)

Complete annotated example

{
  "id": "clinic-reception",
  "name": "Clinic Reception",
  "description": "Front desk for Example Clinic",
  "tenantId": "default",
  "isActive": true,
  "provider": "gemini-vertex",
  "model": "gemini-2.5-flash",
  "temperature": 0.3,
  "maxTokens": 600,
  "systemPrompt": "You are the receptionist for {{clinicName}}. Reply in at most three sentences. For bookings, collect name and preferred day, then call bookAppointment.",
  "variables": { "clinicName": "Example Clinic" },
  "injectContext": true,
  "language": "en",
  "tools": ["getSessionContext", "bookAppointment", "hangupCall"],
  "escalationRules": { "keywords": ["speak to a human", "complaint"], "maxAttempts": 100 },
  "intentThreshold": 0.3,
  "switchingThreshold": 1,
  "handoffMessages": {},
  "metadata": { "department": "reception", "keywords": ["appointment", "clinic hours"] },
  "onSessionEnd": [
    {
      "tool": "sendCallSummary",
      "params": { "session": "{{sessionId}}", "caller": "{{context.caller_id}}", "transcript": "{{transcript}}" },
      "reasons": ["remote_hangup", "llm_hangup", "idle_timeout"]
    }
  ],
  "voice": {
    "enabled": true,
    "voiceName": "Aoede",
    "languageCode": "en-IN",
    "interruption": { "enabled": true },
    "vad": { "silenceDurationMs": 700 },
    "inputMimeType": "audio/pcm;rate=16000"
  }
}

Notes on the example:

  1. provider and model are set explicitly instead of relying on the groq default.
  2. {{clinicName}} is replaced when the file loads. If you create this bot through the API instead, write the name into the prompt, because text chat does not replace variables for API bots.
  3. tools is listed explicitly. An empty list would offer every tool on the server in text chat.
  4. maxAttempts: 100 keeps shouldEscalate for keywords and tools only.
  5. switchingThreshold: 1 keeps callers on this bot. metadata.keywords still lets an unpinned new session be routed here.
  6. onSessionEnd sends a summary when the call ends for any reason except a transfer or an API end. The tool name is an example; use one from your registry.
  7. voice leaves model out, so it uses GEMINI_LIVE_MODEL, and leaves out thinkingBudget, which the schema rejects.

Where to go next