Let a chatbot answer with real SaleSys components: buttons, forms, lists, facts, stats and tables. It works natively inside SaleSys and on any other page. The bot sends small JSON blocks and the kit renders them with the actual SaleSys renderer.
This is the offline demo bot. It goes through every block and interaction: quick replies, multi-choice, lists, details, progress, confirm buttons, links, forms with validation, stats and tables.
Every button, field, switch and list here is the real SaleSys component, in the selected org theme.
Create a view from chat.view.html. SaleSys renders the blocks itself, in the org's theme. Set DEMO = false to talk to Claude through the relay as the signed-in user.
One script with the real renderer bundled in. Works on any page and in any framework.
<div id="chat" style="height:600px"></div>
<script src="https://kit.salesys.ai/s2-chat.js"></script>
<script>
S2Chat.mount('#chat', { bot: myBot, theme: 'Lila' })
</script>
Add prompt.md to the system prompt and reply-tool.json as a tool. Force tool_choice: reply. That's about 2.5k tokens in total.
// A bot is any async function. messages is the conversation in Anthropic Messages format:
// your replies are `reply` tool_use blocks, clicks and forms come back as tool_result JSON.
async function myBot({ messages }) {
const res = await fetch('/my-backend', { method: 'POST', body: JSON.stringify({ messages }) })
return res.json() // { blocks: [...], toolUseId? }
}
// Or use the hosted relay (Claude, for signed-in SaleSys users):
S2Chat.mount('#chat', { relay: { token: saleSysAccessToken, system: 'You are...', model: 'claude-sonnet-5-5' } })
// Inside SaleSys, or with your own renderer: core only, no React
const chat = S2Chat.create({ bot: myBot, onChange: c => render(c.html()) }) // s2chat-core.js
| Block | What it's for | Renders as |
|---|
{"type":"button","id":"pause"} // a buttons item (confirm: true asks for a second click first)
{"type":"choice","ids":["lists"]} // choices (multiple: true gives several ids)
{"type":"select","id":"sthlm"} // a selectable list item
{"type":"form","id":"customer","values":{"name":"Anna","channels":["sms"],"gdpr":true}}
"Shown to the user." // they typed instead (their text follows)
The model never writes markup. It sends JSON that is validated against the schema. All text is escaped, and every handler is a fixed call that only references validated ids. Links are limited to https, mailto and tel and are opened by the kit. A reply can't run code, load scripts or inject templates, in SaleSys or anywhere else.
POST https://kit.salesys.ai/api/reply with Authorization: Bearer <SaleSys access token> and body { system, messages, model }. It returns { blocks, toolUseId }. The token is checked against SaleSys, so only signed-in SaleSys users can use it.
s2-chat.js (anywhere) - s2chat-core.js (core) - s2chat.mjs (ES module) - demo.mjs - prompt.md - reply-tool.json - chat.view.html - all SaleSys components