chatbot is a Gipity kit that drops a configurable AI assistant into any web app: a help bubble in the corner, a support bot, or an in-game NPC dialog. You give it a persona, optional scope guardrails (what it will and won't answer), and optional static knowledge; it streams answers from Gipity's LLM service. No API keys, no backend to write.

Install

gipity add chatbot

The installer drops the kit into src/packages/chatbot/, wires the import map (import { mount } from '@gipity/chatbot'), and declares llm: owner_pays in your gipity.yaml so logged-out visitors can use the bot. Frontend-only: no migrations, no functions. Run gipity deploy dev to ship.

Two ways to use it

1) Bubble widget (default) - a <chatbot-widget> custom element, floating launcher in the corner. The launcher shows a 💬 emoji by default; set ui.launcherIcon to an image URL to replace it. Assistant replies render minimal inline markdown (bold, italic, code, fenced blocks) with everything else HTML-escaped, so markdown in persona/knowledge answers displays properly:

<chatbot-widget id="bot"></chatbot-widget>
<script type="module">
  import { mount } from '@gipity/chatbot';
  import config from './js/chatbot.config.js';
  mount('#bot', config);
</script>

2) Headless engine - bring your own UI (an in-game NPC dialog box, a custom panel):

import { createChatbot } from '@gipity/chatbot';
import config from './js/chatbot.config.js';

const bot = createChatbot(config);
bot.on('delta', (text) => myUi.append(text));   // streaming chunks
bot.on('complete', () => myUi.stopThinking());
await bot.send('how do I fly the ship?');

Config

Install scaffolds src/js/chatbot.config.js with every key present, commented, and pre-filled - persona, scope guardrails (with a worked refusal example), a knowledge placeholder, ui, model. Edit it in place; it is the config reference, so don't go looking for the shape elsewhere. Only persona.name and persona.instructions are required.

One thing worth knowing before you edit it: scope is what keeps the bot on-topic ("if someone asks something off-topic it should politely decline"). Fill allowed / refused / onRefusal, and keep at least one refusalExamples pair - the worked example is what makes the guardrail hold in character. (A stricter pre-classification step is on the roadmap.)

Knowledge - 20k token budget

Give the bot facts to answer from. Two source types today:

If the combined sources exceed maxTokens (default 20,000; estimate is chars / 4), the kit throws rather than silently truncating - trim the sources or raise the budget. File-based knowledge and RAG embeddings are on the roadmap; for now inline the content as a text source.

Theming

Colors come from CSS variables. theme: 'match-app' (the default) reads --primary from the host page, so the bot matches your app automatically (the templates' gipity-theme.css defines --primary). Override per-instance with ui.primaryColor. The widget uses Shadow DOM, so host CSS won't leak in.

Headless engine events

When you drive the bot yourself with createChatbot(config):

bot.on('start',            () => {});            // a send is starting
bot.on('delta',            (text) => {});        // streaming text chunk
bot.on('message',          (msg)  => {});        // a full message landed in history
bot.on('complete',         (msg)  => {});        // assistant response finished
bot.on('usage',            (u)    => {});        // tokens / credits, when reported
bot.on('reset',            ()     => {});        // history cleared
bot.on('error',            (err)  => {});        // something threw
bot.on('knowledge_loaded', ({ tokens }) => {});  // a url source finished loading

What's not in v1

Tool-calling (an explicit tools allowlist exists in the config but project-function calling lands in a later PR), voice (app-tts + app-audio), vision, image generation, and persisted per-user history (storage) are wired in later PRs - the config keys are present but inert today. Build against persona + scope + knowledge for now.

Verifying

After wiring it up, gipity deploy dev and open the page - the launcher should appear in the corner; the greeting renders on first open and the starter chips show before the first message.

Related skills