Provider: your own API
"backend": { "type": "http" }
Put HelpPuff's widget, dashboard, leads and webhooks in front of anything you have built: your own agent, a LangChain or LlamaIndex app, a local model, a gateway. Nothing about your stack goes into HelpPuff, and you need no fork.
Two shapes, chosen with mode.
mode: "openai": any Chat Completions endpoint
vLLM, Ollama, LiteLLM, OpenRouter, DeepSeek, Together, or your own OpenAI-compatible server. HelpPuff keeps the conversation history (from its record of the conversation in D1, or KV without a database) and sends prompt.md as the system message.
"backend": {
"type": "http",
"mode": "openai",
"url": "https://llm.acme.com/v1",
"model": "llama-3.3-70b",
"token": { "env": "HELPPUFF_BACKEND_TOKEN" }
}mode: "helppuff": your service owns everything
Your service decides what to say; HelpPuff carries the messages. It POSTs:
POST {url}/start { siteId, sessionId, lead?, context, firstMessage? }
POST {url}/message { siteId, sessionId, state, input }contextis the page the visitor is on:{ pageUrl, pageTitle?, referrer?, utm?, locale? }.leadis the pre-chat form's answers, when there is one.inputis what the visitor did:{ kind: "text", text }, or{ kind: "action", actionId, value, label }for a button or form.stateis whatever you returned last time (below).
Answer with JSON:
{ "text": "Yes, we service Lilydale. Want a quote?" }or, for rich messages and state:
{
"messages": [
{ "type": "text", "text": "Yes, we service Lilydale." },
{ "type": "options", "options": [{ "id": "q", "label": "Get a quote", "value": "I'd like a quote" }] }
],
"state": { "conversation": "c-9" }
}Messages use the protocol's message shapes (id, ts and role may be left out). Or stream the reply as server-sent events:
event: delta data: {"text":"Yes, we "}
event: delta data: {"text":"service Lilydale."}
event: done data: {"text":"Yes, we service Lilydale.","state":{"conversation":"c-9"}}state comes back to you with the next message. It rides inside the signed session token, so keep it small (under 1 KB): an id into your own storage, not the conversation.
Authentication
token: sent asAuthorization: Bearer …. Store it withhelppuff secret set HELPPUFF_BACKEND_TOKEN.signingSecret: every request also carriesX-HelpPuff-TimestampandX-HelpPuff-Signature: sha256=<hex HMAC-SHA256 of "<timestamp>.<body>">, so your service can check the call came from your Worker.
"backend": {
"type": "http",
"mode": "helppuff",
"url": "https://agent.acme.com/helppuff",
"token": { "env": "HELPPUFF_BACKEND_TOKEN" },
"signingSecret": { "env": "HELPPUFF_BACKEND_SECRET" }
}Set up
npx @knowtific/helppuff init --url acme.com --backend http --http-url https://agent.acme.com/helppuff --http-mode helppuff --http-token "$TOKEN"Your API must answer within 25 seconds. Errors and timeouts become a polite "something went wrong" for the visitor; the details are only in the Worker's logs.
For more ways to build on HelpPuff, see Extending.