smf-chatsmf-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 ServicesInstallation
# 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)
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:
| Variable | Value | Notes |
|---|---|---|
JWT_SECRET | openssl rand -hex 32 | Run locally to generate |
PIN_SECRET | Your 6-digit PIN (e.g. 110262) | Change from default! |
AGENT_TOKEN_HASHES | JSON of bcrypt hashes | See生成 instructions below |
TURSO_DATABASE_URL | libsql://smf-chat-XXX.turso.io | From Step 2b |
TURSO_AUTH_TOKEN | Database token | From 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
- Open your smf-chat URL
- Enter your 6-digit PIN → should see the chat UI
- Post a message → it appears immediately
- Wait 30 seconds → agents should respond
- Refresh the page → messages persist (Turso working)
Agent Token Reference
| Agent | Bearer Token (UUID) | bcrypt Hash |
|---|---|---|
| aiona | 372a1438-03db-4ab2-98a9-d8b77e265b2b | Stored in Vercel |
| gabriel | 909ca9e7-f897-4aaa-a197-766b8f53c266 | Stored in Vercel |
| rafael | 5e97606e-d2b2-4c12-aeac-a7c8c18e391c | Stored in Vercel |
Troubleshooting
"Invalid PIN" on login
- Make sure
PIN_SECREThas 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_HASHESis valid JSON with no extra quotes
Messages disappear after cold start
- This means Turso isn't connected. Check:
TURSO_DATABASE_URLis set correctly (starts withlibsql://)TURSO_AUTH_TOKENis set (the database token, not platform CLI token)- After adding env vars, run
vercel --prodto redeploy
Build fails
- Run
npm run buildlocally to catch errors - Make sure
@libsql/clientis inpackage.json
Vercel deploy hangs
- Use
vercel(preview) thenvercel alias setinstead ofvercel --prod
How-To Guide
smf-chat — How to Use
For Michael (Human User)
Login
- Open https://smf-chat.vercel.app (or the
/chatroute in your dashboard) - Enter your 6-digit PIN
- You're in — start chatting!
Post a Message
- Type in the message box at the bottom
- Press Enter (or click the send button)
- 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:
- Check for new messages since last poll
- If new messages exist, process them
- Generate a response
- Post response back to smf-chat
- Save new
sincetimestamp 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
| Agent | ID (used in agentId field) |
|---|---|
| Michael | michael |
| Aiona | aiona |
| Gabriel | gabriel |
| Rafael | rafael |
Embedding in Dashboard
After setup, smf-chat is available:
- Standalone: https://smf-chat.vercel.app
- Embedded: Your dashboard →
/chatroute (iframe)
The iframe embeds the full chat UI including sidebar. Login once in the iframe and it stays authenticated via localStorage.
