Elixir is an LLM-powered Discord bot for the POAP KINGS Clash Royale clan (#J2RGCRVG).
It is not a generic chat bot and not a single-feed narrator. Elixir is a channel-native clan agent with:
- Discord channel lanes like
river-race,clan-events,leader-lounge, andask-elixir - executable agents/workflows for awareness, conversation, clanops, memory synthesis, content, and specialist tasks
- a central recurring activity registry for scheduled work
- scoped memory for public vs leadership context
- GitHub-backed publishing for poapkings.com
AGENTS.md is the repository source of truth for architecture and operating notes. This README is the best high-level introduction to the project.
Useful companion docs:
Elixir currently handles four main kinds of work:
-
Discord conversation Elixir answers questions in the right channel with the right lane behavior.
#ask-elixiris open conversation and screenshot help,#clan-chatis mention-driven, and#leadersis private clan operations. -
Signal-driven clan updates Elixir detects roster, war, and progression signals, then fans one source event into one or more destination-specific outcomes. A new member join can become:
- a public welcome in
#clan-events - a factual leadership note in
#leaders
- a public welcome in
-
Scheduled recurring activities Elixir runs recurring activities like the
v5-reactive-tickproactive heartbeat,war-poll,player-progression,weekly-recap,promotion-content, and the daily#ask-elixirhidden-fact post. -
POAP KINGS website publishing Elixir generates and publishes structured data for poapkings.com, pushes it to GitHub, and reports publish outcomes in
#website-updates.
Elixir uses channel lanes instead of one overloaded public stream. A lane is a Discord destination contract: channel id, audience, allowed topics, reply policy, memory scope, and voice. Lanes are not independent agents; they are the rooms where one Elixir speaks.
Primary public/proactive lanes:
#river-racefor River Race scoreboards, recaps, and meaningful war momentum#player-highlightsfor curated player milestones and non-war battle pushes#clan-eventsfor joins, promotions, anniversaries, and clan recognitions#announcementsfor the weekly recap and important clan-wide Elixir updates#recruitingfor recruiting copy members can reuse#website-updatesfor website publish visibility
Primary interactive lanes:
#ask-elixirfor open conversation with Elixir#clan-chatfor mention-driven general questions#welcomefor onboarding and identity verification#leadersfor leadership and clan operations
The live channel contract lives in prompts/DISCORD.md.
Recurring automated work is defined in runtime/activities.py. This is the canonical schedule registry.
See runtime/activities.py for the exact keys, schedules, and enabled state. The shape today:
v5-reactive-tickThe proactive heartbeat. Runs the Event Core engine (ingest → detections → recommendations/cases → communication intents → confirmed Discord delivery). This replaced the oldclan-awareness/war-awarenessticks.war-pollHourly live war ingest + River Race snapshot pipeline.player-progressionRefreshes player profiles and battle logs, then emits curated member highlights.daily-clan-insightDaily#ask-elixirhidden fact when the data supports a genuinely interesting insight.weekly-recapWeekly public recap in#announcements, plus members-page sync for the website.promotion-contentWeekly recruiting content for#recruitingand the website.- Plus
api-sentinel,card-catalog-sync,award-detection,weekly-discord-invite-relay,memory-synthesis,clan-wars-intel, anddb-maintenance.
python -m venv venv
source venv/bin/activate
pip install -r requirements.txtCreate a .env file with the required secrets:
DISCORD_TOKEN=your_discord_bot_token
CLAUDE_API_KEY=your_anthropic_api_key
CR_API_KEY=your_clash_royale_api_key
ELIXIR_LOG_WEBHOOK_URL=optional_discord_webhook_url_for_elixir_logStart the bot locally:
venv/bin/python elixir.pySee SETUP.md for production setup, launchd, optional site publishing config, and operational guidance.
venv/bin/python -m pytest tests/ -vTests use in-memory SQLite and mocked external services. No API keys are needed for the test suite.
Core entrypoints:
- elixir.py Main bot runtime entrypoint.
- elixir_agent.py Stable public LLM entrypoint for replies, updates, and site generation.
- heartbeat.py API-driven signal detection for clan, war, and progression events.
- cr_api.py Clash Royale API client.
Prompt and behavior stack:
- prompts/SOUL.md Elixir's persistent identity and stance.
- prompts/PURPOSE.md Mission and guardrails.
- prompts/GAME.md Clash Royale mechanics and stable game knowledge.
- prompts/CLAN.md POAP KINGS-specific rules, thresholds, and clan identity.
- prompts/DISCORD.md Declarative channel contract.
- prompts/lanes/ Discord destination-lane behavior prompts.
- prompts/agents/ Executable workflow prompts for awareness, memory synthesis, routing, and tournament commentary.
Runtime architecture:
- runtime/activities.py Canonical recurring activity registry.
- runtime/channel_router.py Discord message routing and reply-policy enforcement.
- event_core/ Event-sourced v5 reactive engine (the proactive path that replaced the v4 signal/awareness loop).
- runtime/jobs/ Scheduled activity executors.
- runtime/admin.py Admin command dispatch and manual activity execution.
Persistence and intelligence:
- db/ SQLite schema and query helpers.
- storage/ Identity, memory, analytics, and message persistence.
- agent/ LLM prompt composition, workflow contracts, tool policy, and chat loop.
Modules:
- modules/poap_kings/ POAP KINGS website integration and GitHub publishing.
Principle: prompts define what Elixir says and why. Code defines when, where, and how.
The current prompt stack is:
SOUL.mdWho Elixir is.PURPOSE.mdWhat Elixir is for.GAME.mdStable Clash Royale knowledge.CLAN.mdPOAP KINGS-specific reality.DISCORD.mdServer and channel contract.lanes/*.mdDestination-lane behavior.agents/*.mdWorkflow/agent instructions that are not tied to one Discord channel.
This split matters. It keeps one consistent Elixir identity across very different channels without collapsing everything into one noisy system prompt.
Elixir uses two memory layers.
Conversational memory:
- user, member, and channel conversation state
- recent channel history
- message summaries and episodes
Durable scoped memory:
publicleadershipsystem_internal
Important rules:
- public lanes only read public durable memory
leader-loungecan read public plus leadership durable memoryreceptionshould stay focused on onboarding context- multi-outcome signals share a source identity, but public and leadership durable memories stay separated so private copy cannot overwrite public memory
Elixir owns the dynamic site data written to poapkings.com:
elixirClan.jsonelixirRoster.jsonelixirHome.jsonelixirMembers.jsonelixirPromote.json
GitHub-backed site publishing lives in modules/poap_kings/site.py.
When a real publish happens, Elixir reports it in #website-updates with:
- success or failure
- commit SHA
- direct GitHub commit URL
- repo and branch
- changed content types when useful
No-change publishes stay quiet.
Elixir's operator commands live in Discord #leaders; routine runtime notices go to #elixir-log when ELIXIR_LOG_WEBHOOK_URL is configured.
Use slash commands under /elixir ....
Examples:
/elixir system status
/elixir activity show activity:v5-reactive-tick
/elixir integration publish integration:poap-kings target:data preview:true
/elixir member set member:Ditika field:join-date value:2026-03-07
/elixir signal show view:recent limit:5
The command model is object-first and grouped around:
systemclanmembermemorysignalactivityintegration
Useful operational docs:
- SETUP.md Installation, launchd, deploy/update flow, and logs.
- AGENTS.md Deeper architecture and repository conventions.
Elixir stores failed or unusable Discord prompt attempts in the local prompt_failures table.
Review the latest failures with:
venv/bin/python scripts/review_agent_feedback.py --limit 20
venv/bin/python scripts/review_agent_feedback.py --workflow clanops --jsonUse --json when you want to hand the failure set to another model for diagnosis.
venv/bin/python scripts/clean.py
venv/bin/python scripts/clean.py --dbDefault cleanup removes caches like __pycache__ and .pytest_cache.
--db also removes local runtime files like elixir.db and elixir.pid.
The project is designed so a new clan can fork it and mostly rewrite:
- prompts/CLAN.md
- prompts/DISCORD.md
- selected files in prompts/lanes/
The shared Elixir identity in SOUL.md, PURPOSE.md, and the game knowledge in GAME.md should remain broadly portable.