Phase 1: Hello Bot with Event Subscriptions
Overview
Phase 1 implements a basic Slack bot that responds to mentions with a "Hello!" message. This establishes the foundation for the Claude CS Bot by setting up:
- FastAPI web application with Slack event handling
- Slack signature verification for security
- URL verification challenge handling
- Background task processing to meet Slack's 3-second timeout
- Docker containerization
- Google Cloud Run deployment
Project Structure
.
├── main.py # FastAPI application with event handlers
├── config.py # Configuration management with pydantic-settings
├── pyproject.toml # Project dependencies and metadata
├── Dockerfile # Multi-stage Docker build
├── .env.example # Example environment variables
├── .env # Actual environment variables (gitignored)
├── deploy.sh # Automated deployment script
├── DEPLOYMENT.md # Detailed deployment guide
├── slack_manifest.json # Slack app configuration manifest
├── tests/
│ ├── __init__.py
│ └── test_main.py # Unit tests for all endpoints
└── README.md # This fileFeatures Implemented
✅ 1. FastAPI Application Structure
/healthendpoint for health checks/slack/eventsendpoint for Slack event subscriptions- Structured JSON logging
- Background task processing
✅ 2. Slack Signature Verification
- HMAC-SHA256 signature verification
- Timestamp validation (5-minute tolerance)
- Replay attack prevention
- Reference: https://api.slack.com/authentication/verifying-requests-from-slack
✅ 3. URL Verification Challenge
- Handles Slack's URL verification challenge
- Returns challenge parameter in JSON format
- Reference: https://api.slack.com/events/url_verification
✅ 4. App Mention Event Handling
- Responds to
@slackbotmentions - Posts response in thread (maintains conversation context)
- Ignores bot's own messages (prevents loops)
- Background processing to avoid 3-second timeout
✅ 5. Comprehensive Testing
- 9 unit tests covering all functionality
- Test coverage includes:
- Health endpoint
- Signature verification (valid/invalid/old timestamp)
- URL verification challenge
- App mention events
- Bot message filtering
- Invalid JSON handling
✅ 6. Docker Containerization
- Multi-stage build for smaller image size
- Uses
uvpackage manager for fast dependency installation - Non-root user for security
- Health check included
- Optimized for Cloud Run
✅ 7. Deployment Automation
- Automated deployment script (
deploy.sh) - Detailed deployment guide (
DEPLOYMENT.md) - Google Cloud Run configuration
Quick Start
Local Development
- Install dependencies:
bash
uv sync --extra dev- Set up environment variables:
bash
cp .env.example .env
# Edit .env with your Slack credentials- Run tests:
bash
uv run pytest tests/ -v- Run locally:
bash
uv run uvicorn main:app --reload --port 8000- Expose with ngrok (for Slack webhook testing):
bash
ngrok http 8000
# Update Slack Event Subscriptions URL with ngrok URLDocker Testing
- Build image:
bash
docker build -t slack-claude-bot:latest .- Run container:
bash
docker run --rm -p 8080:8080 --env-file .env slack-claude-bot:latest- Test health endpoint:
bash
curl http://localhost:8080/health
# Expected: {"status":"ok"}Deployment to Google Cloud Run
Option 1: Automated Script
bash
./deploy.shThe script will:
- Check authentication
- Enable required APIs
- Create Artifact Registry repository
- Build and push Docker image
- Deploy to Cloud Run
- Display service URL
Option 2: Manual Deployment
See DEPLOYMENT.md for detailed manual deployment instructions.
Slack App Setup
Method 1: Using Manifest (Recommended)
- Go to https://api.slack.com/apps
- Click "Create New App" → "From an app manifest"
- Select your workspace
- Copy contents from
slack_manifest.json - Replace
YOUR-CLOUD-RUN-URLwith your actual Cloud Run URL - Create the app
- Install to workspace
- Copy Bot Token and Signing Secret
Method 2: Manual Configuration
- Create new Slack app at https://api.slack.com/apps
- Configure OAuth & Permissions:
- Bot Token Scopes:
app_mentions:readchat:writechannels:historygroups:historyim:historympim:history
- Bot Token Scopes:
- Configure Event Subscriptions:
- Enable Events: ON
- Request URL:
https://YOUR-CLOUD-RUN-URL/slack/events - Subscribe to bot events:
app_mention
- Install App to Workspace
- Copy Bot Token (starts with
xoxb-) and Signing Secret
Testing the Bot
- Invite bot to channel:
/invite @Claude CS Bot- Mention the bot:
@Claude CS Bot hello- Expected response:
Hello! I'm Claude CS Bot. I'm ready to help you!Architecture
┌─────────────┐ ┌──────────────────┐ ┌──────────────┐
│ │ POST │ │ POST │ │
│ Slack │────────▶│ Cloud Run │────────▶│ Slack Web │
│ Events │ │ (FastAPI App) │ │ API │
│ │◀────────│ │ │ │
│ │ 200 OK │ │ │ │
└─────────────┘ └──────────────────┘ └──────────────┘
│
│ Background
▼ Task
┌─────────────┐
│ Process │
│ Mention │
└─────────────┘Request Flow
- Slack sends event →
/slack/eventsendpoint - Signature verification → Validates request authenticity
- Return 200 immediately → Meets 3-second timeout requirement
- Background task → Processes mention and responds
- Post message to Slack → Sends response in thread
Key Implementation Details
Slack Signature Verification
python
def verify_slack_signature(body: bytes, timestamp: str, signature: str) -> bool:
# Check timestamp (5 minute tolerance)
if abs(current_timestamp - int(timestamp)) > 60 * 5:
return False
# Compute HMAC-SHA256
sig_basestring = f"v0:{timestamp}:{body.decode('utf-8')}"
computed_signature = "v0=" + hmac.new(
signing_secret.encode(),
sig_basestring.encode(),
hashlib.sha256,
).hexdigest()
# Compare signatures
return hmac.compare_digest(computed_signature, signature)Background Task Processing
python
@app.post("/slack/events")
async def slack_events(
request: Request,
background_tasks: BackgroundTasks,
...
):
# Verify signature
# Parse event
# Add to background tasks (non-blocking)
background_tasks.add_task(process_app_mention, event_data)
# Return immediately (within 3 seconds)
return Response(status_code=200)Thread Response
python
async def process_app_mention(event_data: dict):
event = event_data["event"]
channel = event["channel"]
thread_ts = event.get("thread_ts") or event["ts"] # Use existing thread or start new
slack_client.chat_postMessage(
channel=channel,
thread_ts=thread_ts, # Ensures response in thread
text="Hello! I'm Claude CS Bot. I'm ready to help you!",
)Environment Variables
Required for Phase 1:
bash
SLACK_BOT_TOKEN=xoxb-... # Bot User OAuth Token
SLACK_SIGNING_SECRET=... # Signing Secret for verificationOptional (for future phases):
bash
ANTHROPIC_API_KEY=sk-ant-... # Claude API key (Phase 2)
NOTION_API_KEY=secret_... # Notion API key (Phase 3)
NOTION_DATABASE_ID=... # Notion database ID (Phase 3)Monitoring and Logs
View Cloud Run Logs
bash
# Recent logs
gcloud run logs read slack-claude-bot --region us-central1 --limit 50
# Stream logs
gcloud run logs tail slack-claude-bot --region us-central1Log Format
All logs use structured JSON format:
json
{
"time": "2025-10-20 10:30:00",
"level": "INFO",
"message": {
"action": "processing_mention",
"channel": "C123456",
"thread_ts": "1234567890.123456",
"user": "U123456"
}
}Testing
Run All Tests
bash
uv run pytest tests/ -vRun with Coverage
bash
uv run pytest tests/ --cov=. --cov-report=html
open htmlcov/index.htmlTest Results
============================= test session starts ==============================
tests/test_main.py::TestHealthEndpoint::test_health_check PASSED [ 11%]
tests/test_main.py::TestSlackSignatureVerification::test_verify_slack_signature_valid PASSED [ 22%]
tests/test_main.py::TestSlackSignatureVerification::test_verify_slack_signature_invalid PASSED [ 33%]
tests/test_main.py::TestSlackSignatureVerification::test_verify_slack_signature_old_timestamp PASSED [ 44%]
tests/test_main.py::TestURLVerification::test_url_verification_challenge PASSED [ 55%]
tests/test_main.py::TestURLVerification::test_url_verification_invalid_signature PASSED [ 66%]
tests/test_main.py::TestAppMentionEvent::test_app_mention_event PASSED [ 77%]
tests/test_main.py::TestAppMentionEvent::test_app_mention_ignores_bot_messages PASSED [ 88%]
tests/test_main.py::TestAppMentionEvent::test_invalid_json_returns_400 PASSED [100%]
============================== 9 passed in 0.94s ===============================Troubleshooting
Issue: URL Verification Challenge Fails
Symptoms: Slack shows "Your URL didn't respond with the value of the challenge parameter"
Solution:
- Ensure service is deployed and accessible
- Check logs for errors
- Test endpoint manually:
bash
curl -X POST https://YOUR-URL/slack/events \
-H "Content-Type: application/json" \
-d '{"type": "url_verification", "challenge": "test"}'
# Expected: {"challenge":"test"}Issue: 403 Forbidden on Events
Symptoms: Events not being processed, 403 errors in logs
Solution:
- Verify
SLACK_SIGNING_SECRETis correct - Check Cloud Run environment variables
- Ensure signature verification is not failing due to clock skew
Issue: Bot Not Responding
Symptoms: Bot doesn't reply to mentions
Solution:
- Check bot is invited to channel:
/invite @Claude CS Bot - Verify Event Subscriptions are configured
- Check Cloud Run logs for errors
- Ensure
app_mentionevent is subscribed - Verify bot token has
chat:writescope
Issue: Docker Build Fails
Symptoms: Error during docker build
Solution:
- Ensure
pyproject.tomlhas correct dependencies - Check Dockerfile syntax
- Verify uv installation in container
Issue: Tests Fail
Symptoms: pytest shows failures
Solution:
- Ensure
.envfile exists with test values - Check all dependencies installed:
uv sync --extra dev - Verify Python version >= 3.11
Performance Metrics
Cold Start
- Average: 2-3 seconds
- Optimization: Set
--min-instances 1(costs more)
Response Time
- Health check: < 50ms
- URL verification: < 100ms
- Event processing: < 200ms (background task)
Resource Usage
- Memory: ~200MB (512MB allocated)
- CPU: Minimal during idle
- Cost: Within free tier for moderate use
Success Criteria
Phase 1 is complete when:
- ✅ All tests pass (9/9)
- ✅ Docker image builds successfully
- ✅ Health endpoint returns 200 OK
- ✅ URL verification challenge passes
- ✅ Bot responds to mentions with "Hello!" message
- ✅ Responses appear in thread
- ✅ Deployed to Cloud Run
- ✅ Slack Event Subscriptions verified
Next Steps
Once Phase 1 is working:
Verify in production:
- URL verification passes
- Bot responds to mentions
- Logs show no errors
Prepare for Phase 2:
- Get Anthropic API key
- Review Claude Agent SDK documentation
- Plan thread context management
Phase 2 Goals:
- Replace static "Hello!" with Claude AI responses
- Implement conversation history tracking
- Add "Thinking..." → final response flow
- Error handling for Claude API
References
Support
For issues or questions:
- Check DEPLOYMENT.md for deployment issues
- Review logs:
gcloud run logs read slack-claude-bot - Verify Slack app configuration
- Check environment variables are set correctly