Hub/Docs

Slop Bot

How Slop works: the Discord bot that searches the Latent Space wiki-base, remembers members, and schedules community events.

Slop Bot

Slop is Latent Space's Discord bot. It searches the wiki-base, answers questions with source links, remembers who you are, and schedules community events.

Code pathapps/bots/slop/ inside latent-space-hub
Hosted onRailway (always-on process)
LLMClaude Sonnet 4.6 via OpenRouter
DatabaseSame Turso instance as the hub

What Slop Does

  1. Answers questions — Tag @Slop in any allowed channel and it searches the wiki-base to answer with source links
  2. Schedules community events via slash commands:
    • /paper-club — schedule a Paper Club session
    • /builders-club — schedule a Builders Club session
    • /edit-event — edit or cancel a scheduled event
    • /issue — create a GitHub issue in the Hub repo
    • /join — create your member profile (optional)
  3. Sends event reminders — Automated reminders for upcoming Paper Club sessions:
    • 24 hours before the session
    • 1 hour before the session
    • If a paper URL is registered, the reminder includes the link and tells folks to read it

How It Works

The simple version

  1. You send a message mentioning @Slop (or use a slash command)
  2. Slop builds a system prompt with its personality, your member profile, and a list of skills
  3. The LLM gets 9 internal tools it can call to search the wiki-base
  4. The LLM decides what to search, calls tools, reads results, and may search again (up to 5 rounds)
  5. The LLM generates a response with source links
  6. Slop posts the response in a Discord thread
  7. Behind the scenes, the code updates your member profile and logs the interaction

Architecture

Slop connects directly to Turso: it does not use the MCP server. Its runtime lives in apps/bots/slop/.

User @mentions Slop in a channel
    |
    v
Discord sends message to bot (via WebSocket gateway)
    |
    v
Bot checks: allowed channel? rate limit? already processed?
    |
    v
Bot looks up member profile from DB (by Discord ID)
    |
    v
Bot builds system prompt:
  [IDENTITY]  ~400 chars: who Slop is, how to behave
  [RULES]     ~500 chars: search tool routing, citations, no fabrication
  [SKILLS]    ~700 chars: skill index (event scheduling, search patterns, member profiles)
  [MEMBER]    ~400 chars: your profile, interests, interaction preference
    |
    v
Bot sends to OpenRouter (Claude Sonnet 4.6) with:
  - System prompt
  - User message
  - 9 internal tool definitions
    |
    v
LLM decides what to do:
  - Call slop_semantic_search for meaning-based queries?
  - Call slop_search_nodes for known names/terms?
  - Call slop_sqlite_query for date filters or events?
  - Call slop_read_skill for detailed instructions?
  - Or just respond directly (for greetings)?
    |
    v
Bot executes tool calls directly against Turso
Tool results fed back to LLM
(repeats up to 5 rounds)
    |
    v
LLM generates final response with source links
    |
    v
Bot strips any hidden <profile> update block
Bot posts response to Discord thread
Bot logs trace to DB (non-blocking)
Bot updates member profile (non-blocking)

Slash Commands

Five commands registered with Discord. These are typed directly in the message input.

/join

Usage: /join

Creates your member profile in the wiki-base. After joining:

  • Slop remembers your role, company, interests across conversations
  • Your interactions create edges to content you discuss
  • Slop personalizes responses based on your profile

If you've already joined, it refreshes your profile metadata.

/paper-club

Usage: /paper-club

Schedule a Paper Club session (every Wednesday, 12-1pm PT).

  1. Slop shows the next 4 available Wednesdays (skips dates already booked)
  2. You reply with a number and your paper title (optionally with a URL)
  3. Slop creates an event node in the wiki-base and confirms

/builders-club

Usage: /builders-club

Same as /paper-club but for Builders Club sessions (every Saturday 8am Sydney / Friday afternoon PT). You provide a topic instead of a paper.

/edit-event

Usage: /edit-event

Edits one of your scheduled events. You can:

  • Change title/topic
  • Update or remove Paper Club URL
  • Reschedule to another available slot
  • Cancel the event

/issue

Usage: /issue title:"..." body:"..." [labels:"bug,discord"]

Creates a GitHub issue in the Hub repo. It does not write PRDs or modify backlog files.


@Mentions and Threads

Mention @Slop in any allowed channel to start a conversation. Slop creates a thread named Slop: [first 40 chars of your message] and responds there.

In a Slop-owned thread, you don't need to keep mentioning @Slop. All messages in the thread are treated as directed to Slop. Rate limits are relaxed for natural back-and-forth.

