How to Set Up Discord Integration with ChocolateLMLite Webhooks
Configure ChocolateLMLite to POST generated LLM responses to a Discord webhook URL by enabling the global EnableWebhook flag and setting persona-specific webhook_url and webhook_body fields to match Discord's expected JSON payload structure.
ChocolateLMLite, an open-source LLM assistant framework maintained by gpsnmeajp, supports real-time HTTP webhooks that forward AI-generated responses to external services. Setting up Discord integration with ChocolateLMLite webhooks allows you to stream chat completions directly into a Discord channel using Discord's native webhook API and the placeholder substitution system implemented in the source code.
How ChocolateLMLite Webhooks Work
The webhook system operates asynchronously to prevent blocking the UI during HTTP requests. When the LLM finishes generating a response, the system checks the global configuration and persona-specific settings before dispatching the payload.
According to the implementation in [src/LLM.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/LLM.cs#L462-L480), the execution flow follows these steps:
- Verify
fileManager.generalSettings.EnableWebhookis true. - Confirm the active persona has non-empty
WebhookUrlandWebhookBodyproperties. - Replace placeholders (
%text%,%id%,%name%) in theWebhookBodytemplate with the actual response text, persona ID, and persona name. - Wrap the POST operation in
Task.Runto executeHttpClient.PostAsyncon a background thread. - Log the HTTP status code or exception via
MyLog.LogWrite.
The placeholder substitution uses simple string replacement before the JSON payload is sent, allowing you to inject dynamic content into static webhook templates.
Prerequisites
Before configuring the integration, ensure you have the following:
- ChocolateLMLite installed and running (version supporting webhooks, commit
mainbranch or later). - Discord server permissions to create webhooks (Manage Webhooks permission).
- A target Discord channel where messages should appear.
Configuration Methods
You can enable Discord integration using three approaches: the web UI, direct JSON editing, or the REST API.
Method 1: Using the Web UI
The simplest approach uses the settings interface defined in static/setting.htm:
- Navigate to System Settings in the ChocolateLMLite interface.
- Locate the Webhook section (lines 68-76 in the source).
- Check Enable Webhook to set
EnableWebhookto true in [src/FileManager.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/FileManager.cs#L22-L28). - Enter your Discord Webhook URL in the Webhook URL field.
- Set the Webhook Body to
{"content":"%name%: %text%"}to format messages with the persona name prefix.
Method 2: Editing Persona JSON Directly
For advanced configuration, modify the persona JSON file directly. The parsing logic in [src/Persona.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/Persona.cs#L22-L30) reads these fields:
{
"name": "Assistant",
"webhook_url": "https://discord.com/api/webhooks/1234567890/AbCdEfGhIjKlMnOpQrStUvWxYz",
"webhook_body": "{\"content\":\"%name%: %text%\"}",
"EnableWebhook": true
}
Ensure the webhook_body contains valid JSON with escaped quotes, as the deserializer expects a string value that will be used as the POST body template.
Method 3: API Configuration
You can also configure webhooks programmatically via the REST API. According to [API.md](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/API.md#L158-L176), send a PATCH request to update persona settings:
curl -X PATCH http://localhost:5000/api/persona/assistant \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://discord.com/api/webhooks/1234567890/AbCdEfGhIjKlMnOpQrStUvWxYz",
"webhook_body": "{\"content\":\"%name%: %text%\"}",
"EnableWebhook": true
}'
The API validates the JSON structure before saving to the persona configuration file.
Discord-Specific Payload Formatting
Discord webhooks expect specific JSON schemas. ChocolateLMLite's placeholder system allows you to construct valid Discord payloads dynamically.
Basic Text Messages
For simple text forwarding, use the default template:
{"content":"%text%"}
This maps directly to Discord's content field, which accepts up to 2000 characters of plain text or Discord markdown.
Including Persona Identity
To identify which persona generated the response in multi-bot setups, include the name placeholder:
{"content":"**%name%**: %text%"}
The ** syntax renders bold text in Discord, making the persona name stand out in the channel.
Advanced Embeds (Optional)
While ChocolateLMLite sends the raw webhook_body string as-is, you can construct Discord embed objects by manually editing the JSON:
{
"content": null,
"embeds": [{
"title": "Response from %name%",
"description": "%text%",
"color": 3447003
}]
}
Ensure the JSON is minified and properly escaped when stored in the persona configuration string.
Testing Your Webhook Integration
Before deploying to production, verify the integration using a local test server. The repository includes a Flask example in [API.md](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/API.md#L39-L65) that captures incoming webhooks:
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
data = request.get_json()
print("[Webhook received]", data)
return jsonify({"status": "ok"}), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
Run the server with:
pip install flask
python webhook_server.py
Then configure ChocolateLMLite with webhook_url set to http://localhost:5000/webhook. Generate a test message in the chat interface; you should see the Discord-formatted JSON payload printed in your terminal, confirming the placeholder substitution and POST execution from [src/LLM.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/LLM.cs#L462-L480) is functioning correctly.
Troubleshooting Common Issues
Webhook Not Firing
If messages do not appear in Discord, verify the global flag in [src/FileManager.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/FileManager.cs#L22-L28):
- Ensure Enable Webhook is checked in System Settings.
- Check that
fileManager.generalSettings.EnableWebhookevaluates totruein the runtime state.
400 Bad Request Errors
Discord returns HTTP 400 if the JSON payload is malformed. Common causes:
- Unescaped quotes: When editing
webhook_bodymanually in JSON files, ensure inner quotes are escaped as\". - Missing
contentfield: Discord requires at least one ofcontentorembeds. Verify your template includes"content":"%text%"or similar.
Asynchronous Delay
Because the webhook executes inside Task.Run as shown in [src/LLM.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/LLM.cs#L462-L480), failures are logged asynchronously and may not trigger immediate UI errors. Check the application logs (via MyLog.LogWrite) for status codes or exception messages if messages fail to arrive.
Summary
- ChocolateLMLite supports Discord integration via HTTP webhooks configured in [
src/FileManager.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/FileManager.cs#L22-L28) and [src/Persona.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/Persona.cs#L22-L30). - Enable the global
EnableWebhookflag, then set thewebhook_url(Discord URL) andwebhook_body(JSON template) for each persona. - Use placeholders
%text%,%id%, and%name%to dynamically insert response data into Discord's expected JSON format, typically{"content":"%name%: %text%"}. - The actual POST request executes asynchronously in [
src/LLM.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/LLM.cs#L462-L480) usingHttpClient.PostAsync, ensuring the UI remains responsive during transmission to Discord.
Frequently Asked Questions
How do I find my Discord webhook URL?
Navigate to your Discord channel settings, select Integrations → Webhooks → New Webhook, then copy the generated URL. This URL follows the format https://discord.com/api/webhooks/{id}/{token} and must be pasted into the Webhook URL field in ChocolateLMLite's settings (defined in static/setting.htm) or directly into the persona JSON file parsed by [src/Persona.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/Persona.cs#L22-L30).
Why are my messages not appearing in Discord even though the webhook is enabled?
First, verify that the global EnableWebhook flag in [src/FileManager.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/FileManager.cs#L22-L28) is set to true in the System Settings UI. Next, confirm that the active persona has valid non-empty values for both WebhookUrl and WebhookBody (checked in [src/LLM.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/LLM.cs#L462-L480)). Finally, ensure your webhook_body contains valid JSON with properly escaped quotes, as Discord returns HTTP 400 errors for malformed payloads.
Can I customize the Discord message format beyond simple text?
Yes, the webhook_body field accepts any valid Discord webhook JSON payload. While the default template {"content":"%text%"} works for basic text, you can construct complex embed objects by manually editing the JSON string in the persona configuration. For example, use {"embeds":[{"title":"Response from %name%","description":"%text%","color":3447003}]} to send rich embeds. Ensure the JSON is minified and inner quotes are escaped as \" when stored in the configuration file parsed by [src/Persona.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/Persona.cs#L22-L30).
Does the webhook block the chat interface while sending to Discord?
No, the webhook execution is fully asynchronous. According to the implementation in [src/LLM.cs](https://github.com/gpsnmeajp/chocolatelmlite/blob/main/src/LLM.cs#L462-L480), the HTTP POST is wrapped in Task.Run, which executes the HttpClient.PostAsync call on a background thread. This design ensures that even if Discord's API experiences latency or temporary outages, the ChocolateLMLite chat interface remains responsive and the LLM generation flow continues uninterrupted. Errors are logged via MyLog.LogWrite for debugging without disrupting the user experience.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →