Buzzkeeper is a Rust Discord bot for Hive communities. It acts like a tavern character inside a server: people can talk to it, tip it, buy it drinks with HIVE, HBD, or Hive Engine tokens, push it into different mood states, and turn a Discord channel into a noisy on-chain pub.
Repository: github.com/Vheissu/buzzkeeper
- Runs as a Discord bot using
poiseandserenity - Stores persistent guild state in a local JSON file
- Tracks tavern mood, intoxication, hangovers, party meter, regulars, and memories
- Supports local and hosted LLM backends
- Defaults to Ollama with
qwen3:4b - Watches a Hive account for incoming HIVE, HBD, and Hive Engine transfers
- Turns recognized payments into drinks, actions, or explicit tips
- Supports public tavern mode so the bot can act like a participating server member
- Supports admin roles, channel policy, quiet hours, cooldowns, and payment announcement channels
Buzzkeeper is currently a single-process bot with a single JSON state file.
That means:
- run one bot instance per deployed environment
- mount persistent storage for
STORAGE_PATH - do not horizontally scale multiple replicas against the same JSON file
If you want multi-instance scaling later, the storage layer should move from JSON to a real shared database.
- Rust 1.85+ with Cargo
- A Discord bot application and token
- A Hive account to receive transfers
- An LLM backend
Recommended local stack:
- Ollama
qwen3:4b
- Clone the repo:
git clone https://github.com/Vheissu/buzzkeeper.git
cd buzzkeeper- Copy the example environment file:
cp .env.example .env-
Fill in
DISCORD_TOKEN -
Install the default local model:
ollama pull qwen3:4b- Run the test suite:
cargo test- Start the bot:
cargo runGo to the Discord Developer Portal, create a new application, then create a bot user for it.
In the Bot tab:
- create the bot if you have not already
- copy the token
- put it in
.envasDISCORD_TOKEN
Buzzkeeper uses:
- standard non-privileged intents
Message Content Intent
Message Content Intent is required if you want:
- public tavern mode
- non-mention chatter detection
- reply-chain continuation without explicit mention every time
In the Discord Developer Portal:
- open your application
- go to
Bot - enable
Message Content Intent - save
In OAuth2 -> URL Generator:
- select scopes:
botapplications.commands
- select permissions:
View ChannelsSend MessagesRead Message HistoryUse Slash Commands
Optional but useful:
Embed LinksAttach Files
Not recommended unless you truly need them:
Mention EveryoneAdministrator
Buzzkeeper currently registers commands globally on startup. New or changed slash commands can take a little while to show up in Discord.
If you restart the bot after pulling updates, give Discord a minute or two to reflect the latest command set.
Buzzkeeper does not sign on-chain transactions in the current version.
It only:
- watches inbound transfers to a Hive account
- parses matching transfers
- reacts inside Discord
So today you do not paste a Hive private key into .env or into Discord.
You need a dedicated Hive account that can receive:
- HIVE
- HBD
- Hive Engine tokens
Recommended approach:
- create a dedicated account just for Buzzkeeper
- do not reuse your personal account if you are testing apps and transfers constantly
- manage that account's keys in Hive Keychain or your normal Hive wallet flow
- keep the active key secure and offline from the bot until you build outbound transfer support
Use a dedicated Hive account and store its keys in a wallet or key manager you trust. The bot only needs the account name today.
Example:
- account name:
buzzkeeper.bot - configure Buzzkeeper to watch that account
- send users' tavern payments to that account
Buzzkeeper now ignores unknown memos and unrelated transfer noise.
It will react only to:
- recognized memos like
drink:first-round - recognized memos like
action:karaoke - explicit
tip/donation/house - exact price matches when there is no memo
Random app memos and unrelated tiny transfers are ignored.
Buzzkeeper defaults to:
- provider:
ollama - model:
qwen3:4b
That makes local development cheap and predictable.
Install and run:
ollama pull qwen3:4bBuzzkeeper talks to:
http://127.0.0.1:11434
by default.
- Ollama
- OpenAI
- Anthropic
- Google Gemini
- Offline fallback
See .env.example.
Common examples:
DEFAULT_LLM_PROVIDER=ollama
DEFAULT_LLM_MODEL=qwen3:4b
OLLAMA_BASE_URL=http://127.0.0.1:11434
OLLAMA_MODEL=qwen3:4bDEFAULT_LLM_PROVIDER=openai
DEFAULT_LLM_MODEL=gpt-4.1-mini
OPENAI_API_KEY=...
OPENAI_MODEL=gpt-4.1-miniDEFAULT_LLM_PROVIDER=anthropic
DEFAULT_LLM_MODEL=claude-3-5-sonnet-latest
ANTHROPIC_API_KEY=...
ANTHROPIC_MODEL=claude-3-5-sonnet-latestDEFAULT_LLM_PROVIDER=google
DEFAULT_LLM_MODEL=gemini-2.5-flash
GOOGLE_API_KEY=...
GOOGLE_MODEL=gemini-2.5-flashMinimum .env for local Discord + local Ollama:
DISCORD_TOKEN=your_discord_bot_token
DEFAULT_LLM_PROVIDER=ollama
DEFAULT_LLM_MODEL=qwen3:4b
OLLAMA_BASE_URL=http://127.0.0.1:11434
OLLAMA_MODEL=qwen3:4b
STORAGE_PATH=data/tavern-state.jsonFormat:
cargo fmtRun tests:
cargo testBuild check:
cargo checkRun bot:
cargo runIf you want to verify the model path before running the bot:
curl -s http://127.0.0.1:11434/api/chat \
-H 'Content-Type: application/json' \
-d '{
"model":"qwen3:4b",
"messages":[
{"role":"system","content":"You are a tavern bot. Return only valid JSON with a reply field."},
{"role":"user","content":"Say hello from the tavern in one sentence."}
],
"stream":false,
"think":false,
"format":{
"type":"object",
"properties":{"reply":{"type":"string"}},
"required":["reply"]
}
}'Use a private test server first.
Recommended test flow:
/setup/status/catalog/set_reply_behavior/set_public_tavern@Buzzkeeper hello- reply directly to the bot
- test
/chat - test a transfer and
/sync_payments
Buzzkeeper watches one Hive account per guild.
Users trigger tavern behavior by sending the configured asset to that account.
The configured house asset can be:
- HIVE
- HBD
- a Hive Engine token symbol plus issuer
You set that asset with /setup.
For HIVE:
/setup bot_name:Buzzkeeper theme:tavern llm_provider:ollama llm_model:qwen3:4b asset_ledger:hive asset_symbol:HIVE payment_account:buzzkeeper.bot
For a Hive Engine token:
/setup bot_name:Buzzkeeper theme:tavern llm_provider:ollama llm_model:qwen3:4b asset_ledger:hive-engine asset_symbol:LEO asset_issuer:leo.tokens payment_account:buzzkeeper.bot
asset_issuer is required for Hive Engine assets. Buzzkeeper resolves the token issuer from the Hive Engine token registry and rejects transfers that do not match the configured issuer.
Then set the Discord channel where payment reactions should be posted:
/set_payment_channel channel:#buzzkeeper-bar
Or do it in one shot:
/set_payment_account account:buzzkeeper.bot payment_channel:#buzzkeeper-bar
Supported memo formats:
drink:<slug>action:<slug>action:<slug> <target>tipdonationhouse
Examples:
drink:first-rounddrink:goblin-grogaction:karaokeaction:roast @beggarstip
If a payment has no memo:
- Buzzkeeper checks whether the amount exactly matches a drink price
- then checks whether it exactly matches an action price
- otherwise it ignores the transfer
If a payment has an unknown memo:
- Buzzkeeper ignores it
- no Discord message is posted
This is intentional so shared app/testing accounts do not spam your server.
Buzzkeeper polls for:
- native Hive transfers
- Hive Engine transfers
You can force an immediate refresh with:
/sync_payments
Be aware of current behavior:
- Buzzkeeper only ingests incoming transfers
- it does not broadcast outbound on-chain operations
- it does not use your Hive private keys today
- Hive Engine assets require
asset_issuer, and Buzzkeeper enforces issuer matching against the Hive Engine token registry before accepting a transfer
Buzzkeeper has two conversation modes:
People use:
@Buzzkeeper .../chat ...
Buzzkeeper can also behave like a public participating member in allowed channels.
When enabled, it can:
- react to normal channel chatter
- continue conversations when users reply to one of its messages
- use shared channel context instead of treating every message as a standalone request
Enable it:
/set_public_tavern enabled:true ambient_reply_chance_pct:25 ambient_cooldown_secs:8
Recommended companion settings:
/set_reply_behavior mention_enabled:true mention_cooldown_secs:2 chat_cooldown_secs:1
Direct mentions bypass cooldown when mention replies are enabled. `mention_cooldown_secs` is retained for compatibility, but direct @mentions should always get a reply unless another policy blocks it.
Public tavern mode is guild-wide, but actual usable channels are controlled by the allowed-channel policy.
To keep Buzzkeeper only in one channel:
/clear_channels
/allow_channel channel:#buzzkeeper-bar
If the allowed-channel list is empty, Buzzkeeper treats that as all channels allowed.
Admin commands require one of:
- Discord
Manage Server - a configured admin role in Buzzkeeper
Grant a bot admin role:
/add_admin_role role:@Mods
Restrict command channels:
/allow_channel channel:#buzzkeeper-bar
/disallow_channel channel:#off-topic
/clear_channels
Set quiet hours:
/set_quiet_hours enabled:true start_hour_utc:22 end_hour_utc:8
/setup- configures bot name, theme, provider, model, house asset, and optional payment account
/status- shows stage, persona, party meter, asset, latest event, and public tavern state
/catalog- lists drinks and actions for the current guild
/policy- shows admin, payment, cooldown, public tavern, and channel policy
/set_payment_account- sets the watched Hive account and optional payment announcement channel
/set_payment_channel- sets the Discord channel for payment reactions
/sync_payments- forces an immediate poll of Hive and Hive Engine transfers
/set_reply_behavior- controls whether direct mentions are enabled and the
/chatcooldown
- controls whether direct mentions are enabled and the
/set_public_tavern- enables or disables public tavern mode, ambient chance, and ambient cooldown
/set_system_prompt- appends additional guild-specific persona instructions
/clear_system_prompt- removes custom guild prompt additions
/chat- direct slash-command conversation with the bot
/remember- saves a lore note or recurring joke into persistent memory
Buzzkeeper now treats memory as a small retrieval problem instead of dumping the latest notes into every prompt.
- stored memories are persisted in JSON and kept in a larger pool
- each reply recalls only the most relevant memories for the current message, speaker, and recent channel context
- memories are grouped into broad categories like preferences, lore, incidents, and self-reflection
- memories can carry bot-state context, so the bot can recall what it said or did while tipsy, buzzing, cooked, gone, or hungover
- when model access is available, memories are automatically enriched with summaries, tags, entities, and importance scores for stronger retrieval
- each incoming message can be analysed into retrieval topics, entities, categories, and requested bot states before recall runs
- recalled memories update lightweight usage metadata so useful notes stay easier to surface over time
- older state files remain compatible, missing memory metadata defaults safely on load
/allow_channel- add an allowed channel
/disallow_channel- remove an allowed channel
/clear_channels- clear the channel restriction list
/add_admin_role- add a role that can administer the bot
/remove_admin_role- remove a role from the bot admin list
/set_quiet_hours- define UTC quiet hours
/drink- admin-only complimentary test pour in Discord
/action- admin-only complimentary test action in Discord
/set_stage- admin-only direct stage override for testing
soberthroughhungover
- admin-only direct stage override for testing
/clear_context- admin-only short-term conversation reset for the current channel, leaves long-term memories alone
/sync_commands- admin-only guild command resync if a slash command is missing or stale
Buzzkeeper now uses two persistent stores:
- a JSON file for guild state and bot configuration
- a SQLite database for long-term memory indexing, FTS, and vector search
Default:
data/tavern-state.json
Default memory index path:
data/tavern-state.memories.sqlite3
Override it with:
STORAGE_PATH=/absolute/path/to/tavern-state.json
MEMORY_DB_PATH=/absolute/path/to/tavern-state.memories.sqlite3Recommended production path:
STORAGE_PATH=/data/tavern-state.json
MEMORY_DB_PATH=/data/tavern-state.memories.sqlite3Optional memory retrieval controls:
MEMORY_MODEL_ASSISTED=true
MEMORY_ANALYSIS_MAX_TOKENS=220
MEMORY_EMBEDDING_MODEL=nomic-embed-text
MEMORY_EMBEDDING_DIMENSIONS=128Notes:
- the SQLite mirror syncs incrementally, so unchanged memories are not re-indexed on every reply
- if
MEMORY_EMBEDDING_MODELis set, Buzzkeeper will try provider-backed embeddings for the SQLite vector index - if embedding generation fails or is not configured, Buzzkeeper falls back to deterministic local embeddings so memory recall still works offline
Deployment guidance lives in docs/DEPLOYMENT.md.
Short version:
- deploy one instance only
- mount persistent storage
- set
STORAGE_PATHandMEMORY_DB_PATHto that mounted path - keep outbound internet access enabled
- enable
Message Content Intentin Discord
This repo now includes:
Enable Message Content Intent in the Discord Developer Portal and restart the bot.
Buzzkeeper registers commands globally on startup and also syncs them into joined guilds for faster visibility. If one command still looks stale, run /sync_commands as an admin in that server or reopen Discord.
Pull the latest version and restart. Backward-compatible defaults now exist for the public tavern fields.
Check:
/policy- allowed channels
- quiet hours
- public tavern mode
- mention cooldown
- ambient cooldown
Check:
- watched Hive account is correct
- house asset is configured correctly
- memo matches expected format
- payment channel is set
/sync_payments
- custom admin-defined drinks and actions
- timezone-aware quiet hours
- richer server events and quests
- outbound Hive operations if the project later needs them
If you are open sourcing Buzzkeeper, add the license file and contribution rules you want before publishing broadly. The codebase is ready for that next step, but the repository currently does not include a license file in this workspace.