You can also reply to any Slop message to continue a conversation without creating a new thread.


Tools

Slop has 9 internal tools that query Turso directly. These are defined in apps/bots/slop/src/tools.ts, not via MCP.

Search tools (each uses a different index type):

ToolHow it searchesBest for
slop_semantic_searchVector embeddings (meaning)Natural language questions, conceptual queries
slop_search_nodesSQL LIKE (substring match)Known names, exact terms, node_type filtering
slop_search_contentFTS5 (keyword index)Exact words/phrases in transcripts and articles

Graph traversal and utility tools:

ToolPurpose
slop_get_nodesLoad full node records by ID
slop_query_edgesFind connections from a node
slop_list_dimensionsList all categories with counts
slop_get_contextWiki-base stats (nodes, edges, chunks)
slop_sqlite_queryRead-only SQL for date filters, aggregations, event queries
slop_read_skillRead full skill instructions (from local bot files)

The system prompt tells the LLM which search tool to use based on the query type. Temporal queries ("latest", "upcoming") route to sqlite_query. Event queries explicitly use node_type='event' with metadata filters to avoid confusing scheduled sessions with past recordings.

The LLM can call multiple tools across up to 5 rounds before generating its response.

All tools are read-only. The LLM cannot write to the database. All writes (member updates, event creation, edge creation) happen in the bot's own code, outside the LLM loop.


Skills

Skills are instruction sets that Slop loads on demand. The system prompt includes a brief index of available skills. When the LLM needs detailed instructions (e.g. how to query events), it calls slop_read_skill to load the full skill body.

Available Skills

SkillWhat it coversWhen Slop reads it
Start HereSlop runtime orientation and routing to specialist skillsFirst reference for most Slop interactions
DB OperationsSchema, search patterns, citation formatWhen Slop needs operational DB guardrails
Member ProfilesHow to build profiles over time, the <profile> block format, interaction preferencesWhen users share personal info or ask about their profile
Event SchedulingHow events work, SQL queries for upcoming/past events, directing users to slash commandsQuestions about Paper Club or Builders Club

Skills live in apps/bots/slop/skills/ as markdown files with YAML frontmatter. The frontmatter (name, description, when to use) appears in the system prompt. The body is fetched on demand from local files: this keeps the system prompt small.


Member System

Joining

Use /join to create your member node. This stores:

  • Discord ID, username, avatar
  • Join date and last active timestamp

Profile Building

As you chat with Slop, it builds your profile over time:

  • Role, company, location: captured when you mention them
  • Interests: accumulated from conversations (up to 25 topics)
  • Interaction preference: how you like to communicate (observed or explicitly stated)
  • Interaction history: last 3 conversation summaries

Slop extracts profile updates by appending a hidden <profile> block to its responses. The block is stripped before the message reaches Discord: you never see it.

Interaction Preference

Slop adapts its style to each member. If you prefer short technical answers, say so. If you like being challenged, Slop will remember. The preference develops two ways:

  1. Explicitly: Tell Slop: "keep it short", "be more technical", "challenge my assumptions"
  2. Implicitly: Slop observes your communication patterns and updates over time

The preference is stored in your member metadata and injected into the system prompt every interaction.

Member Edges

After each interaction, Slop creates edges linking your member node to any content nodes discussed. Over time this builds a map of what you've engaged with.


Event Reminders

Slop posts automated reminders for upcoming Paper Club sessions. Reminders are scheduled via node-cron and run on the bot process (not a separate service).

Reminder Windows

ReminderFires atLooks forMessage
24-hour12:00 PM PT dailyTomorrow's Paper Club events"Paper Club tomorrow (12pm PT)" with presenter mention + paper link
1-hour11:00 AM PT dailySame-day Paper Club events"Paper Club in 1 hour" with presenter mention + paper link

Both reminders post to the channel configured by PAPER_CLUB_CHANNEL_ID.

How It Works

  1. Cron fires at the scheduled time (timezone: America/Los_Angeles)
  2. Queries Turso for node_type='event' where metadata.event_type='paper-club', metadata.event_status='scheduled', and the relevant reminded_*_at field is NULL
  3. Atomically claims the row in the DB to prevent duplicate posts (safe across restarts and multiple instances)
  4. Posts the reminder to Discord
  5. On success: writes reminded_*_at and reminded_*_message_id to the event's metadata
  6. On failure: releases the claim so it can retry next cycle

Idempotency

Reminders use DB-backed durable state, not in-memory tracking. Each reminder window writes separate metadata fields:

  • 24h: reminded_24h_claimed_at, reminded_24h_at, reminded_24h_message_id
  • 1h: reminded_1h_claimed_at, reminded_1h_at, reminded_1h_message_id

