Technical description
Node 22+, zero dependencies (`node:http`, built-in `fetch`). Every client has a JSON knowledge base and a `config/client.json`; a new vertical is a new JSON file, not new code.
How to run it
node src/cli.mjs serve # HTTP (PORT, default 8788; this demo runs on 8798)
node _qa/smoke.mjs # 12/12 checks, offline, $0
node src/cli.mjs test --file sample/lead-implant.json
node src/cli.mjs metrics
node src/cli.mjs digest --day 2026-10-21
# live model (production): "llm": { "mode": "live" } + DEEPSEEK_API_KEY
# without a key the machine falls back to offline rules
API
| method | path | what it does |
|---|---|---|
POST | /lead | new inquiry (JSON or form) — the channel connects here |
POST | /lead/:id/message | the next turn of the conversation |
GET | /lead/:id | the whole conversation |
POST | /lead/:id/takeover | a human takes the conversation over |
POST | /lead/:id/human-reply | a human reply in the same thread |
POST | /learn | a new rule in one sentence |
GET | /watch | operator dashboard |
GET | /metrics | numbers: totals, exceptions, average and p95 reply time, SLA |
GET | /digest?day= | daily report (the same text sent to Telegram) |
Data
- knowledge/<client>.json — services, prices, hours, rules, FAQ (the knowledge base is the product)
- config/client.json — client name, tone, SLA, qualification, CRM (no secrets)
- data/events.jsonl — every event with its timestamp (append-only, source of the metrics)
Limits — what this demo does not do
- The demo runs offline (keyword rules) — enough to show, not enough to sell without the model.
- No mail/WhatsApp adapter — the channel is a webhook on `/lead`; reply delivery is the next adapter.
- One client per instance (one `config/client.json`).
- The demo has no authentication — anyone can send an inquiry and take a conversation over.
How it is deployed
One Node process behind nginx, a systemd unit, Let’s Encrypt. Recipe: E:\poslovi\DEMO-REGISTAR.md.
The demo cannot spend money: it runs offline and no `DEEPSEEK_API_KEY` is present in the environment.