Python AI bot for Schuberg Philis Slack workspace, automating parts of Leo Simons' work.
Slack AI Assistant - Interactive chat via Slack's Assistant API, powered by LLM through LiteLLM proxy. Maintains thread context, shows thinking status, suggests follow-up prompts.
Blog Automation - Monitors GitHub activity, generates blog posts summarizing significant commits, publishes to WordPress.com. Runs as scheduled CLI command.
lsimons_bot/
├── app/ # Bootstrap (main.py, config.py)
├── bot/ # Bot abstraction with system prompt
├── llm/ # AsyncOpenAI client for LiteLLM proxy
├── slack/ # Slack integration layer
│ ├── assistant/ # AI Assistant API handlers
│ ├── home/ # Home tab handlers
│ └── messages/ # Message event handlers
└── blog/ # Blog automation module
├── github.py # GitHub commit fetching
├── wordpress.py # WordPress.com API client
├── content.py # LLM-based content generation
└── publish.py # Orchestration logic
- mise (installs everything else, including
fnox) - slack cli
- 1Password CLI (
op) signed in
mise install
mise run installNon-secret config and any secrets not yet in 1Password live in .env:
cp .env.example .env
# Edit .env with your Slack/LiteLLM credentials and blog configSecrets stored in 1Password are resolved at runtime by fnox
— see fnox.toml. The mise run run and mise run blog tasks
invoke commands through fnox exec, which reads secret references from
fnox.toml and injects the resolved values as environment variables.
Secrets currently sourced from 1Password (vault AI):
LLM_AUTH_TOKEN- LiteLLM key for the blog LLM clientWORDPRESS_CLIENT_SECRET- WordPress.com OAuth client secretWORDPRESS_APPLICATION_PASSWORD- WordPress.com application passwordGITHUB_WORDPRESS_TOKEN- GitHub personal access token (for blog activity)
Slack Assistant additionally requires (via .env):
SLACK_BOT_TOKEN- Bot OAuth tokenSLACK_APP_TOKEN- App-level token for socket modeLITELLM_API_BASE- LiteLLM proxy URLLITELLM_API_KEY- LiteLLM API keyASSISTANT_MODEL- Model name (e.g.,gpt-4)
Blog Module additionally requires (via .env):
WORDPRESS_USERNAME- WordPress.com usernameWORDPRESS_CLIENT_ID- WordPress.com OAuth client IDWORDPRESS_SITE_ID- Target site IDLLM_BASE_URL,LLM_DEFAULT_MODEL- Blog LLM config
slack help
slack app settings # Opens web settingsThe manifest.json contains initial config; ongoing changes via web settings.
mise run run
# or directly: fnox exec -- slack run# Full publish with 1Password-backed secrets
mise run blog
# Dry run (no publishing) — pass args through fnox exec
fnox exec -- uv run python -m lsimons_bot.blog --dry-run --verboseBlog publishes when: >24 hours since last post AND (>5 commits OR any commit >200 lines changed).
See AGENTS.md for development guidelines.
# Format
uv run ruff format .
# Lint
uv run ruff check .
uv run basedpyright
# Test
uv run pytest
# Test with coverage
uv run pytest --cov=lsimons_bot- 000-shared-patterns.md - Spec template
- 001-spec-based-development.md - How to write specs
- 002-slack-client.md - Slack integration architecture
- 003-blog-module.md - Blog automation design
- 004-bot-llm-layer.md - Bot and LLM abstraction
- 005-application-bootstrap.md - Application startup
MIT. See LICENSE.md.
