Skip to content

Repository files navigation

OpenLabs Discussion Scout

A local-first desktop research agent that discovers high-value scientific discussions (Reddit-first, plus manual X/Twitter and public web links), scores them, turns selected ones into OpenLabs discussion drafts, lets you review/edit/approve, and posts / replies only after your explicit approval — defaulting to dry-run.

It runs as a native Tauri v2 desktop app. You launch a real app window; the React UI runs inside the Tauri shell and talks to a local Python backend. You never need to open a browser.

Scope, enforced in code: discussions & comments only. The app cannot create OpenLabs projects, vote, create bounties, or trigger funding/staking/stage actions, and it never posts to Reddit/X or sends DMs. See Guardrails.


Architecture

Layer Tech
Desktop shell Tauri v2 (Rust) — native window, notifications, macOS osascript fallback
Renderer React + TypeScript + Vite + Tailwind v4
Backend Python 3.11 + FastAPI, 127.0.0.1:8787
Database SQLite via SQLModel (with a storage abstraction for future Supabase)
Local model Ollama — prefilter, classification, dedup, light scoring, summarization
Cloud model Claude API — final scoring, synthesis, draft generation/revision, replies
Scheduling APScheduler — interval discovery runs (default 6h, discovery-only)

The renderer polls the backend over local HTTP (no websockets). The Tauri window health-gates on the backend /health endpoint and shows a native setup screen with logs/guidance if it can't connect.

Why Tauri v2 instead of Electron

Tauri ships a much smaller binary and uses the OS's native WebView instead of bundling Chromium, so memory/disk footprint is far lower — important for the MacBook Air M1 / 16GB target. The native layer is Rust (fast, safe), and Tauri v2's capability-scoped plugin permissions fit this app's "only do a few specific things" security posture.


Prerequisites

  • Rust + Cargo (for the Tauri shell): https://www.rust-lang.org/tools/install
  • Node 18+
  • Python 3.11+ (macOS system Python is 3.9 — install 3.11, e.g. brew install python@3.11)
  • Ollama (optional but recommended): https://ollama.com
  • macOS Xcode command-line tools for the Tauri build: xcode-select --install

Setup

# 1. Clone / open the project, then copy env
cp .env.example .env      # fill in whatever you have; everything is optional for dry-run/demo

# 2. Backend deps (uses Python 3.11)
python3.11 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

# 3. Frontend + Tauri deps
npm install                 # root: Tauri CLI
npm --prefix frontend install

Ollama setup (optional)

ollama pull qwen2.5:14b     # default local model (configurable in Settings)
ollama pull gemma3:4b       # a small fallback works too
ollama serve                # or just run the Ollama app

The app checks http://localhost:11434/api/tags at startup. If Ollama is down it degrades to Claude (if configured) or a deterministic mock scorer.

Claude API setup (optional)

Put your key in .env:

ANTHROPIC_API_KEY=sk-ant-...
ANTHROPIC_MODEL=claude-sonnet-5

Used for final scoring, drafting, revision, and reply drafting. Without it, Ollama or the mock scorer is used and drafts are generated locally.

Reddit credentials (optional, read-only)

Create a script app at https://www.reddit.com/prefs/apps and set (in .env or Settings):

REDDIT_CLIENT_ID=...
REDDIT_CLIENT_SECRET=...
REDDIT_USER_AGENT=ol-research-agent/0.1 by your_reddit_username

No Reddit username/password is required (application-only, read-only). Graceful degradation: with credentials → full PRAW search; without credentials → a credential-less public JSON path (www.reddit.com/…/search.json, limited/rate-capped); if even that is unreachable (e.g. Reddit blocks some datacenter IPs) → deterministic mock candidates. The status bar shows full, limited, or mock.

OpenLabs token (optional)

OPENLABS_AGENT_TOKEN=...
OPENLABS_DRY_RUN=true

This MVP is dry-run only — see below. The token is never shown in the UI.


Credentials management

Configure all providers in-app at Settings → Credentials (Anthropic, OpenAI, Reddit, X, Supabase) — or via .env. In-app secrets are stored in a git-ignored data/credentials.json (chmod 600), layered over .env at runtime; the raw values are never returned to the UI (only masked status + last-4). Each provider has a Test button that live-validates the key. A generation provider switch (anthropic | openai) selects which cloud model does scoring/drafting/replies; it falls back to the other cloud provider, then local Ollama, then a deterministic mock.

OpenLabs agent onboarding & dry-run vs live mode

Settings → OpenLabs agent runs the full onboarding flow (id.bio.xyz create → onboard → authenticate → verify), or you can paste an existing bearer. See https://openlabs.bio.xyz/signup?mode=agent.

  • Dry-run (default): OpenLabs create/reply are simulated — no network write; a local dry_run row is stored and a simulated permalink returned.
  • Live mode: set OPENLABS_DRY_RUN=false (Settings toggle) and have a valid agent session. Live posting is implemented (LIVE_POSTING_IMPLEMENTED = True) and refreshes the bearer on 401. Even in live mode, nothing posts without your explicit per-item approval.

The confirmed OpenLabs API mapping (from the public OpenAPI) is in backend/app/connectors/openlabs_api.py: POST /posts (discussion), GET /posts/{id}/comments, POST /posts/{id}/comments (reply). Only these three operations exist in the client — no project/vote/bounty/funding methods.


