◆ BOT FORGE

Setup & usage guide

Everything you need to create, embed, and manage AI chatbots with Bot Forge — by no-code dashboard, command line, or AI agent.

# Overview

Bot Forge is a multi-tenant chatbot platform. Each business is a tenant (one chatbot) identified by a tenantId. There are four ways to work with it:

  • Embed — drop one <script> tag on any website.
  • Console — no-code management at /admin (sign in with email or Google).
  • CLInpx bot-forge, an interactive shell (or one-shot commands) for terminal control.
  • MCP — connect one URL to an AI agent (Claude) and it builds & manages bots as tools.

Sign in (or create a workspace) to get a console for your team — your workspace only ever sees its own clients. Base URL for everything: https://bot.ops4ge.com.

# Quickstart (5 minutes)

  1. Create your workspace — sign up at https://bot.ops4ge.com/signup (email + password or Google). You become the Owner of a fresh, empty workspace.
  2. Create a chatbot — via the console, the CLI (bot-forge login first), or just ask an agent (MCP). Pick a tenantId like acme.
  3. Embed it — paste the snippet on the client's site:
<script src="https://bot.ops4ge.com/embed.v1.js" data-tenant="acme" defer></script>
  • Add knowledge (optional) — give it the business's FAQ/pricing for grounded answers.
  • # Concepts

    • User — you sign in with email + password or Google. Your account belongs to one or more workspaces.
    • Workspace (org) — a team's container. Tenants, API keys, leads, and usage all belong to a workspace; you only ever see your own.
    • RoleOwner (full control), Admin (manage tenants, keys, members), Member (create/edit tenants). See Accounts & teams.
    • Tenant — one chatbot for one business. The data-tenant in the embed snippet selects it.
    • API key / token — authenticates the CLI / MCP / a project backend. bot-forge login mints one for you; or create one in the console for CI. Scope to one tenant to limit it. Stored hashed; shown once.
    • Provider — each tenant runs on Claude, GPT, or Gemini.
    • RAG — optional vector search over the business's uploaded knowledge.

    # Embed on a website

    Paste once, right before </body>. Swap the tenant id:

    <script src="https://bot.ops4ge.com/embed.v1.js" data-tenant="acme" defer></script>

    The widget renders in a Shadow DOM, so it never clashes with the host site's CSS. It loads its branding automatically from https://bot.ops4ge.com/api/config?tenant=acme.

    Branding (color, logo, greeting, tone) comes from the tenant config. Set autoTheme: true to sample the host page's accent color instead of a fixed brand color. Optional attribute data-api="https://bot.ops4ge.com" overrides the API origin.

    The snippet loads /embed.v1.js — a version-pinned widget, so a future breaking change never ships silently to live sites (those land as /embed.v2.js).

    # Voice vs chat

    Every tenant can run two channels off the same knowledge and rules:

    • Chat — the text widget (💬 bubble). Streams replies, shows booking buttons, captures leads. On by default.
    • Voice — a human-like spoken agent (ElevenLabs Conversational AI). Same facts and guardrails as the chat bot, just a more conversational, spoken delivery. When enabled, a 🎙 button stacks directly above the chat bubble — a site can offer chat only, voice only conceptually, or both.

    Both ship in the same one-line snippet — there's nothing extra to embed. The voice button only appears when the tenant has voice enabled:

    <script src="https://bot.ops4ge.com/embed.v1.js" data-tenant="acme" defer></script>

    Enable voice

    Flip it on per tenant — dashboard (Tenants → Edit config → Voice bot), CLI, or create_chatbot/patch_chatbot (voiceEnabled):

    npx bot-forge set acme voice.enabled=true
    npx bot-forge set acme voice.voiceId=<elevenlabs-voice-id>     # optional
    npx bot-forge set acme voice.tone="warm, natural, conversational"  # optional
    npx bot-forge set acme voice.firstMessage="Hi! How can I help?"    # optional spoken greeting

    In the console (Tenants → Edit config → Voice), the voice is a dropdown of your ElevenLabs voices — no need to paste an id (a custom-id field is still there if you want one). On the first voice session, Bot Forge provisions an ElevenLabs agent for that tenant (synced from its facts) and reuses it after that.

    Voice needs ELEVENLABS_API_KEY set on the server — without it, voice stays off and the chat bot is unaffected. Twilio is not required to embed voice on a website; it's only for a later phase (linking a phone number to an agent for phone/SMS). Leads spoken during a call are captured via a post-call webhook, same as chat.

    Try it live: the demo widget on the home page and /demo.html has both — tap 💬 to chat or 🎙 to talk.

    # Chat protocol & security

    Allowed domains (who can embed a bot)

    Each tenant has an allowedDomains list that controls which origins may use its chatbot — this stops anyone copying a public data-tenant id and running the bot (and your LLM bill) from their own site.

    • Empty / unset — locked down: only same-origin requests work. /api/chat rejects other origins with 403 ORIGIN_NOT_ALLOWED before calling the model.
    • List of origins — only those exact origins, e.g. ["https://acme.com","https://www.acme.com"].
    • ["*"] — any site may embed it. Public demos only.

    Set it in the dashboard (Tenants → Edit config → Allowed domains), the CLI (npx bot-forge domains acme https://acme.com), or on create_chatbot. /api/configonly ever exposes branding/booking/leadCapture — never facts or the system prompt.

    Chat wire protocol (SSE)

    Only needed if you build a custom UI instead of the widget. POST /api/chat with { tenantId, sessionId, messages:[{role,content}] } returns Server-Sent Events:

    event: meta     data: { "provider": "...", "model": "..." }   // once at start
    event: text     data: { "delta": "..." }            // incremental reply text
    event: booking  data: { "options": {...}, "reason": "..." }  // show booking buttons
    event: lead     data: { "captured": true }          // a lead was saved
    event: done     data: {}                             // turn complete
    event: error    data: { "message": "..." }

    # Console (no-code)

    Sign in at https://bot.ops4ge.com/login with email + password or Google. The console is scoped to your workspace — you only see your own clients. From there:

    • Tenants — view config, pick the voice, manage each chatbot's RAG knowledge.
    • Leads — every captured contact with intent.
    • Conversations — full transcripts.
    • Team — invite members, set roles (Owner/Admin).
    • API keys — create / scope / revoke keys for CI & integrations.
    • Account — set or change your password.

    # Accounts & teams

    Bot Forge is multi-tenant for your team too. Each account belongs to a workspace that owns its tenants, keys, leads, and usage — fully isolated from other workspaces.

    Sign in

    • Email + password — sign up at /signup; manage your password under Account.
    • Google — one-click sign-in; first sign-in creates your workspace automatically.

    Roles

    RoleCan
    OwnerEverything — including billing/ownership of the workspace.
    AdminManage tenants, API keys, and team members (invite/role/remove).
    MemberCreate and edit the workspace's tenants.

    Invite teammates

    Console → Team → invite by email (as Admin or Member). Send them the generated link; they sign in (or sign up) and join your workspace.

    New sign-ups always start with an empty workspace. Inviting an existing user adds them to yours — they may need to sign out and back in for the new workspace to become active.

    # API keys & CLI login

    There are two ways to authenticate programmatic access:

    • CLI login (recommended) — run bot-forge login. It opens a browser approval (the OAuth device flow), links this device to your account, and stores a token for you. bot-forge logout revokes it.
    • API key (CI / backends) — create one in the console at /admin/keys. Use it as the BOTFORGE_API_KEY env var, an Authorization: Bearerheader (MCP / HTTP), or x-api-key (REST).

    Either way the token belongs to your workspace; scope it to a single tenant for least privilege, and revoke anytime (logout, or the console). Secrets are shown once — store them safely.

    # CLI — npx bot-forge

    No install needed (npx), or npm i -g bot-forgefor a bare bot-forge. First, link this device to your account — it opens a browser approval and stores the token in ~/.bot-forge, so you never have to paste a key:

    npx bot-forge login        # opens the browser to approve this device
    #  → Linked as you@email.com — owner of Your Workspace

    CI or headless? Paste a token instead: bot-forge login <bf_live_…>, or set BOTFORGE_API_KEY. bot-forge logout revokes the device token server-side.

    Interactive shell

    Run bot-forge with no command to enter a branded shell: Tab completes commands and tenant ids, ↑/↓ walks history, live spinners show progress, and your working directory appears in the status panel. Type exit (or Ctrl-C) to leave.

    npx bot-forge                # or:  bot-forge shell
    
    forge › whoami
    forge › create acme.json
    forge › test acme "what are your hours?"
    forge › usage --by day
    forge › embed acme

    One-shot commands

    Every command also runs directly — ideal for scripts & CI:

    npx bot-forge whoami                 # verify key + list chatbots
    npx bot-forge list                   # list chatbots
    npx bot-forge create acme.json       # create/update from JSON
    npx bot-forge set acme branding.greeting="Hi!"   # update fields
    npx bot-forge domains acme https://acme.com      # set allowed embed domains
    npx bot-forge knowledge acme faq.txt # ingest RAG ('-' = stdin); list|clear too
    npx bot-forge models                 # valid model ids per provider
    npx bot-forge test acme "your hours?"  # ask the bot, print its reply
    npx bot-forge usage --by day         # tokens, minutes & cost report
    npx bot-forge leads acme             # list captured leads
    npx bot-forge embed acme             # print the <script> snippet
    npx bot-forge prime                  # print the /prime onboarding prompt

    Account & CLI

    npx bot-forge login               # link this device (browser approval)
    npx bot-forge login bf_live_...   # or paste a token (CI / headless)
    npx bot-forge whoami              # who you're linked as + chatbots
    npx bot-forge logout              # revoke this device's token + clear it
    npx bot-forge version             # version + check npm for updates (alias: -v)
    npx bot-forge update              # upgrade to the latest release
    npx bot-forge help                # full, colour-coded command list

    Auth resolves in this order: BOTFORGE_API_KEY env var → a .env in the current folder → the token saved by login (in ~/.bot-forge). BOTFORGE_URL overrides the base URL (defaults to production).

    Tenant JSON for create:

    {
      "tenantId": "acme",
      "provider": "anthropic",
      "branding": { "name": "Acme Plumbing", "primaryColor": "#0ea5e9",
        "greeting": "Hi! Need a plumber? Ask me anything." },
      "knowledge": { "facts": "Open Mon-Sat 7-7. Emergency repairs, water heaters...",
        "tone": "friendly and reassuring", "ragEnabled": false },
      "booking": { "calendly": "https://calendly.com/acme/visit" },
      "leadCapture": true
    }

    # MCP — let an agent build chatbots

    Connect the Bot Forge MCP server to an AI agent (Claude Code, Claude Desktop, Cursor, …) and it builds & manages chatbots as tools — create, add knowledge, test, pull leads, get the embed snippet — all in plain conversation. Three steps.

    Step 1 — Connect the agent (one URL)

    Hosted, nothing to install. Point your agent at the MCP URL with your key as a Bearer token. Claude Code, one line (bash, zsh, PowerShell):

    claude mcp add --transport http bot-forge https://bot.ops4ge.com/api/mcp --header "Authorization: Bearer bf_live_..."

    Or add it to .mcp.json / Claude Desktop:

    {
      "mcpServers": {
        "bot-forge": {
          "type": "http",
          "url": "https://bot.ops4ge.com/api/mcp",
          "headers": { "Authorization": "Bearer bf_live_..." }
        }
      }
    }

    On connect, the server's initializeresponse briefs the agent on every tool, the chat protocol, valid models, and the allowedDomains security model — so it knows the whole surface without probing. The token is a Bot Forge API key (from Console → API keys) — use a tenant-scoped key so an agent can only touch one client. Offline? Local stdio instead — it reuses your bot-forge login token automatically, or pass one explicitly: claude mcp add bot-forge -e BOTFORGE_API_KEY=bf_live_... -- npx -y -p bot-forge bot-forge-mcp.

    Step 2 — Give it a starter prompt

    That one URL is everything the agent needs. Just describe the business in plain language and let it drive the tools:

    Using the Bot Forge MCP server, create a chatbot for Acme Plumbing
    (tenant id "acme"). Facts: open Mon-Sat 7-7, emergency repairs and
    water heaters, serving the Phoenix metro. Friendly, reassuring tone.
    Booking: https://calendly.com/acme/visit. Only allow it to embed on
    https://acme.com. Then test it with a few real questions and give me
    the embed snippet.

    The agent calls create_chatbot, test_message, and get_embed_snippet for you and hands back the ready-to-paste <script>.

    Step 3 — Or /prime a client's codebase

    To build a bot from a client's own repo or website, open your agent in that project (with the MCP connected) and run:

    npx bot-forge prime    # prints the /prime prompt — paste it to your agent
                           # (or use the /prime slash command if your agent has one)

    The agent studies the codebase, drafts the facts and branding, detects the production domain for allowedDomains, creates the bot, verifies it with test_message, and returns the embed snippet — asking you only for what it genuinely can't infer. Review its summary and you're live.

    Tools

    whoami, list_models, list_chatbots, get_chatbot, create_chatbot, patch_chatbot, delete_chatbot, add_knowledge, list_knowledge, delete_knowledge, test_message, list_leads, get_embed_snippet.

    # RAG knowledge

    For larger knowledge bases, enable vector retrieval so answers stay grounded in the business's own docs.

    1. Backend prereqs: MongoDB Atlas + OPENAI_API_KEY, and run npm run setup-db once (creates the vector index).
    2. Set ragEnabled: true on the tenant.
    3. Ingest text — dashboard (Tenants → pick one → paste), CLI (npx bot-forge knowledge acme faq.txt), or MCP (add_knowledge).

    Without RAG, the chatbot still answers from the knowledge.facts field — plenty for most small businesses.

    # Providers & models

    Each tenant picks a provider and optional model:

    ProviderDefault modelGood for
    anthropicclaude-haiku-4-5Default — fast, cheap, great quality
    openaigpt-4o-miniOpenAI ecosystem
    googlegemini-2.0-flashGemini ecosystem

    Set a stronger model (e.g. claude-sonnet-4-6) for complex knowledge bases. The matching API key must be set on the server.

    # Tips & tricks

    • Scope keys per client — give an agent or project a tenant-scoped key so it can only touch that one chatbot.
    • Shell mattersexport VAR=… is bash; on Windows use $env:VAR="…".
    • Booking — add Calendly / Google Meet / Zoom links; the bot shows buttons when a visitor wants to book.
    • Lead alerts — set a tenant ownerEmail (Resend), slackWebhook, or leadWebhook (POSTs each lead to your CRM) to get notified instantly.
    • Auto-themeautoTheme: true makes the widget match the host site's accent.
    • Rate limits — tune RATE_LIMIT_PER_SESSION / _PER_IP / _WINDOW_SEC.
    • Restrict embedding — always set a tenant's allowedDomains to the client's origins. Empty = locked to same-origin; ["*"] = any site (demos only). See Chat protocol & security.

    # Troubleshooting

    CLI: “Not logged in”
    Run npx bot-forge login and approve the device in the browser — the token is saved to ~/.bot-forge for every future session. (An env var BOTFORGE_API_KEY or a .env file still work and take precedence; for CI use bot-forge login <token>.)
    Sign-in fails / Google error
    Google sign-in needs the redirect URI https://bot.ops4ge.com/api/auth/callback/googleregistered on the OAuth client. If login 500s, confirm AUTH_SECRET is set on the server. Email + password works without any Google config.
    Dashboard 500 / “Can’t reach MongoDB”
    Atlas is blocking the server. Add 0.0.0.0/0 under Atlas → Network Access (Vercel uses dynamic IPs), confirm MONGODB_URIis set, and redeploy.
    MCP won’t connect
    Use --transport http and an Authorization: Bearer bf_live_… header pointing at https://bot.ops4ge.com/api/mcp. Make sure the key isn't revoked. claude mcp list shows status.
    RAG returns nothing
    Confirm ragEnabled: true, OPENAI_API_KEY is set, npm run setup-db built the vector index, and you've ingested text for that tenant.
    Widget doesn’t appear
    Check the data-tenant matches a real tenant, the snippet is before </body>, and the browser console for errors.

    # Reference

    Endpoints

    • POST /api/chat — streaming chat (used by the widget)
    • GET /api/config?tenant=… — public branding config
    • GET|POST /api/v1/tenants · GET|PATCH|DELETE /api/v1/tenants/:id
    • POST|GET|DELETE /api/v1/knowledge · GET /api/v1/leads
    • POST /api/v1/test · GET /api/v1/models · GET /api/v1/whoami (returns user/org/role)
    • POST /api/mcp — hosted MCP (Bearer auth)
    • /api/auth/* — sign-in (Auth.js) · POST /api/oauth/device/start|token — CLI device login
    • POST /api/voice/session — mint a signed voice session · POST /api/voice/webhook — ElevenLabs post-call hook
    • /embed.v1.js — the version-pinned widget loader

    Key env vars (server)

    • ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_GENERATIVE_AI_API_KEY
    • MONGODB_URI · AUTH_SECRET · AUTH_GOOGLE_ID + AUTH_GOOGLE_SECRET (Google sign-in) · ADMIN_API_KEY (legacy superadmin)
    • RESEND_API_KEY + LEAD_EMAIL_FROM · SLACK_WEBHOOK_URL
    • ELEVENLABS_API_KEY (+ ELEVENLABS_DEFAULT_VOICE_ID, ELEVENLABS_WEBHOOK_SECRET) — voice bot

    Full details in the repo README.