This OpenClaw AI Agent blueprint brings ProblemβMarket Observability to life: it scans Hacker News, Google News, and X.com for market signals, analyzes them via LLM, and delivers daily alignment digests to Telegram.
π Read the article: Detecting ProblemβMarket Drift Before Your Metrics Break
What it does
- Signal Radar: Multi-source scanning (Hacker News, Google News, X.com) for friction signals (churn, conversion, complaints).
- OpenClaw Agent: Intelligent classification using LLMs (Claude/GPT) against your product's core messaging.
- Strategic Insights: Automated ProblemβMarket Alignment reports (daily digest, trend comparison, language gaps).
- Telegram Interface: Command-driven access to
/trend,/brief,/problem, and/wording 7d.
Quick Start
- Clone the repo.
- Setup Environment: Copy the
.env.examplefiles in the subfolders and add your API keys. - No Secrets: This repo contains no secrets or pre-configured keys.
- Deploy: Use the provided
docker-composefiles to spin up the Postgres DB and the Agent. See detailed steps below.
Fork & Adapt
This is a demo and blueprint agent. It is functional out of the box but designed to be extended. Feel free to fork, adapt, and improve it for your own specific use case. If you build something cool on top of this or find a better way to detect drift, pull requests and feedback are always welcome.
Architecture
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββ
β signal-radar ββββββΆβ Postgres βββββββ OpenClaw β
β (HN, GNews, X) β β radar β β + Plugin β
βββββββββββββββββββ ββββββββββββββββββββ ββββββββ¬βββββββ
β² β² β
β Cron β SQL β Telegram
β β βΌ
βββββββββ΄ββββββββββββ βββββββββββ΄βββββββββ ββββββββββββββββ
β trigger-radar- β β market-radar β β You (DM) β
β digest.sh β β plugin (tools) β β or Channel β
βββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββ
Stack: Node.js, PostgreSQL (pgvector), Docker, OpenClaw.
Sources: Hacker News, Google News RSS, X.com.
How the bot works
- You send a message to the Telegram bot (e.g. "Latest signals", "Brief 7d", "Start now").
- OpenClaw receives it and routes to the market-radar skill.
- The skill maps your phrase to a tool:
get_signalsβ Fetch signals from the DB (filter by days, keyword, source)get_source_statsβ Counts per sourceget_trendβ Compare two time periodsrun_scannerβ Trigger a new scan (requires elevated permission)
- The plugin runs the tool (SQL or Docker) and returns data.
- The LLM (Claude/GPT) formats the response and sends it back to you.
Example flow: "Start now" β run_scanner β plugin starts signal-radar container β "Scanner started. Results in a few minutes."
Components
| Folder | Role |
|---|---|
| signal-radar/ | Scanner (HN, Google News) β Postgres |
| openclaw/ | AI agent (Telegram), skills, digest webhook |
| postgres/ | Postgres + pgvector, radar DB |
Prerequisites
- Docker & Docker Compose
- Anthropic API key (Claude) β OpenAI key optional for rate-limit fallback
- Telegram Bot Token (@BotFather)
- ~10 min setup
Quick Start
1. Network & Postgres
docker network create radar-net cd postgres && docker-compose up -d
Connect to Postgres and init the DB:
CREATE DATABASE radar; CREATE USER radar_user WITH PASSWORD 'your_secure_password'; GRANT ALL ON DATABASE radar TO radar_user; \c radar CREATE TABLE runs (id SERIAL PRIMARY KEY, source TEXT, created_at TIMESTAMPTZ DEFAULT NOW()); CREATE TABLE signals (id SERIAL PRIMARY KEY, run_id INT REFERENCES runs(id), source TEXT, title TEXT, content TEXT, url TEXT UNIQUE, subreddit TEXT); CREATE TABLE messaging (page_id TEXT PRIMARY KEY, headline TEXT, subheadline TEXT, pain_block TEXT, cta TEXT, version TEXT, updated_at TIMESTAMPTZ DEFAULT NOW()); GRANT ALL ON runs, signals, messaging TO radar_user; GRANT USAGE, SELECT ON SEQUENCE runs_id_seq, signals_id_seq TO radar_user;
2. Signal Radar
cd signal-radar cp .env.example .env # Edit .env: DATABASE_URL=postgresql://radar_user:your_secure_password@pgvector-db:5432/radar docker-compose build docker-compose run --rm signal-radar # Test run
3. OpenClaw
cd openclaw cp .env.example .env # Edit .env β see "Env variables" below mkdir -p config cp ../openclaw.example.json config/openclaw.json # config uses ${VAR} β values come from .env cd plugins/market-radar && npm install && cd ../.. docker-compose up -d
3b. Messaging import (for /wording 7d)
cd openclaw ./scripts/trigger-import-messaging.sh # Import messaging/homepage.md β DB
4. Auth profiles (API keys)
OpenClaw needs API keys in auth-profiles.json. Either run openclaw onboard interactively, or add them via env: ANTHROPIC_API_KEY and OPENAI_API_KEY in .env are picked up if auth profiles reference them.
5. Cron (optional β daily digest)
crontab -e
# Add: 0 8 * * * cd /path/to/openclaw && ./scripts/trigger-radar-digest.shEnv variables
Set these in openclaw/.env (no secrets in the repo):
| Variable | Purpose |
|---|---|
ANTHROPIC_API_KEY |
Claude (primary model) |
OPENAI_API_KEY |
Fallback on rate limit |
DATABASE_URL |
Postgres for plugin (same as signal-radar) |
TELEGRAM_BOT_TOKEN |
From @BotFather |
OPENCLAW_HOOKS_TOKEN |
Digest webhook auth β generate a random string |
OPENCLAW_GATEWAY_TOKEN |
Gateway auth β generate a random string |
TELEGRAM_CHAT_ID |
Where to send digest (group/channel ID) |
TELEGRAM_USER_ID |
Your Telegram user ID (for "Start now") β get via @userinfobot |
X_BEARER_TOKEN |
X (Twitter) API Bearer Token β for X.com signals (optional, set in signal-radar/.env) |
SCANNER_SOURCES |
Limit sources, e.g. hackernews,google-news = no X.com (optional, saves API costs) |
openclaw.example.json uses ${TELEGRAM_BOT_TOKEN}, ${OPENCLAW_HOOKS_TOKEN}, ${OPENCLAW_GATEWAY_TOKEN}, ${TELEGRAM_USER_ID} β all resolved from .env.
Bot commands & phrases
| You say | Tool | Result |
|---|---|---|
| "Latest signals", "What's new" | get_signals | Recent signals from DB |
| "Source stats" | get_source_stats | Counts per source |
| "Trend 7 days" | get_trend | Compare periods |
| "Brief 7d", "Weekly brief" | get_signals + LLM | Thematic brief, narrative recommendation |
| "Hooks", "LinkedIn hooks" | get_signals + LLM | 5 emotional post hooks |
| "Problem X", "Problem churn" | get_signals + LLM | Problem spotlight |
| "Wording 7d", "Language patterns" | get_signals + get_messaging + LLM | Market signals vs. your messaging (Block 4 contrast) |
| "X.com entries", "Twitter signals" | get_signals (source: x) | X.com/Twitter signals (EN only) |
| "Start now", "Scan now" | run_scanner | Trigger new scan |
Note: /wording 7d requires get_messaging β add your landing-page texts in openclaw/messaging/*.md, run import, and ensure get_messaging is in tools.allow.
run_scanner ("Start now")
To let the bot trigger scans via Telegram:
- Docker socket β
docker-composealready mounts/var/run/docker.sockandgroup_add: "docker". If you get "Unable to find group docker", use your socket's GID:group_add: ["1001"](seels -la /var/run/docker.sock). - Config β
openclaw.example.jsonalready hasrun_scannerintools.allowandtools.elevated.allowFrom.telegramβ${TELEGRAM_USER_ID}. SetTELEGRAM_USER_IDin.env. - Image β Ensure signal-radar is built:
cd signal-radar && docker-compose build.
File layout
.
βββ openclaw.example.json # Config template (uses ${VAR} from .env)
βββ openclaw/
β βββ config/ # openclaw.json lives here (not committed)
β βββ messaging/ # Landing-page texts for /wording 7d (homepage.md etc.)
β βββ plugins/market-radar/
β βββ scripts/ # trigger-radar-digest.sh, import-messaging.js, trigger-import-messaging.sh
β βββ workspace/skills/market-radar/
βββ signal-radar/
β βββ sources/ # hackernews, google-news, x (X.com/Twitter)
β βββ keywords/ # EN only: hackernews.json, google-news.json, x.json
βββ postgres/
Never commit: .env, openclaw/config/openclaw.json, openclaw/config/agents/. Use .env.example and openclaw.example.json as templates.
Troubleshooting
| Problem | Fix |
|---|---|
| "DATABASE_URL not set" | Add to openclaw/.env, same as signal-radar |
| "elevated is not available" | Add TELEGRAM_USER_ID to .env, ensure tools.elevated.enabled: true |
| "EACCES /var/run/docker.sock" | Use group_add: ["1001"] (or your docker GID) in docker-compose |
| "Image signal-radar_signal-radar not found" | cd signal-radar && docker-compose build |
| Digest not arriving | Check OPENCLAW_HOOKS_TOKEN matches hooks.token, TELEGRAM_CHAT_ID correct |
License
MIT