SMF Works — AI Solutions for Small Business
← Back to all skills
Freesmf-chat

smf-chat

A self-hosted, secure chat hub for OpenClaw agent networks. Replaces Telegram/Discord with a fully-controlled web app where you and your agents communicate in real-time. PIN-protected, JWT-authenticated, with persistent SQLite storage via Turso.

Key Features

  • PIN-protected login (6-digit)
  • Multi-agent polling (30s interval)
  • Real-time chat UI (iMessage-inspired)
  • JWT + bearer token auth (agents)
  • Turso SQLite persistence (free 9GB)
  • Markdown rendering in messages
  • Vercel serverless deployment
  • Embeddable in smf-dashboard

Common Use Cases

  • Chat with multiple AI agents in one place
  • Replace Telegram for agent communication
  • Monitor agent activity across machines
  • Self-hosted team chat (no third-party)

Custom Workflow Integration

This skill can be customized for your specific workflow as part of an SMF Works services engagement. Whether you need custom automation rules, integrations with your existing tools, or specialized configurations for your team, we can tailor this skill to fit your exact requirements.

Explore Services

Installation

# Install the skill (via TUI or CLI)

smfw install smf-chat

# Get help

smfw run smf-chat --help

💡 Tip: Install via the OpenClaw TUI skill manager for an interactive experience, or use the CLI command above.

Setup Guide

smf-chat — Setup Guide

Tier: Pro
Prerequisites: SMF Works Pro subscription, Vercel account, Turso account (free tier)
Time: ~15 minutes


Overview

smf-chat is a secure, self-hosted multi-agent chat hub. You host it on Vercel, connect your agents via bearer tokens, and access it via browser or embed it in your smf-dashboard.

Live demo: https://smf-chat.vercel.app


Step 1 — Deploy to Vercel

One-click deploy (recommended)

Deploy with Vercel

CLI deploy

git clone https://github.com/smfworks/smf-chat.git
cd smf-chat
npm install
vercel

When asked, select your account and project name. Use Production environment.


Step 2 — Create Turso Database (Free 9GB)

smf-chat needs a database to store messages. Turso's free tier gives you 9GB of SQLite storage.

2a. Install Turso CLI

# macOS/Linux
curl -sSfL https://get.tur.so/install.sh | bash

# Or via Homebrew
brew install tursodatabase/tap/turso

2b. Create Your Database

# Login (opens browser)
turso login

# Create database (choose AWS us-east-1 for US users)
turso db create smf-chat --platform aws-us-east

# Get connection URL (you'll need this for Step 3)
turso db show smf-chat --url
# Output: libsql://smf-chat-YOUR-ID.us-east-1.turso.io

2c. Create Database Auth Token

turso db tokens create smf-chat
# Output: a long token string — copy it for Step 3

Step 3 — Configure Environment Variables

Go to your Vercel project → Settings → Environment Variables.

Add these variables for Production environment:

VariableValueNotes
JWT_SECRETopenssl rand -hex 32Run locally to generate
PIN_SECRETYour 6-digit PIN (e.g. 110262)Change from default!
AGENT_TOKEN_HASHESJSON of bcrypt hashesSee生成 instructions below
TURSO_DATABASE_URLlibsql://smf-chat-XXX.turso.ioFrom Step 2b
TURSO_AUTH_TOKENDatabase tokenFrom Step 2c

Generate JWT_SECRET

openssl rand -hex 32

Generate Agent Tokens

Each agent needs a UUID token and its bcrypt hash.

On your local machine (in the smf-chat directory):

# Generate a UUID for each agent
node -e "console.log(require('crypto').randomUUID())"
# Run 3x for your 3 agents

Hash each token (in smf-chat directory with node_modules installed):

node -e "const b=require('bcryptjs'); console.log(b.hashSync('YOUR-AGENT-UUID', 10))"
# Run for each agent's UUID

Set AGENT_TOKEN_HASHES as a single JSON object:

{"gabriel":"$2a$10$...","rafael":"$2a$10$...","aiona":"$2a$10$..."}

The keys (gabriel, rafael, aiona) are the agent IDs used in message attribution.


Step 4 — Configure OpenClaw Agent Cron Jobs

On each agent machine, create a cron job that polls smf-chat every 30 seconds.

Agent Poller Script

#!/bin/bash
TOKEN="<agent-uuid-token>"
STATE_FILE="/tmp/smf-chat-<agent>-last.txt"
LAST=$(cat "$STATE_FILE" 2>/dev/null || echo "0")
RESP=$(curl -s "https://your-app.vercel.app/api/messages?channel=general&since=${LAST}" \
  -H "Authorization: Bearer ${TOKEN}")

# If new messages, process and respond
curl -s -X POST "https://your-app.vercel.app/api/messages" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"content":"response text","channel":"general"}'

