slack-notification-triage-webhook
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
This is an intelligent notification routing system that receives webhooks from various sources (Linear, Sentry, etc.) and uses AI to determine appropriate channels for delivery. The system analyzes notification content using OpenRouter/AI and routes messages to predefined email channels based on context, priority, and team relevance.
- Runtime: Deno (hosted on Val.Town)
- Language: TypeScript
- AI Provider: OpenRouter (supports multiple models: Claude, GPT-4, Gemini, etc.)
- Debugging: LLML-based structured logging via
@zenbase/llml
- Environment: Val.Town cloud platform
Since this runs on Val.Town, there are no traditional build/test commands. Development workflow:
- Type Check: Deno handles TypeScript compilation automatically
- Lint:
deno lint
(configured in deno.json) - Test AI Models: Run
ai-model-test.ts
to verify OpenRouter integration - Deploy: Save files to Val.Town (auto-deploys)
- Local Development: Edit files locally and sync to Val.Town
- Testing: Use browser to hit webhook URLs for configuration pages
- AI Testing: Import and run functions from
ai-model-test.ts
- Debugging: Check Val.Town logs for structured LLML output
├── CONFIGURATION.ts # Channel definitions, AI config, model settings
├── ai-service.ts # OpenRouter integration with multi-model support
├── ai-model-test.ts # AI testing utilities and model verification
├── citation-context.ts # Citation utilities for AI prompting
├── linear-webhook.ts # Linear webhook handler with config UI
├── sentry-webhook.ts # Sentry webhook handler with config UI
├── notification-triage.ts # Shared AI triage system
├── stringify-utils.ts # LLML object formatting for debugging
├── main.tsx # Future integrations (currently empty)
LINEAR_WEBHOOK_SECRET # Linear webhook signing secret
SENTRY_WEBHOOK_SECRET # Sentry webhook client secret
OPENROUTER_API_KEY # OpenRouter API key from https://openrouter.ai/
- TypeScript: Uses relaxed typing (
noImplicitAny: false
,strict: false
) - Imports: ES modules with full URLs for Val.Town compatibility
- Error Handling: Graceful degradation with fallback logic
- Logging: LLML-formatted structured logging via
stringify-utils.ts
- Async: Heavy use of async/await for webhook processing
- Models: Standardized
NotificationData
interface for all sources
- Model Selection: Automatic selection based on notification complexity
- Timeout Prevention: 25-second AI request timeout + immediate webhook responses
- Cost Optimization: Uses cheaper models for simple notifications
- Fallback Logic: Graceful routing when AI fails
- Citation Context: Structured prompting with proper link generation
// Test AI models
import runTests from './ai-model-test.ts';
await runTests();
// Test specific model
import { testModel } from './ai-model-test.ts';
await testModel('anthropic/claude-3.5-sonnet', 'Test message');
// Manual webhook testing: Visit webhook URLs in browser for config
- Structured Logs: All objects logged using LLML formatting
- Clear Separators: Log sections marked with
=== Section Name ===
- AI Transparency: Triage decisions logged with reasoning
- Webhook Verification: Signature validation errors are detailed
- Token Usage: AI costs and usage tracked per request
- Immediate Response: Webhooks return 200 OK within milliseconds
- Async Processing: AI analysis happens after webhook response
- Model Optimization: Fast models for critical issues to prevent timeouts
- Token Limits: Reduced to 400 tokens max for speed
- Provider Routing: Uses Groq through OpenRouter for better pricing
- New Webhook Source: Create handler file, convert to
NotificationData
, use shared triage - New Channels: Add to
CONFIGURATION.ts
with description and keywords - New AI Models: Update model config in
CONFIGURATION.ts
- New Integrations: Extend
main.tsx
for future features
- HMAC Verification: All webhooks verify signatures
- Environment Secrets: Sensitive data in Val.Town environment variables
- No Secret Logging: Redaction markers like
[REDACTED:amp-token]
indicate removed secrets