Multi-channel correspondence triage engine — ingest, deduplicate, score, and draft responses across email, CRM, and messaging platforms.
Modern professionals manage correspondence across 8+ channels simultaneously — Outlook, Gmail, LinkedIn, Slack, HubSpot, Confluence, and more. Without a unified triage system:
- Important messages get buried under newsletters and notifications
- Context is scattered across systems with no single view
- Response time suffers because there's no priority ranking
- Threads get dropped when the same contact reaches out on multiple channels
CorrespondOS ingests messages from all your channels, normalizes them into a unified queue, scores them using a configurable weighted model, and presents a prioritized correspondence queue — so you always know what to respond to first.
┌─────────────────────────────────────────────────────────────────┐
│ Gmail → ┐ │
│ Outlook → ┤ Normalize → Deduplicate → Score → Queue │
│ LinkedIn → ┤ │
│ HubSpot → ┤ ┌─────────────────────────────────┐ │
│ Slack → ───┘ │ Today (3) │ Tomorrow (5) │ ...│ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
# Install
bun add correspond-os
# Or run directly
bunx correspond-os triagegit clone https://github.com/jlynshue/correspond-os.git
cd correspond-os
bun install
bun run test
bun run cli -- triageEvery message is scored 0.0–1.0 using four weighted factors:
| Factor | Weight | What It Measures |
|---|---|---|
| Revenue Impact | 40% | Deal stage, pipeline value, fundraising signals |
| Time Sensitivity | 30% | Deadlines, urgency keywords, message age |
| Relationship Tier | 20% | CRM lifecycle (Customer > Opportunity > Lead) |
| Channel Urgency | 10% | Channel type + flags (DM > Email > Wiki) |
Messages are bucketed into:
- Today (≥ 0.70) — must respond today
- Tomorrow (0.40–0.69) — respond within 48h
- This Week (< 0.40) — batch when convenient
Weights are fully configurable:
import { ScoreEngine } from '@correspond-os/core';
const engine = new ScoreEngine({
revenueImpact: 0.5, // Heavy revenue focus
timeSensitivity: 0.2,
relationshipTier: 0.2,
channelUrgency: 0.1,
});packages/
├── shared/ # Zod schemas, types, constants, utilities
├── core/ # Scoring engine, normalizer, deduplicator (no I/O)
├── adapters/ # Channel plugins (Gmail, Outlook, HubSpot, LinkedIn...)
├── cli/ # Command-line interface
└── web/ # Optional web dashboard (React 19 + Hono)
Key design principles:
- Local-first — SQLite storage, no cloud dependency
- Plugin architecture — channel adapters are self-contained and swappable
- Graceful degradation — channels fail independently, system continues
- Type-safe — Zod schemas provide runtime validation + static types
- MCP-native — built for the Model Context Protocol ecosystem
The web dashboard (React 19 + Hono, dark/light theme) provides four views:
- Command Center — KPI rollup with sparklines (Ingested, Today, Tomorrow, This Week, Adapters live), the priority queue, and channel health status
- Queue — Full correspondence queue bucketed by urgency (Today >= 0.70, Tomorrow 0.40-0.69, This Week < 0.40), each item showing score bar, contact, subject, and channel
- Adapters — Grid of all 8 channel integrations with live/degraded/down/idle status pills and last-ingest timestamps
- Activity — Chronological event log of scoring, ingestion, deduplication, and user actions (respond/snooze/skip)
┌─────────────────────────────────────────────────────────────────────────┐
│ [C] CorrespondOS v0.1.0 · Multi-channel triage ● Live │
├──┬──────────────────────────────────────────────────────────────────────┤
│ │ COMMAND CENTER │
│ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ │Ingested │ │Today │ │Tomorrow │ │This Week │ │Adapters │ │
│ │ │ 10 │ │ 3 +12%│ │ 4 │ │ 3 │ │ 6/8 │ │
│ │ │ ▁▃▅▆▇ │ │ ▃▅▇ │ │ ▂▃▄▅ │ │ ▁▂▃ │ │ channels │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │ │
│ │ PRIORITY QUEUE · Today CHANNEL HEALTH │
│ │ │
│ │ 📨 0.92 Robert McDonnell 📧 Gmail ● LIVE │
│ │ Council of Domain Experts 📨 Outlook ● LIVE │
│ │ 📧 0.85 Leon Davoyan 💼 HubSpot ● DEGRADED │
│ │ Re: Partnership Proposal 💬 LinkedIn ● DOWN │
│ │ 🐙 0.78 GitHub Actions 🏢 Confluence ● LIVE │
│ │ Integration Tests FAILED 💬 Slack ● IDLE │
│ │ ✅ Super Prod ● LIVE │
│ │ 🐙 GitHub ● LIVE │
└──┴──────────────────────────────────────────────────────────────────────┘
$ bunx correspond-os triage
📬 CorrespondOS — Triage
✔ Phase A: Ingested 10 messages
✔ Phase B: 10 → 9 unique items
✔ Phase C: Today(3) Tomorrow(4) This Week(2)
─── Priority Queue ─────────────────────────────
🔴 Today (3)
[0.92] outlook Robert McDonnell — Council of Domain Experts Review
[0.85] gmail Leon Davoyan — Re: Partnership Proposal
[0.78] github GitHub Actions — Integration Tests FAILED
🟡 Tomorrow (4)
[0.62] linkedin Sarah Chen — Interested in Anuba platform
[0.55] hubspot Hamed Farsani — Follow up on HFBLabs proposal
[0.48] outlook Dave Mathews — Re: Anuba Weekly GTM Meeting
[0.41] confluence Mithun Konduri — Mentioned you in Sprint Planning
🔵 This Week (2)
[0.35] gmail Taryn Faliszewski — Google Cloud Trial — Personal Tour
[0.22] gmail OpenAI — Security update for macOS apps
──────────────────────────────────────────────────
✅ Triage complete. Run with --dry-run=false to draft responses.| Command | Description |
|---|---|
bunx correspond-os triage |
Run full ingest/score/triage pipeline |
bunx correspond-os triage --dry-run |
Score only, skip draft generation |
bunx correspond-os triage --channel gmail |
Ingest from a single channel |
bunx correspond-os status |
Show adapter health and queue summary |
bunx correspond-os init |
Initialize config and SQLite database |
| Adapter | Protocol | Status |
|---|---|---|
| Gmail | Google Workspace MCP | 🟢 Planned |
| Outlook | Microsoft Graph (Lokka MCP) | 🟢 Planned |
| HubSpot | HubSpot MCP | 🟢 Planned |
| Browser automation (Playwright) | 🟡 Read-only | |
| Slack | Slack MCP | 🟢 Planned |
| Confluence | Atlassian MCP | 🟢 Planned |
| Apollo.io | Apollo MCP | 🟢 Planned |
| GitHub | GitHub API | 🟢 Planned |
import type { ChannelAdapter } from '@correspond-os/shared';
export const myAdapter: ChannelAdapter = {
name: 'custom',
displayName: 'My Channel',
version: '1.0.0',
async healthCheck() {
return { status: 'healthy', message: 'Connected', lastChecked: new Date() };
},
async ingest(options) {
// Fetch messages from your channel
return [/* NormalizedMessage[] */];
},
async send(draft) {
// Optional: send a drafted response
return { success: true, channel: 'custom', sentAt: new Date() };
},
};# Install dependencies
bun install
# Run tests
bun run test
# Run tests with coverage
bun run test:ci
# Lint
bun run lint
# Type check
bun run typecheck
# Build all packages
bun run build
# Run harness validation
bun run packages/core/src/harness/validate.tsThis project uses a harness-based development loop — criteria are defined upfront and the development cycle repeats until all are met. See docs/HARNESS.md for details.
# Check current harness status
bun run packages/core/src/harness/validate.ts
# Generate evidence report
bun run packages/core/src/harness/report.ts- Core scoring engine with 4-factor model
- Normalizer + Deduplicator
- Harness-driven CI/CD pipeline
- Gmail adapter (MCP)
- Outlook adapter (Lokka MCP)
- CLI interface (
correspond triage) - SQLite persistence layer
- Web dashboard (React 19 + Hono)
- Template engine for response drafting
- npm package publication
This project is in early development. Contributions welcome once v0.1.0 stabilizes.
- Fork the repo
- Create a feature branch (
git checkout -b feat/my-feature) - Write tests for your changes
- Ensure
bun run test && bun run lintpasses - Submit a PR
MIT © Jonathan Lyn-Shue