Synaplan
开源 AI 软件平台,面向企业:自托管 AI 代理,符合 GDPR 的聊天机器人小部件,RAG 知识库,WhatsApp 与 Outlook AI,MCP,多模型路由。支持 Docker、Kubernetes 或在 Germ 托管。
AI 翻译
尚未收集仓库信息。
尚未检测到更新。GitHub 发布版本后会显示在这里。
制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗A one-line <script> that gives a small business a chat assistant which answers from its own documents, books appointments, hands difficult conversations to a person and masks personal data before anything reaches the model.
The demo business is a fictional dental clinic. The same engine also serves WhatsApp through Meta's Cloud API, and it runs without any AI key using keyword rules.
Live demo: https://chatbot.marcelo.ar (fictional data, per-visitor limits, every conversation deleted after 24 hours).
| Widget on a business page | Full chat page |
|---|---|
The widget screenshot was taken locally in rule-based mode (no API key): the visitor asks for a cleaning, gets the free slots of the right professional and books one.
data/clinica.md (what the bot may say) and data/negocio.json (professionals, weekly schedules, reasons for a visit).[TEL_1] before the model sees them, and are restored only in tool calls and replies.Small clinics and shops get most of their questions in chat, outside office hours, and the same ten questions repeat: prices, hours, insurance, "can I come tomorrow?". A generic chatbot either invents answers or cannot act. This project shows a narrow assistant that answers only from the business's own documents, does one useful action (booking against a real schedule) and knows when to hand over to a person.
Technical decisions:
node:sqlite): no database server to install or pay for. A single file is enough for one business and keeps the deploy to "copy, npm ci, start". Two runtime dependencies in total: Express and the Anthropic SDK.frame-ancestors decides which sites may embed it.flowchart LR
subgraph Clients
W["Website widget<br/>widget.js + iframe"]
WA["WhatsApp Cloud API<br/>signed webhook"]
P["Admin panel<br/>/panel"]
end
W -->|"POST /api/chat"| API
WA -->|"POST /webhook/whatsapp"| API
P -->|"/api/admin (Basic auth)"| API
API["Express app<br/>validation, rate limits, CSP"] --> ENG
subgraph ENG["Conversation engine"]
direction TB
KB["Knowledge base<br/>clinica.md + negocio.json"]
MASK["PII masking"]
LLM["Claude with tools<br/>or keyword rules"]
TOOLS["Tools: availability, booking,<br/>cancel, contact, handoff"]
KB --> LLM
MASK --> LLM
LLM --> TOOLS
end
ENG --> DB[("SQLite")]
TOOLS --> NOTIFY["Team alert<br/>WhatsApp or webhook"]
/chat.html?embed=1 in an iframe. The page sends messages to POST /api/chat and polls for new ones, so replies typed by a person in the panel appear too.POST /webhook/whatsapp, are accepted only with a valid X-Hub-Signature-256 signature and go through the same engine./panel and can give the conversation back to the bot.Requires Node.js 22.13 or newer. No API key needed.
git clone https://github.com/Srproxo/ai-chat-widget-demo.git
cd ai-chat-widget-demo
npm ci
cp .env.example .env # enables the panel locally (admin / change-me); add ANTHROPIC_API_KEY for AI replies
npm run demo # loads fictional sample data, then starts the server
Then open:
?open=1 starts it open).env)npm start alone also works on a fresh clone without .env: rule-based mode, empty database, panel disabled. npm run seed resets the sample data at any time.
If ANTHROPIC_API_KEY is empty, nothing is sent to any external API and the engine answers with keyword rules (src/reglas.js):
2026-10-28 09:00 rios books that slot.data/clinica.md.Paste this before </body> on any page, with the URL of your deployment:
<script src="https://your-domain.example/widget.js" data-lang="en" defer></script>
| Attribute | Values | Default |
|---|---|---|
data-lang | en, es, pt | en |
data-position | right, left | right |
data-color | hex colour, e.g. #1f7a5c | #1f7a5c |
data-open | true to start with the panel open (focus stays on the page) | closed |
ALLOWED_EMBED_ORIGINS decides which sites may frame the chat (Content-Security-Policy: frame-ancestors on /chat.html). It defaults to * for local testing; in production list your own origins. The admin panel can never be framed.
data/clinica.md: services, prices, hours, policies, when to hand over. The bot only answers from this document.data/negocio.json: business name, time zone, appointment length, reasons for a visit and professionals with their weekly schedules.public/chat.html if your business is not a clinic.WA_PHONE_NUMBER_ID, WA_ACCESS_TOKEN, WA_VERIFY_TOKEN (any string you choose) and WA_APP_SECRET (the app secret, used to verify every incoming webhook).https://your-domain.example/webhook/whatsapp, the verify token to the same WA_VERIFY_TOKEN, and subscribe to messages.WA_REMINDER_TEMPLATE, WA_ALERT_TEMPLATE and WA_TEMPLATE_LANG (suggested bodies are in .env.example).Without these variables only the web chat is active. Without WA_APP_SECRET the webhook rejects every message.
All variables are optional. .env.example has the same list with comments.
| Variable | Purpose | Default |
|---|---|---|
ANTHROPIC_API_KEY | Enables the AI engine. Empty means keyword rules and no external calls. | empty |
CLAUDE_MODEL | Model id | claude-opus-5-5 |
PORT | HTTP port | 3000 |
BASE_URL | Public URL, used in links sent to the team | http://localhost:3000 |
TRUST_PROXY | Express trust proxy: 1 behind one reverse proxy, 0 without one | 1 |
CHAT_MAX_PER_IP | Chat messages per IP every 10 minutes | 60 |
ALLOWED_EMBED_ORIGINS | Origins allowed to frame the chat, comma-separated | * |
PANEL_USER | Admin panel user | admin |
PANEL_PASS | Admin panel password, 8+ characters. Empty disables the panel. | empty |
WA_PHONE_NUMBER_ID, WA_ACCESS_TOKEN | WhatsApp Cloud API credentials | empty |
WA_VERIFY_TOKEN | Token for Meta's webhook verification | empty |
WA_APP_SECRET | App secret to verify X-Hub-Signature-256 (required for the webhook) | empty |
WA_GRAPH_VERSION | Graph API version | v21.0 |
WA_REMINDER_TEMPLATE, WA_ALERT_TEMPLATE | Approved template names for reminders and team alerts | empty |
WA_TEMPLATE_LANG | Template language code | es_AR |
TEAM_WHATSAPP, TEAM_WEBHOOK_URL | Handoff notifications: WhatsApp number and/or webhook (Slack, Make, n8n) | empty |
REMINDER_HOUR |
POST must carry a valid X-Hub-Signature-256 (HMAC-SHA256 of the raw body with WA_APP_SECRET), compared in constant time. Without a secret the endpoint rejects everything.PANEL_PASS is set; no built-in password. Constant-time credential check, 10 failed logins per IP in 15 minutes lock that IP, responses are Cache-Control: no-store. Credentials travel in the Authorization header (not cookies), so cross-site request forgery does not apply; use HTTPS.textContent only; the panel escapes every API value. A Content-Security-Policy limits scripts, connections and frames to the app's own origin.Known limits: the chat and panel pages still use inline scripts, so the CSP allows 'unsafe-inline' for scripts; rate limits live in memory and apply per process; the panel has a single shared account.
public/widget.js Embeddable widget (no dependencies)
public/embed-example.html Sample business page with the widget
public/chat.html Chat UI (also inside the iframe with ?embed=1)
public/panel.html Admin panel
src/app.js Express app: chat API, webhook, panel API, error handling
src/security.js Rate limiter, constant-time compare, security headers
src/server.js Starts the server, reminders and demo cleanup
src/engine.js Conversation engine, system prompt and tools
src/reglas.js Keyword rules used when there is no AI key
src/agenda.js Availability and booking
src/pii.js Personal data masking
src/channels/ WhatsApp Cloud API and outbound dispatch
src/seed.js Fictional sample data
data/ Knowledge base and business definition
test/ node:test suite
app.cjs CommonJS startup file for Passenger hosting
npm test
The suite uses the built-in node:test runner, ignores any .env file, runs without an API key and never calls an external service. It covers the widget (in a fake DOM), the HTTP API, the rule-based mode, PII masking, the schedule, WhatsApp payloads and signatures, panel authentication and lockout, rate limits, input validation, security headers and XSS guards. GitHub Actions runs it on Node 22 and 24 for every push and pull request.
Node hosting with Passenger / LiteSpeed: upload the repository, run npm ci --omit=dev, set the environment variables in the hosting panel and use app.cjs as the startup file (it loads the ES module server with a dynamic import). The SQLite file needs a writable folder (DB_PATH).
VPS: install Node 22.13+, clone, npm ci --omit=dev, create .env and run npm start under systemd or another process manager. Put it behind a reverse proxy with HTTPS (Nginx, Caddy or Traefik), keep TRUST_PROXY=1 so rate limits see real client IPs, and set ALLOWED_EMBED_ORIGINS to the sites that embed the widget. HTTPS is required for the WhatsApp webhook.
For a public demo set DEMO_MODE=1 and a PANEL_PASS of 10+ characters (or leave it empty to keep the panel closed).
'unsafe-inline'.MIT, see LICENSE. Copyright (c) 2026 Srproxo.
Widget de chat con IA que se agrega a cualquier web con una sola etiqueta <script>. Responde con la información del negocio (data/clinica.md y data/negocio.json), agenda turnos por profesional, deriva a una persona cuando hace falta y enmascara teléfonos y DNI antes de enviar texto al modelo. El mismo motor atiende WhatsApp Cloud API, con verificación de firma obligatoria. Sin clave de IA funciona con reglas por palabras clave, así que se puede probar completo sin gastar nada: npm ci, cp .env.example .env y npm run demo. Usa SQLite embebido, sin framework de front, y el widget vive en Shadow DOM con el chat en un iframe. Demo en vivo con datos ficticios en https://chatbot.marcelo.ar (se borra cada 24 h).
Widget de chat com IA que se adiciona a qualquer site com uma única tag <script>. Responde com as informações do negócio (data/clinica.md e data/negocio.json), agenda consultas por profissional, encaminha para uma pessoa quando necessário e mascara telefones e documentos antes de enviar o texto ao modelo. O mesmo motor atende o WhatsApp Cloud API, com verificação de assinatura obrigatória. Sem chave de IA funciona com regras por palavras-chave, então dá para testar tudo sem custo: npm ci, cp .env.example .env e npm run demo. Usa SQLite embutido, sem framework de front-end, e o widget fica em Shadow DOM com o chat em um iframe. Demo online com dados fictícios em https://chatbot.marcelo.ar (apagada a cada 24 h).
| Hour (0-23) when next-day reminders go out |
18 |
TIMEZONE | Business time zone | America/Argentina/Buenos_Aires |
PII_MASK | 1 masks phone numbers and national IDs before the model, 0 turns it off | 1 |
DB_PATH | SQLite file | ./data/asistente.db |
DEMO_MODE | 1 turns on public demo mode | 0 |
DEMO_MAX_MSGS | Demo: messages per visitor | 12 |
DEMO_MAX_DIA | Demo: AI replies per day, all visitors | 400 |
DEMO_MAX_IP | Demo: messages per IP every 10 minutes | 30 |