The Sanctum Chronicler
A Dockerized Python MVP for an AI stream assistant that monitors Twitch chat, gently guides conversation, stores stream events, and exports a post-stream markdown ledger.
Overview
The Sanctum Chronicler is an intelligent assistant designed to enhance live streaming by:
- Monitoring real-time chat and stream activity
- Maintaining a warm, non-intrusive presence during streams
- Flagging suspicious content and spam patterns
- Archiving discussion highlights and clip candidates
- Generating post-stream ledgers and blog ideas
The system uses a multi-mode agent architecture, where different "personas" handle different aspects of stream management:
- Hearthkeeper - Gently prompts chat when it's quiet
- Steward - Responds thoughtfully to engagement
- Warden - Detects suspicious content and spam
- Librarian - Archives important discussion
- Scribe - Compiles post-stream ledgers
Architecture
Project Structure
sanctum-agent/
├── app/
│ ├── main.py # FastAPI application
│ ├── config.py # Configuration (pydantic-settings)
│ ├── twitch/
│ │ ├── eventsub.py # Twitch EventSub client (stub)
│ │ └── chat.py # Chat message handling (stub)
│ ├── agent/
│ │ ├── orchestrator.py # Main agent orchestrator
│ │ ├── policies.py # Behavior policies
│ │ └── modes/
│ │ ├── hearthkeeper.py
│ │ ├── steward.py
│ │ ├── warden.py
│ │ ├── librarian.py
│ │ └── scribe.py
│ ├── memory/
│ │ ├── database.py # Async SQLAlchemy setup
│ │ ├── models.py # Database models
│ │ └── repository.py # Data access layer
│ ├── llm/
│ │ ├── client.py # Pluggable LLM client
│ │ └── prompts.py # Prompt templates
│ └── exports/
│ └── markdown.py # Markdown ledger generation
├── exports/ # Generated ledgers
├── data/ # Local data storage
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── .env.example
└── README.md
Tech Stack
- Python 3.12 - Core language
- FastAPI - REST API framework
- SQLAlchemy + asyncpg - Async database ORM
- PostgreSQL - Primary data store
- Docker & Docker Compose - Containerization
- Pydantic - Configuration and validation
Key Design Patterns
Agent Modes: Each mode operates independently but shares access to:
- The LLM client for text generation
- The database repository for persistence
- Shared policies for behavior control
Policies: Encapsulate decision logic:
ChatActivityPolicy- Tracks inactivity periodsResponseSuppression- Avoids speaking during active chatSuspiciousContentPolicy- Pattern matching for spam/scams
Async Architecture: All I/O operations are non-blocking:
- Database queries use
asyncpg - FastAPI endpoints handle concurrent requests
- LLM calls prepare for real API integration
Setup & Quick Start
Prerequisites
- Docker & Docker Compose
- Python 3.12 (for local development)
- PostgreSQL 16 (or use Docker)
1. Clone Repository
cd ws-sanctum-chronicler
2. Configure Environment
cp .env.example .env
# Edit .env with your settings (Twitch tokens, LLM provider, etc.)
3. Start Services
docker-compose up --build
The API will be available at http://localhost:8000
4. Test the API
Health Check:
curl http://localhost:8000/health
Start Session:
curl -X POST http://localhost:8000/admin/session/start \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "channel_name=example_channel"
Send Test Message:
curl -X POST http://localhost:8000/admin/test-message \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "session_id=<SESSION_ID>&username=test_user&message=Hello stream!"
Get Ledger:
curl http://localhost:8000/admin/ledger?session_id=<SESSION_ID>
End Session:
curl -X POST http://localhost:8000/admin/session/end \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "session_id=<SESSION_ID>"
API Endpoints
Health & Status
GET /health- Application health check
Session Management
POST /admin/session/start?channel_name=<name>- Start stream sessionPOST /admin/session/end?session_id=<id>- End stream session
Testing & Admin
POST /admin/test-message?session_id=<id>&username=<user>&message=<msg>- Send test messageGET /admin/ledger?session_id=<id>- Retrieve markdown ledger
Configuration
All settings are loaded from environment variables (see .env.example):
Application
APP_NAME- Application display nameAPP_ENV- Environment (development/production)DEBUG- Enable debug logging
Database
DATABASE_URL- PostgreSQL connection stringDB_PASSWORD- Database password (for docker-compose)
Twitch (Optional - Stubs Present)
TWITCH_CLIENT_ID- Twitch OAuth client IDTWITCH_CLIENT_SECRET- Twitch OAuth secretTWITCH_BOT_USERNAME- Bot usernameTWITCH_CHANNEL_NAME- Channel to monitor
LLM
LLM_PROVIDER- Provider:openai,ollama,lm_studio, or empty for mockLLM_BASE_URL- API endpoint (for local providers)LLM_API_KEY- API key (if needed)LLM_MODEL- Model identifier (default: gpt-3.5-turbo)
Export
EXPORT_PATH- Directory for ledger exports
Agent Policies
Chat Activity Policy
- Inactivity Threshold: 15 minutes
- Hearthkeeper Activation: Sends gentle prompt when no messages for 15+ minutes
- Human Override: Hearthkeeper stays silent if chat is active (5+ messages/minute)
Response Suppression
- Active Chat Threshold: 5 messages per minute
- Behavior: Agent suppresses responses when humans are actively talking
- Rationale: Respects human conversation and avoids noise
Suspicious Content Detection
Patterns Detected:
- "join our discord", "discord.gg" (growth spam)
- "grow your channel", "easy money" (scams)
- Multiple URLs (spam)
- Common scam keywords
Actions: Warden flags suspicious messages (not auto-delete)
Database Schema
StreamSession
id(UUID) - Primary keychannel_name- Twitch channelstarted_at- Session start timeended_at- Session end time (null if active)theme- Stream themeis_active- Boolean flag
ChatMessage
id(UUID)session_id- Reference to sessionusername- Message authorcontent- Message texttimestamp- Message timeis_bot,is_moderator- Flags
AgentAction
id(UUID)session_id- Reference to sessionaction_type- RESPONSE, FLAG_SUSPICIOUS, ARCHIVE_CLIP, etc.mode- Which agent mode took actiontriggered_by_message_id- Message that triggered actiondescription- Action details
ClipCandidate
id(UUID)session_id,message_idreason- Why it's clip-worthy
BlogSeed
id(UUID)session_idtopic,descriptionrelated_messages- JSON array
LLM Integration
The system includes a pluggable LLM client that currently:
- Generates mock responses when no provider is configured
- Prepares for OpenAI, Ollama, and LM Studio integration
Current Mock Behavior:
- Returns deterministic responses based on keywords
- Useful for testing without API costs
Implementing Real Providers:
See app/llm/client.py for TODO comments marking where to integrate:
_generate_openai()- OpenAI API calls_generate_ollama()- Ollama local API_generate_lm_studio()- LM Studio API
Current Limitations
This is scaffolding, not production code:
- Twitch EventSub connection is a stub (see TODO comments)
- Chat sending is not implemented
- LLM providers are not integrated yet (mock mode works)
- No real OAuth flow for Twitch
- Database migrations are automatic (no versioning)
- No rate limiting on endpoints
- No authentication/authorization
- Ledger export is basic markdown (no formatting options)
Next Implementation Steps
Phase 1: Core Features (Recommended)
-
Implement real Twitch integration:
- Implement EventSub WebSocket connection in
app/twitch/eventsub.py - Implement send chat message API in
app/twitch/chat.py - Add OAuth token exchange flow
- Implement EventSub WebSocket connection in
-
Integrate real LLM provider:
- Choose provider (e.g., Ollama for self-hosted)
- Implement
_generate_ollama()or_generate_openai() - Test with actual model
-
Enhance agent modes:
- Refine Hearthkeeper timing logic
- Implement Steward mention detection
- Expand Warden pattern library
- Complete Librarian topic extraction
Phase 2: User Experience
-
Add UI/Dashboard:
- Stream monitoring view
- Ledger generation UI
- Settings panel
-
Improve exports:
- Configurable markdown templates
- JSON export option
- Email distribution
-
Add persistence:
- Session history
- Settings storage per channel
- Analytics dashboard
Phase 3: Production Readiness
-
Testing:
- Unit tests for policies
- Integration tests for agent modes
- E2E tests for full flows
-
DevOps:
- Database migrations (Alembic)
- Logging aggregation
- Monitoring/alerting
-
Performance:
- Rate limiting
- Caching for repeated LLM calls
- Message deduplication
Development
Local Setup (Without Docker)
# Create virtual environment
python3.12 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Create .env file
cp .env.example .env
# Run migrations (auto-created on app startup)
# Start app
python -m uvicorn app.main:app --reload
Database Access
# Connect to running PostgreSQL
docker-compose exec sanctum-db psql -U sanctum -d sanctum
# View tables
\dt
# Query sessions
SELECT id, channel_name, started_at FROM stream_sessions;
Logging
The application uses Python's standard logging. Configure in app/main.py:
logging.basicConfig(level=logging.DEBUG)
Contributing
When adding features:
- Maintain async/await patterns throughout
- Add type hints to all functions
- Include docstrings with purpose and TODO comments for future work
- Keep modes independent but shareable
License
(Add your license here)
Support
For issues or questions:
- Check TODO comments in relevant files
- Review the architecture overview
- File an issue with reproduction steps