This means reminders survive bot restarts and won't duplicate if multiple bot instances are running.

Configuration

Env varDefaultPurpose
PAPER_CLUB_CHANNEL_IDChannel to post reminders (required)
REMINDERS_ENABLEDtrueMaster toggle for all reminders
REMINDERS_ONE_HOUR_ENABLEDtrueToggle for the 1-hour reminder
REMINDERS_TIMEZONEAmerica/Los_AngelesTimezone for cron scheduling
BOT_INSTANCE_IDhostname/pidIdentifies which instance claimed a reminder

Limitations

  • event_date is date-only (YYYY-MM-DD), not datetime. Reminder timing is hardcoded to Paper Club's fixed Wednesday 12pm PT schedule rather than computed from per-event times.
  • If duplicate event rows exist for the same slot (see PRD-45), a reminder posts once per duplicate.

Automated Kickoffs

When the hub ingests new content (via hourly cron), it can trigger Slop to discuss it automatically.

The hub sends a POST to Slop's internal API (/internal/kickoff) with:

  • Content title, type, date, URL
  • Optional summary or custom prompt

Slop then:

  1. Creates a thread in the configured channel
  2. Searches the wiki-base for context on the new content
  3. Generates an opening take with the full agentic tool loop
  4. Posts it for the community to discuss

This is authenticated via a shared secret (DEBATE_KICKOFF_SECRET).


Response Format

Every Slop response includes:

  • Model badge: Shows which model generated the response (e.g. claude-sonnet-4-6)
  • Response body: The actual response, split into chunks if over 1800 chars (Discord's limit)
  • Tools footer: Shows which tools were called (e.g. search_nodes(x2) | get_nodes)

Trace Logging

Every interaction is logged to the chats table in Turso:

FieldWhat's stored
User messageThe original prompt
Assistant responseSlop's response (first 8000 chars)
Tool callsFull trace: tool name, arguments, result summary, duration per call
MetadataDiscord user ID, channel, model, latency, retrieval method, member ID

View traces at /evals on the web app.

Slop System Message (Live from apps/bots/slop)

This section is generated at runtime from:

  • apps/bots/slop/src/llm/prompts.ts
  • apps/bots/slop/src/skills/index.ts
  • apps/bots/slop/skills/*.md
[IDENTITY]
You are Slop — the Latent Space Discord bot. Brief, direct, precise. The opposite of slop.
You bridge the Latent Space wiki-base (podcasts, articles, AI news, workshops, community content) into Discord conversations.

[RULES]
Search the knowledge base BEFORE answering factual questions. Don't guess, look it up.
Pick the right search tool:
- semantic_search: natural language questions, conceptual queries ('what has LS covered about chip supply chains')
- search_nodes: known names or exact terms, optionally filtered by node_type ('Dylan Patel', 'SemiAnalysis')
- search_content: exact words/phrases you expect in transcripts ('capex spending', 'inference cost')
- slop_get_upcoming_events: default for upcoming Paper Club/Builders Club schedule questions. Pass event_type when user asks for one type only.
- sqlite_query: temporal queries ('latest', 'newest', 'recent', 'upcoming') for non-event content. For event SQL, always include node_type='event', event_status='scheduled', and event_type when type-specific.
- sqlite_query for events: upcoming events are node_type='event' with json_extract(metadata,'$.event_status')='scheduled'. Do NOT use 'paper-club'/'builders-club' node_type for upcoming sessions — those are recordings.
If user asks 'upcoming paper clubs', do NOT include builders-club rows.
Always link to sources: [Title](url). Never reference content without a link.
Never fabricate names, dates, episodes, quotes, or links. If tools return nothing, say so.
Mark speculation explicitly: 'No hard data, but...' or 'Extrapolating here...'

[SKILLS] Available skills. Use slop_read_skill(name) for full instructions.
- **Start Here**: Slop Discord runtime orientation. Read this first on every interaction.
- **Member Profiles**: How Slop manages Discord member profiles in the Latent Space graph.
- **DB Operations**: Schema, search patterns, citation format, and response framing for Slop's graph queries.
- **Event Scheduling**: Paper Club and Builders Club event schedule, commands, and how to query upcoming events.

[MEMBER CONTEXT]
Name: <member name>
Role: <if known>
Company: <if known>
Location: <if known>
Interests: <comma-separated>
Interaction preference: <if known>
Last active: <timestamp>
Recent interactions: <summary>
Use this to personalize your response. Update interaction_preference in <profile> when you learn how they like to interact.