Running the app

One command (recommended)

npm run dev        # starts backend + Tauri (Tauri also starts Vite)

Or in separate terminals

# terminal 1 — backend
npm run dev:backend            # = uvicorn on 127.0.0.1:8787 (creates venv on first run)

# terminal 2 — desktop app
npm run dev:tauri              # compiles Rust (slow first time), then opens the window

The first tauri dev compiles the Rust dependencies and can take several minutes on an M1. After that it's fast. The window shows a setup screen until the backend /health responds, then loads the full UI automatically.

Root scripts

Script Does
npm run dev backend + Tauri together
npm run dev:backend FastAPI via scripts/run-backend.sh
npm run dev:frontend Vite dev server only
npm run dev:tauri Tauri dev (native window)
npm run build build the frontend
npm run package:mac tauri build (macOS bundle)

Using it

  1. DiscoveryRun discovery now. Reddit (or mock) candidates are gathered, pre-scored by Ollama, refined by Claude if available, ranked, and stored. You can also ingest a link manually.
  2. Candidates → expand a card (rank, source, tags, relevance, risks, suggested angle, related OpenLabs links, recommendation, raw excerpt). Actions: reject / save / mark duplicate / collect material / draft.
  3. Collect material shows an approval modal — “This will collect material… No posting will happen.” After approval it builds a research brief (source excerpt + public OpenLabs context).
  4. Draft discussion generates an 8-section OpenLabs draft.
  5. Drafts → edit in the Markdown editor, save versions, view version history, or ask the agent to revise from feedback. Approve & post shows the final approval modal and posts in dry-run.
  6. OpenLabs → see your (dry-run) posts, check comments (simulated), draft replies, and approve & post reply (dry-run) behind an approval modal.
  7. Reports → run/candidate/draft/post/comment stats, which model is in use, and a token-usage bar chart with a day / hour toggle (segmented by provider/model, with a legend).

While any long task runs (discovery, collect, draft, revise), a progress bar appears above the status bar showing the task, the model in use, step x/total, and percent.

Approval gates (all enforced in the UI)

  1. Before collecting material for a candidate.
  2. Before finalizing/posting a discussion.
  3. Before posting a reply to a comment.

Nothing is published without an explicit approval click, and an approvals row is recorded for each.

Scheduling

Settings → run interval (default 6h) + auto-discovery toggle. Scheduled runs do discovery only — they never collect material, draft, or post. On completion a desktop notification fires and candidate cards wait for your review.

Configuring topics / objectives / sources

Settings lets you pick from the key topic list, add free-text objectives, edit subreddits and query terms, set the Ollama/Claude models, toggle dry-run, and manage notifications and storage provider.


Desktop notifications

Uses the Tauri notification plugin. The frontend polls /notifications and raises a native banner for anything new (discovery complete, candidates ready, material/draft ready, post result, new comments, reply needs approval). If the plugin fails, a macOS osascript fallback (native Rust command) is used — no terminal-notifier required. Test it from Settings → Send test notification.


Guardrails

Enforced in code, not just prompts (backend/app/guardrails.py):

  • Blocked (hard stop, raise on attempt): create project · vote · bounty · fund · stake · move project stage · DM · post to X · post to Reddit.
  • OpenLabs client implements only create_discussion, list_comments, reply_to_comment. Project/vote/bounty/funding methods do not exist in the codebase.
  • Dry-run by default; live posting cannot fire in this MVP.
  • No fabrication: prompts forbid inventing citations, links, papers, or OpenLabs entities; related OpenLabs items come only from the public feed or the user. Scoring force-rejects medical-advice, marketing, and political items.
  • No medical advice / clinical recommendations.

Supabase (future)

A storage abstraction exists (backend/app/storage/): LocalSQLiteStore (default) and a SupabaseStore placeholder. Settings expose storage_provider: sqlite | supabase. Supabase is not required and not implemented for the MVP.


Known TODOs / unknowns

  • OpenLabs live posting / agent onboarding — the 3-step id.bio.xyz create→token→authenticate flow plus /auth/agent/onboard + /agent-smoke is not implemented. Dry-run only.
  • Post permalink — the API returns no slug; we construct a best-effort /posts/{id} (unverified).
  • Python sidecar packaging — for a distributable app the backend should be bundled as a Tauri sidecar; MVP documents manual backend start instead.
  • OpenLabs topic_id — left null unless a topic list becomes discoverable.

Smoke tests

See PLAN.md §11 and the checklist below. Backend checks:

curl -s 127.0.0.1:8787/health
curl -s 127.0.0.1:8787/status
curl -s -X POST 127.0.0.1:8787/runs/discovery/start
curl -s 127.0.0.1:8787/candidates
  • backend /health
  • DB init + settings read/write
  • Ollama availability check
  • mock candidate generation without Reddit creds
  • manual link ingestion
  • draft save/edit/versioning + revise
  • dry-run OpenLabs post returns a simulated link
  • comment monitoring + reply (dry-run)
  • desktop notification test
  • Tauri window launches and health-gates on the backend

About

Identify viral claims, fact checks, and captures findings as a post on OpenLabs.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages