This README is the canonical reference for installing, configuring, operating, and troubleshooting Chatbot.
Our kind sponsors of this project:
| Sponsor | Level | Weblink | Logo |
|---|---|---|---|
| Surety | Silver Plus | suretyhome.com | ![]() |
- The original Discourse AI Chatbot!
- Can provide customer-support answers grounded in your community content; see Building a technical support chatbot.
- Converse with the bot in Topics, Personal Messages, Chat channels, and Chat threads, one-to-one or with others!
- Customise the character of your bot to suit your forum!
- want it to sound like William Shakespeare, or Winston Churchill? can do!
- Configurable tools let the bot:
- Search your forum for answers so the bot can be an expert on the subject of your community.
- not just be aware of the information on the current Topic or Channel.
- Search Wikipedia
- Search current news*
- Search Google*
- Return current End Of Day market data for stocks.*
- Evaluate mathematical expressions with Dentaku, including common aliases for PI and E.
- Collect outstanding editable User Fields in private conversations.
- Escalate a private Chat conversation to configured staff groups.
- Search your forum for answers so the bot can be an expert on the subject of your community.
- Vision support - select the
visiontool for the relevant trust levels to let the bot answer questions about uploaded images. - Image generation and editing support - select the paint tools and choose a supported image model.
- OpenAI PDF input support can be enabled with
chatbot_support_pdf. - Uses the tool-calling capabilities of OpenAI, Anthropic, Google Gemini, and xAI models through their OpenAI-compatible APIs.
- Includes a special quota system to manage access to the bot: more trusted and/or paying members can have greater access to the bot!
- Supports OpenAI, Anthropic, Google Gemini, and xAI, plus Azure and OpenAI-compatible proxy connections.
*Sign-up for external, unaffiliated API services is required. Links are provided in the settings.
The bot has one implementation with a separate built-in tool allowlist for each trust level. Leave an allowlist empty to expose no built-in tools, or select tools to give that trust level access to local search and other capabilities. Tools that require credentials or supporting configuration are only exposed when those requirements are also met. Extension tools supplied by other plugins are independent of these allowlists.
This bot can be used in public spaces on your forum. Local forum search is controlled separately for each bot trust level through the tool settings.
When local forum search is enabled, the bot is governed by chatbot_embeddings_strategy (default benchmark_user) and is privy to all content the benchmark user can see. Thus, if interacted with in a public-facing Topic, the bot could leak information if you gate sensitive content at that level.
For local forum search, make sure you have a benchmark user at the configured trust level with no additional group membership beyond the automated groups. Bear in mind that the bot can share anything that user can access.
Alternatively:
- Set
chatbot_embeddings_strategytocategoriesand populatechatbot_embeddings_categorieswith only the Categories the bot may search. Including private Categories means their matching content could be returned to less-privileged users elsewhere. - Remove
local_forum_searchfrom any trust-level tool allowlist that should not search embedded content. - Use moderation and carefully scoped groups as additional safeguards.
This is a deliberate compromise: semantic search is optimised for speed and does not perform a fresh per-request visibility check for the person asking the bot. Private Messages are never embedded. Contact me if you need a more restrictive permission model and would like to sponsor that work.
- LLM API responses can be slower for higher-capability and reasoning models. Choose the model for each trust level based on the quality, latency, and cost your community needs.
- Chatbot natively supports OpenAI, Anthropic, Google Gemini, and xAI through their OpenAI-compatible endpoints, including custom model names and URLs for each trust level. Proxy servers can provide access to other compatible services without changing Chatbot code.
- Other plugins can extend the toolset without maintaining a fork of Chatbot.
For a new installation, configure model providers, access and quotas, and trust-level tools first. Stored forum embeddings are optional and are needed for local forum search. Blocked-question matching can use System One forum-scope judgments or example-based embeddings without requiring the stored forum index.
Install the plugin using the standard self-hosted plugin procedure.
Local forum search requires PostgreSQL's pgvector extension, version 0.5.1 or newer. Most supported Discourse installations already provide it. If a rebuild fails with PG::UndefinedObject: ERROR: access method "hnsw" does not exist, enter the running container and update the extension:
./launcher enter app
su postgres -c 'psql discourse'
\dx
ALTER EXTENSION vector UPDATE;
\dx
\q
exit
Then leave the container and rebuild the app.
If you wish Chatbot to know about the content on your site, turn this setting ON:
chatbot_embeddings_enabled
This is only necessary when at least one trust level has the local_forum_search tool and the bot should know about content beyond the current Topic.
Initially, Chatbot creates embeddings for all in-scope Posts and Topic titles so the bot can find forum information. This happens in the background after the setting is enabled.
This seeding job can take a period of days for very big sites.
This is determined by several settings:
chatbot_embeddings_strategy, which can be eitherbenchmark_userorcategories;chatbot_embeddings_benchmark_user_trust_level, which sets the relevant trust level forbenchmark_user;chatbot_embeddings_categories, which identifies the Categories included by thecategoriesstrategy.
When these settings change, background jobs gradually bring the stored embeddings into the new scope.
Enter the container:
./launcher enter app
and run the following rake command to fill missing embeddings:
rake chatbot:refresh_embeddings[1]
If the selected provider rate-limits requests, add a one-second delay:
rake chatbot:refresh_embeddings[1,1]
Embedding costs vary by provider and model. Monitor usage and billing in the dashboard for your selected embeddings provider.
Embeddings are created only for Posts in the scope selected above. The benchmark_user strategy uses the configured trust level, while categories uses the explicitly selected Categories. Personal Messages are never embedded.
@37Rb writes: "Here’s a SQL query I’m using with the Data Explorer plugin to monitor & verify embeddings… in case it helps anyone else."
SELECT e.id, e.post_id AS post, p.topic_id AS topic, p.post_number,
e.provider, e.model, e.created_at, e.updated_at,
p.deleted_at AS post_deleted
FROM chatbot_post_embeddings e LEFT JOIN posts p ON e.post_id = p.id
You might get an error like this:
OpenAI HTTP Error (spotted in ruby-openai 6.3.1): {"error"=>{"message"=>"This model's maximum context length is 8192 tokens, however you requested 8528 tokens (8528 in your prompt; 0 for the completion). Please reduce your prompt; or completion length.", "type"=>"invalid_request_error", "param"=>nil, "code"=>nil}}
In this example, the embedding model has a limit of:
8192 tokens
however you requested 8528
Reduce the current value of this legacy-named setting, which applies to every embeddings provider:
chatbot_open_ai_embeddings_char_limit
As a starting point for English text, multiply the token difference by roughly four characters.
So, in this example, 4 x (8528 - 8192) = 1344
Dropping chatbot_open_ai_embeddings_char_limit by about 1,500 would therefore be a cautious first adjustment. Tokenisation varies by provider, model, and language, so lower it further if the error continues.
Select chatbot_embeddings_provider, then choose the model shown for that provider. OpenAI, Google Gemini, and xAI are supported; Anthropic does not provide an embeddings API. The selected provider reuses its provider-specific API key.
Changing the embeddings provider or model automatically makes older Post and Topic-title vectors invalid. Background jobs gradually regenerate them with the new configuration, so you do not need to delete them manually.
Embedding records and their search indexes use a shared 1,536-dimension storage contract. When text-embedding-3-large is selected, Chatbot uses OpenAI's dimensions parameter to request a shortened 1,536-dimension vector rather than storing the model's native 3,072-dimension output.
For a custom embeddings service, set chatbot_open_ai_embeddings_model_custom_name and, when required, chatbot_open_ai_embeddings_model_custom_url. The endpoint must implement the selected provider's embeddings API shape and return exactly 1,536 dimensions.
To refresh every in-scope embedding immediately, enter the container and run:
rake chatbot:refresh_embeddings
Use rake chatbot:refresh_embeddings[1] only to fill missing rows. Add a positive delay as the second argument, for example rake chatbot:refresh_embeddings[1,1], if the provider rate-limits requests.
chatbot_forum_search_tool_similarity_threshold controls the minimum semantic similarity and
chatbot_forum_search_tool_max_results limits the result count. If a new embeddings model returns
few useful results, retune the threshold rather than assuming scores are directly comparable with
the previous model.
Search can return individual Posts or Topics, optionally include Topic-title embeddings, and blend Discourse keyword search with semantic search. Group and Tag promotion settings can promote matches from preferred authors or Topics without restricting the embedding scope to them. These controls affect relevance; they do not add per-request permissions beyond the configured embedding scope.
The bot supports Topic Posts, Personal Messages, Chat channels, and Chat threads when those surfaces are enabled in Discourse and allowed in Chatbot settings.
- Subject to permissions and quota, the bot responds when it is @mentioned.
- In a Topic or Chat conversation containing only the bot and one other user, it can respond without an @mention.
- Replying directly to the bot can invoke it.
chatbot_max_look_behindcontrols how much prior conversation context is sent, which affects cost.chatbot_permitted_all_categoriesandchatbot_permitted_categoriescontrol Topic availability.chatbot_permitted_in_private_messagesandchatbot_permitted_in_chatcontrol those surfaces.
chatbot_unlimited_topic_auto_replies is enabled by default. Once the bot has participated, it can keep replying without a mention while only one human is participating. The system user and built-in bot accounts do not count as humans.
Disable unlimited replies to use chatbot_auto_reply_up_to_post_count:
- 0: require an @mention or a direct reply to a bot post, including in auto-response categories.
- A positive number: allow automatic replies while the topic's total post count is at or below that number. Follow-ups still require previous bot participation and only one human participant.
The count includes human and bot posts, not just questions or bot replies. For example, with a limit of 3, a human question, bot answer, and human follow-up total 3 posts, so the bot can answer that follow-up. The next human post exceeds the limit and needs a mention or direct reply.
The final automatic reply includes a reminder to reply directly or @mention the bot to continue.
Explicit mentions and direct replies work above the limit, subject to the usual permissions and quotas. These settings do not affect Personal Messages or Chat.
In a Personal Message whose only recipients are you and the configured bot (with no recipient groups), new posts invoke the bot without an @mention, including before its first reply. Normal permission, quota, and question-blocking checks still apply.
Categories listed in chatbot_auto_respond_categories can receive an automatic reply to each new Topic. Configure the Category-specific additional prompt in that Category's settings.
Write that prompt as the user's request, not as a replacement system prompt. For example:
Welcome me, introduce yourself, and use local forum search to share five relevant forum Topics with links.
Add user_information to the relevant trust-level tool allowlist to let the bot collect outstanding editable User Fields in private conversations. Text, dropdown, and confirmation fields are supported; multi-select fields are not.
Enable chatbot_blocked_questions_enabled to check requests before calling the full language model, in Topics, Personal Messages, and Chat.
Select the method with chatbot_blocked_questions_strategy:
system_one(default) preserves existing behaviour: use System One when configured, with example-based embedding matching as a fallback.examplesalways uses example-based embedding matching, regardless of System One credentials. Choose this to combine example-based blocking with System One tool selection.
The system_one option is available only when the System One model, URL and key are populated. Reload the settings page after changing these connection settings to refresh the choices. Clearing credentials retains the saved strategy but makes blocking fall back to examples.
With system_one selected and all three settings below populated, System One evaluates whether the question relates to this community:
| Setting | Default |
|---|---|
chatbot_system_one_model |
jev-latest |
chatbot_system_one_url |
https://api.typesafe.ai/v1/systemone (full evaluation endpoint) |
chatbot_system_one_key |
Empty; stored as a secret |
The endpoint must implement the TypeSafe System One API. This path sends the forum title and descriptions, category description when available, the question, and up to four preceding conversation messages. It does not require or consult chatbot_blocked_question_examples. Category descriptions can explicitly permit off-topic discussion. Keep descriptions accurate: they define the scope used by the model.
The model chooses in scope, out of scope, or unclear. Only an out-of-scope decision meeting chatbot_system_one_out_of_scope_threshold (default 0.9, range 0–1) produces an explicit refusal explaining that the question appears unrelated to the forum and inviting a community-related question. Lower values block more readily; for example, 0.75 blocks an out-of-scope result of 0.77. Unclear and lower-probability results proceed normally. This is an initial conservative threshold, not an accuracy guarantee; validate it against your forum's questions. The embedding similarity setting does not affect System One. Model decisions, all three probabilities, the applied threshold, the reason for allowing or declining, and token usage appear in the existing optional inner-thoughts audit.
The check includes up to four preceding visible messages from the same topic or Chat thread, labelled by speaker role and limited to 2,000 characters each. Bot diagnostic dumps are excluded before applying that limit. Short follow-ups and pleas to continue are interpreted against this context, including earlier refused questions. This bounded context cannot guarantee detection of references to older or truncated messages.
System One request and response bodies are logged when verbose console logging is enabled or verbose Rails logging is set to api_calls_only or all. Entries include a correlation ID, response HTTP status and elapsed time; failures include the exception class. Authorization headers are omitted and the configured API key is redacted from parsed JSON before log serialization. Non-JSON response bodies are omitted. These diagnostic bodies include question text and conversation context, including PM content, so enable verbose logging only when needed.
With the examples strategy, or if any System One connection setting is blank, the existing embedding matcher compares questions against chatbot_blocked_question_examples, using chatbot_blocked_questions_similarity_threshold. Matching questions receive a canned decline containing the configured subject label. System One timeouts, HTTP errors, and invalid responses also fall back to this matcher. Keep examples if you want this fallback to block questions; without examples, requests proceed normally. Embedding failures also allow normal processing.
The chatbot_tools_low_trust, chatbot_tools_medium_trust, and
chatbot_tools_high_trust settings determine which built-in tools the bot may expose. An empty
selection exposes no built-in tools. Selecting a tool is an allowlist decision; runtime
requirements still apply. For example, news, web_search, web_crawler, and stock_data need
their API credentials, while local_forum_search needs embeddings to be enabled. Extension tools
provided by other plugins are controlled by those plugins instead.
The defaults are:
- Low and medium trust:
calculate,remaining_bot_quota, andlocal_forum_search. - High trust: those tools plus
wikipedia,news,web_crawler,web_search, andstock_data.
Runtime requirements still take precedence over these defaults. For example,
local_forum_search is exposed only when embeddings are enabled, and tools backed by external
services are exposed only when the required credentials are configured.
The user_information tool is available only in private conversations. The escalate_to_staff
tool is available only in private Chat and creates a staff Personal Message containing the
configured amount of conversation history. More tools can improve grounding and task coverage,
but tool loops may add latency and provider cost.
External tools use separate service credentials:
newsrequireschatbot_news_api_token;web_crawleruses Firecrawl or Jina;web_searchuses SerpAPI or Jina; andstock_datarequires a Marketstack key.
The relevant key and notional quota-cost settings are hidden from the model and documented in the admin settings UI.
The calculate tool uses Dentaku expression syntax. It accepts constants such as PI and E,
normalizes common model-generated forms such as Math::PI, and returns correction guidance for
invalid expressions rather than evaluating the same rejected input repeatedly.
For Chatbot to work in Chat you must have Chat enabled.
Enable chatbot_system_one_tool_selection_enabled to filter the eligible tool set once
per request, before the answering model runs. It uses the existing System One model, URL,
and API key, independently of question blocking. There is no logging-only mode: disabled
means no selection call or selection diagnostic; enabled means active filtering.
| Setting | Default | Purpose |
|---|---|---|
chatbot_system_one_tool_selection_enabled |
false |
Enable active selection. |
chatbot_system_one_tool_selection_context |
Empty | Optional administrator guidance, up to 4,000 characters. |
chatbot_system_one_tool_selection_look_back |
4 |
Include 0–20 preceding messages, independently of the answering model's history window. |
chatbot_system_one_tool_removal_threshold |
0.9 |
Remove only tools classified irrelevant at or above this probability. |
For example, additional context could say: “Keep forum search available for questions about members' experiences. Keep web search available when the user requests external evidence.” The service receives the current query, topic/channel title, category context, recent messages with speaker roles, and eligible tool descriptions and parameters. Each preceding message is limited to 2,000 characters. Chat history stays within the current thread; deleted messages and bot-authored Inner Thoughts dumps are excluded, as are hidden/non-regular forum posts. The current query is not truncated. If the selection state exceeds 40,000 characters, or administrator guidance exceeds 4,000 characters, all eligible tools remain available.
Relevant, unclear, and below-threshold decisions retain the tool. Missing configuration, provider errors, and invalid responses also retain the eligible set. A forced local search remains available. If the administrator requires any tool call and selection would remove every tool, the eligible set is retained. Existing access rules, credentials and extension availability checks run first; selection never enables an otherwise unavailable tool.
The selected set stays fixed for the response's tool loop and applies to both Chat Completions and Responses API requests. It controls tool definitions, execution lookup and tool-dependent prompts. For user-information collection and staff escalation, the criteria also consider whether the user requests the action or answers a pending collection question. This is a relevance check, not an authorization or proposed-argument check.
When Inner Thoughts output is enabled, a selection entry says, for example: “I removed these tools from the available set based on the query: wikipedia, paint_picture.” It includes removed/retained names, per-tool probabilities, protected tools, model and usage. It also explains keeping all tools or falling back. These diagnostics are not fed back to the answering model. System One usage is reported separately, like scope-evaluation usage.
Filtering adds an evaluation call and can change prompt-cache reuse; reduced tool count does not guarantee lower total cost or better answers. Thresholds and guidance should be evaluated against your community's requests.
Other plugins can add tools by loading zero-argument subclasses of
DiscourseChatbot::Tool. Chatbot discovers subclasses that are not in its built-in tool
list. Trust-level tool settings only control built-in tools and do not affect extension tools.
An extension class may define self.available?(opts) to decide at request time whether it should
be exposed; classes without this method remain available by default. If an extension raises while
checking availability or initializing, Chatbot logs the error and omits that extension without
affecting the remaining tools. Request-aware selection also considers extension tools that
pass these checks. Extensions whose tools have side effects can override the instance method
requires_user_intent? to return true, so selection checks whether the user requests that action.
Requests made through the Chat Completions API can use additional inference-time computation to review or compare an answer before returning it. Configure this with chatbot_advanced_local_reasoning:
| Strategy | Behaviour | Additional model calls after the first answer |
|---|---|---|
simple |
Uses the existing tool and answer loop without extra local reasoning. This is the default. | None |
verify_and_revise |
Asks for a compact review. A corrected answer is generated only when the review identifies a material defect. | One review, plus one conditional revision |
best_of_two |
Generates an independent second answer and asks a compact pairwise judge to select the stronger candidate. | One alternative and one judge |
uncertainty_guided |
Uses generated-token probabilities to accept a confident first answer immediately. A low-confidence answer is escalated to best_of_two. |
None when confident; otherwise one alternative and one judge |
For uncertainty_guided, chatbot_advanced_local_reasoning_min_confidence sets the acceptance threshold from 0 to 100. Confidence is the geometric mean probability of the generated tokens. If an OpenAI-compatible provider does not return log probabilities, the strategy falls back to comparing two answers. If the provider rejects the logprobs parameter, the request is retried without it before falling back.
These strategies have several safeguards:
- They apply only to Chat Completions. Reasoning models using the Responses API retain their native reasoning flow.
- Tools run only on the shared initial path. They are disabled for alternative, review, revision, and judge calls, preventing repeated side effects.
- Persisted inner-thought audit posts are excluded from future model context, including when general whispers are included in post history.
- Additional calls count towards
chatbot_chain_of_thought_max_iterationsandchatbot_open_ai_max_chain_tokens. - Revised and alternative answers are checked against any trusted URL provenance collected from tools.
- Usable partial responses produced at the configured completion length limit are returned without additional reasoning.
- If optional reasoning fails, exceeds its available budget, produces malformed control output, or proposes an invalid answer, the already-valid first answer is returned.
The staff-visible inner-thoughts trace records tool calls, the selected advanced strategy, compact review, confidence, and selection information, and the final outcome in chronological order, including safe fallbacks. It also includes aggregate input, output, cache, and provider-reported reasoning token statistics for the complete response. These statistics are accumulated outside the model context and are only merged into the persisted audit entry after generation finishes. It does not request or expose a model's hidden chain-of-thought.
chatbot_max_response_tokens limits visible output for non-reasoning Chat Completions requests,
while chatbot_open_ai_max_reasoning_output_tokens limits the combined reasoning and visible output
for Responses API requests. chatbot_open_ai_max_chain_tokens,
chatbot_chain_of_thought_max_iterations, and chatbot_chain_of_thought_max_tool_calls cap the
overall tool loop. chatbot_tool_response_char_limit caps content returned by web tools before it
is included in a later model request.
The chain-token limit counts actual reported model usage, including model usage explicitly
reported by tools. Token-based user quotas still include all notional tool charges, such as
Jina response characters multiplied by the configured cost multiplier. These charges do not
exhaust the chain-token limit. When tools incur a charge, Inner Thoughts also reports
tool_quota_tokens (all tool charges), quota_tokens (the combined token quota cost), and
chain_tokens (model usage counted against the chain limit). Query-based quotas still charge
one query per request. Custom tools can return model_token_usage alongside the existing
token_usage quota charge to include real model usage in the chain budget.
When chatbot_url_integrity_check is enabled, Chatbot checks generated URLs against trusted URLs
from the conversation and tool results. chatbot_chain_of_thought_max_url_repair_attempts controls
how many times the model may repair an unsupported URL before the response is rejected.
- Scaling LLM Test-Time Compute Optimally can be More Effective than Scaling Model Parameters motivates adaptive allocation of inference-time compute and compares search strategies with best-of-N sampling.
- Self-Refine: Iterative Refinement with Self-Feedback describes the generate, self-review, and revise pattern behind
verify_and_revise. - Self-Consistency Improves Chain of Thought Reasoning in Language Models establishes the value of sampling multiple reasoning paths rather than relying on one greedy answer.
- Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena studies model-based pairwise evaluation and its biases, informing the compact judge used by
best_of_two. - Semantic Uncertainty: Linguistic Invariances for Uncertainty Estimation in Natural Language Generation motivates uncertainty-aware escalation. The plugin uses a cheaper token-probability signal rather than semantic entropy.
This is governed mostly by a setting: chatbot_reply_job_time_delay over which you have discretion.
The intention of having this setting is to:
- protect you from reaching the selected provider's rate limits
- protect your site from users that would like to spam the bot and cost you money.
It defaults to two seconds and can be reduced to zero 🏎️, but be aware of the above risks.
Setting this to zero can make the bot, including tool-enabled conversations, feel much more responsive.
Obviously this can be a bit artificial and no real person would actually type that fast ... but set it to your taste and wallet size.
Chatbot cannot directly control provider response time. Higher-capability models, greater reasoning effort, advanced local reasoning, and multi-step tool use can all increase latency.
For Chatbot to work in Chat you must have Chat enabled.
Choose providers independently for language-model replies, embeddings, vision, and image generation. Each capability uses the API key belonging to its selected provider.
| Capability | OpenAI | Anthropic | Google Gemini | xAI |
|---|---|---|---|---|
| LLM replies and tools | ✅ | ✅ | ✅ | ✅ |
| Embeddings | ✅ | — | ✅ | ✅ |
| Vision | ✅ | ✅ | ✅ | ✅ |
| Image generation | ✅ | — | ✅ | ✅ |
| Image editing | GPT Image models | — | — | ✅ |
| PDF conversation input | ✅ | — | — | — |
Select the reply provider with chatbot_llm_provider, then enter its key in chatbot_open_ai_token, chatbot_anthropic_token, chatbot_google_gemini_token, or chatbot_x_ai_token. Keys are available from OpenAI, Anthropic, Google AI Studio, and the xAI Console. Provider-specific keys are intentionally retained, so changing one capability's provider does not require copying credentials into a generic key.
The language model is selected independently for low-, medium-, and high-trust users. The settings UI displays only the active provider's model dropdowns. The lists contain stable model names rather than dated snapshot variants; use the custom-model option when you need another model.
chatbot_embeddings_provider, chatbot_vision_provider, and chatbot_image_provider select providers for those capabilities independently of the reply provider. Their model settings are likewise shown only for the selected provider.
Leave a custom URL blank to use Chatbot's built-in official endpoint for the selected provider. Generation controls for temperature, top-p, frequency penalty, and presence penalty are shown only for OpenAI and xAI, whose supported API shapes accept them. chatbot_api_supports_name_attribute is OpenAI-only and should remain disabled for custom endpoints unless they explicitly document support. OpenAI reasoning and Responses API settings are hidden for the other providers.
- Create an OpenAI API key and ensure API billing is enabled.
- Set
chatbot_llm_providerto OpenAI and paste the key intochatbot_open_ai_token. - Leave the custom URL blank, choose an OpenAI model for each trust level you intend to use, and add your test group to the matching Chatbot access setting.
- Mention the bot in an allowed Topic, Personal Message, or Chat to test it.
Custom names and URLs let Chatbot use services that implement one of the supported providers' API shapes. Select the provider shape the service emulates, enable the custom model for each applicable trust level, enter the exact model name, and set the custom URL. The provider-specific key for the selected shape is sent to that endpoint.
This supports OpenAI-compatible services such as many proxies and local model servers, including Ollama when its OpenAI-compatible endpoint is enabled. Endpoint paths differ between services, so use the base URL documented by that service—commonly a URL ending in /v1/—rather than assuming one universal Ollama or proxy URL.
Azure OpenAI remains available through the OpenAI custom URL, API type, and API version settings. Custom embeddings, vision, and image endpoints have separate URL overrides. Compatibility depends on the endpoint implementing the request and response fields used by the selected capability.
When installed, the plugin creates an AI bot user with these initial attributes:
- Name: 'Chatbot'
- User ID: -4
- Bio: "Hi, I’m not a real person. I’m a bot that can discuss things with you. Don't take me too seriously. Sometimes, I'm even right about stuff!"
- Group Name: "ai_bot_group"
- Group Full Name: "AI Bots"
You can edit the name, avatar and bio (see locale string in admin -> customize -> text) as you wish but make it easy to mention.
Initially no one has access to the bot, including staff. Assign groups to the low-, medium-, or high-trust Chatbot group settings. A user receives the model, tools, and quota associated with their highest matching Chatbot trust level.
Hosted model APIs are generally metered services, so Chatbot includes quotas to control access, cost, and abuse. Set chatbot_quota_basis to enforce either query or token quotas, then configure the allowance for each trust level. Check the pricing documentation for every provider and model you enable.
There are several locale text "settings" that influence what the bot receives and how the bot responds.
The most important one you should consider changing is the bot's system prompt. This is sent every time you speak to the bot.
For example, you can try a system prompt like:
You are an extreme Formula One fan. You love everything to do with motorsport and its high-octane excitement.
Keep the tool-use instructions after "You are a helpful assistant." when tools are selected, or you may break agent behaviour. Reset the prompt if you run into problems.
Try one that is most appropriate for the subject matter of your forum. Be creative!
Changing these locale strings can make the bot behave very differently. They apply globally to future requests rather than acting as per-conversation controls. I recommend changing only the system prompts because the other prompt strings play important roles in tool behavior and conversation attribution.
There are separate open and private system prompts. The open prompt is used in public Topics and Chat channels; the private prompt is used in Personal Messages and direct-message Chat. Keep the tool-use instructions intact whenever the corresponding trust level has tools enabled.
NB In Topics, the first Post and Topic Title are sent in addition to the window of Posts (determined by the lookback setting) to give the bot more context.
You can edit these strings in Admin -> Customize -> Text under chatbot.prompt.
View the chatbot prompt text in the server locale file.
The bot supports Chat Messages and Topic Posts, including Private Messages (if configured).
You can prompt the bot to respond by replying to it, or @ mentioning it. You can set how far the bot looks behind to get context for a response. The bigger the value the more costly will be each call.
There's a floating quick-access button that connects you immediately to the bot. Configure it with chatbot_quick_access_talk_button, choose whether the bot starts the conversation with chatbot_quick_access_bot_kicks_off, and optionally choose an icon with chatbot_quick_access_talk_button_bot_icon. If the icon is blank, Chatbot uses the bot user's avatar.
And remember, you can also customise the text that appears when it is expanded by editing the locale text using Admin -> Customize -> Text chatbot.
For temporary diagnostics:
- enable
chatbot_include_inner_thoughts_in_private_messageswhen testing privately; - set
chatbot_enable_verbose_rails_loggingtoapi_calls_onlyorall; - choose the warning log destination if you need entries to appear in the Discourse
/logsinterface; - reproduce the request, then inspect the Sidekiq job exception and Rails logs immediately;
- never publish API keys or unredacted request headers.
The provider's HTTP status and response body are usually more useful than the final Ruby stack trace. Custom endpoints should be checked against the API shape selected in Chatbot.
Other plugins can add tools without maintaining a fork of Chatbot. See the function-extension example and the original extension pull request.
Extension tools subclass DiscourseChatbot::Tool. They may implement self.available?(opts) for request-time availability. Trust-level allowlists control built-in tools; an extension plugin remains responsible for the permissions and configuration of its own tools.
- Semantic search permissions are based on the configured embedding scope, not on each person asking the bot.
- User Fields collection does not support multi-select fields.
- Custom endpoints vary in their support for tools and optional request attributes.
- Bot typing indicators and streamed responses remain potential future improvements.
- Responding to edits that add a missing @mention remains potential future work.
- Thanks to @MarcP for enthusiastic support and detailed testing feedback.
- Thanks to contributors to ruby-openai, which provides the shared OpenAI-compatible client.
- The floating button design was based on Discourse's Material Design Stock Theme.
- The original fixtures code was based on work from discourse-autobot.
- Thanks to @P16, whose early chatbot work helped inspire this plugin.
Remove the plugin's clone statement from app.yml, then rebuild the Discourse container. Plugin database tables are retained unless you remove them separately.
I'm not responsible for the bot's responses. Consider the plugin to be at beta stage; things can go wrong. Understand the strengths, limitations, and risks of LLMs before enabling it. They can generate convincing text that is factually wrong.
Conversation content, uploaded media, and tool results may be sent to the providers selected for LLM replies, vision, images, embeddings, or external tools. Local forum search may send matching embedded Posts from the configured scope to the reply provider. Review every selected provider's retention and data-use terms, and disclose this processing in your forum's terms of service and privacy notice.
Generated-output terms differ by provider and jurisdiction. Review the terms for every provider you enable. OpenAI's related guidance is available in Will OpenAI claim copyright over what outputs I generate with the API?