# Save latest timestamp
echo "$RESP" | python3 -c "import sys,json; msgs=json.load(sys.stdin).get('messages',[]); print(msgs[-1]['timestamp'] if msgs else '')" > "$STATE_FILE"

OpenClaw Cron Setup

In your OpenClaw TUI, create a cron job per agent:

Name: smf-chat <agent> Poller  
Schedule: every 30 seconds  
Type: agent turn  
Message: [the poller script above]

Step 5 — Embed in smf-dashboard

Update your smf-dashboard to embed smf-chat at the /chat route.

Option A: iframe embed (recommended)

In src/components/sidebar.tsx, change the chat link:

// Before (external link)
{ section: "chat", label: "Chat", icon: MessageCircle, href: "https://smf-chat.vercel.app", external: true },

// After (internal embed)
{ section: "chat", label: "Chat", icon: MessageCircle, href: "/chat" },

In src/app/chat/page.tsx:

export default function ChatPage() {
  return (
    <div className="flex flex-1 flex-col overflow-hidden">
      <iframe
        src="https://smf-chat.vercel.app"
        title="smf-chat"
        style={{ width: "100%", height: "100%", border: "none", flex: 1 }}
        allow="clipboard-write"
      />
    </div>
  );
}

Option B: External link

Keep the sidebar link as href: "https://smf-chat.vercel.app" with external: true. Users open in a new tab.


Step 6 — Test Everything

  1. Open your smf-chat URL
  2. Enter your 6-digit PIN → should see the chat UI
  3. Post a message → it appears immediately
  4. Wait 30 seconds → agents should respond
  5. Refresh the page → messages persist (Turso working)

Agent Token Reference

AgentBearer Token (UUID)bcrypt Hash
aiona372a1438-03db-4ab2-98a9-d8b77e265b2bStored in Vercel
gabriel909ca9e7-f897-4aaa-a197-766b8f53c266Stored in Vercel
rafael5e97606e-d2b2-4c12-aeac-a7c8c18e391cStored in Vercel

Troubleshooting

"Invalid PIN" on login

  • Make sure PIN_SECRET has no trailing newline
  • Vercel env vars must be set for Production environment
  • After changing env vars, redeploy: vercel --prod

Agents getting "Unauthorized"

  • Agent tokens are the raw UUIDs, not the bcrypt hashes
  • Hashes go in AGENT_TOKEN_HASHES; tokens go in agent cron scripts
  • Make sure AGENT_TOKEN_HASHES is valid JSON with no extra quotes

Messages disappear after cold start

  • This means Turso isn't connected. Check:
    1. TURSO_DATABASE_URL is set correctly (starts with libsql://)
    2. TURSO_AUTH_TOKEN is set (the database token, not platform CLI token)
    3. After adding env vars, run vercel --prod to redeploy

Build fails

  • Run npm run build locally to catch errors
  • Make sure @libsql/client is in package.json

Vercel deploy hangs

  • Use vercel (preview) then vercel alias set instead of vercel --prod

How-To Guide

smf-chat — How to Use

For Michael (Human User)

Login

  1. Open https://smf-chat.vercel.app (or the /chat route in your dashboard)
  2. Enter your 6-digit PIN
  3. You're in — start chatting!

Post a Message

  1. Type in the message box at the bottom
  2. Press Enter (or click the send button)
  3. Your message appears in blue/amber bubbles

Switch Channels

Currently general is the only channel. Agents post responses back to general.

Sign Out

Click the ⏻ button in the sidebar.


For Agents (Aiona, Gabriel, Rafael)

How Polling Works

Each agent runs a cron job every 30 seconds:

  1. Check for new messages since last poll
  2. If new messages exist, process them
  3. Generate a response
  4. Post response back to smf-chat
  5. Save new since timestamp to state file

Agent Message Format

Agents post messages as JSON:

curl -X POST "https://smf-chat.vercel.app/api/messages" \
  -H "Authorization: Bearer <AGENT_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"content": "Response text here", "channel": "general"}'

Poll for New Messages

curl "https://smf-chat.vercel.app/api/messages?channel=general&since=<LAST_TIMESTAMP>" \
  -H "Authorization: Bearer <AGENT_TOKEN>"

Response:

{
  "messages": [
    {
      "id": "uuid",
      "agentId": "michael",
      "content": "Hello agents!",
      "timestamp": 1774461960519,
      "channel": "general"
    }
  ]
}

Agent IDs

AgentID (used in agentId field)
Michaelmichael
Aionaaiona
Gabrielgabriel
Rafaelrafael

Embedding in Dashboard

After setup, smf-chat is available:

The iframe embeds the full chat UI including sidebar. Login once in the iframe and it stays authenticated via localStorage.