Open-source go-to-market signal scoring and outbound automation.
Account intelligence, AI-powered reply drafting, lead qualification, and sales routing — powered by Deepline.
Quick Start · Features · Architecture · API Docs · Deepline · License
This repo has been anonymized. Company names, signals, scoring weights, and configuration values have been scrubbed or replaced with representative examples — they are not real or accurate. The architecture, code patterns, and integrations are production-tested, but the specific data you see is illustrative. Customize the Atlas scoring weights, P0 title patterns, ICP definitions, qualification rules, and integration hooks for your own go-to-market motion before deploying.
A standalone GTM engineering platform that turns your PostgreSQL database into a ranked account intelligence layer. Built for sales and revenue teams who want signal-based prioritization, automated outbound reply handling, and lead qualification — without relying on expensive all-in-one platforms.
Built with: Next.js, PostgreSQL (Neon), Deepline enrichment, OpenAI, Slack, Lemlist/SmartLead/Instantly/HeyReach, Attio CRM, HubSpot
- Scores every account using tech stack adoption, contact seniority, and P0 penetration signals
- 30-day score trends with observed vs. derived data clearly labeled
- Configurable ICP definitions and qualification rules via YAML
- Backtested scoring weights you can override for your GTM motion
- Multi-provider: Lemlist, SmartLead, Instantly, HeyReach — all routed through Deepline gateway
- Receives inbound replies via webhooks (Lemlist) and polling (SmartLead/Instantly/HeyReach via Trigger.dev)
- Drafts AI-powered responses using OpenAI GPT-5-mini with full company context
- Posts to Slack for human review with Approve / Edit / Reject buttons
- Undo Send — approved messages queue for 60s via Upstash QStash before delivery
- Round-robin lead routing to sales reps with Attio CRM + HubSpot sync
- AI-powered qualification against configurable ICP definitions
- Website scraping + LLM analysis for product-market fit scoring
- Automatic routing: qualified leads go to reps, others enter nurture campaigns
- Full audit trail of every routing decision
- API key auth, Slack HMAC-SHA256 verification, Lemlist shared secret, QStash signature verification
- Sliding-window rate limiting (DB-backed), SSRF protection, PII redaction
- LLM prompt injection guardrails, Zod input validation, error sanitization
- 60-second undo-send queue via QStash with cancellation support
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Lemlist │───▶│ Webhook API │───▶│ LLM Draft │
│ SmartLead │ │ /api/outbound│ │ (OpenAI) │
│ Instantly │ └──────┬───────┘ └──────┬──────┘
│ HeyReach │ │ │
└─────────────┘ ┌──────▼────────────────────▼──────┐
│ PostgreSQL (Neon) │
│ inbound.leads | conversations │
│ qualification_results | routing │
│ message_queue | rate_limit_log │
└──────┬────────────────────────────┘
│
┌───────────▼───────────┐
│ Slack Approval │
│ Approve │ Edit │ Undo │
└───────────┬───────────┘
│
┌────────────▼────────────┐
│ QStash (60s delay) │
│ → /api/send-reply │
│ → Deepline Gateway │
│ → Provider-specific API │
└────────────┬────────────┘
│
┌────────────▼────────────┐
│ Attio + HubSpot CRM │
└─────────────────────────┘
Data flow: Deepline enriches company and contact records → Atlas algorithm scores accounts → qualified leads route to sales reps → outbound replies get AI-drafted responses → Slack approval workflow → QStash delayed queue with undo-send → Deepline gateway sends via correct provider → CRM sync.
- Node.js 20+
- PostgreSQL (Neon recommended) with
dl_resolvedanddl_graphschemas - Deepline CLI installed and authenticated (for enrichment)
git clone https://github.com/getaero-io/gtm-signal-scoring
cd gtm-signal-scoring
npm install
cp .env.example .env.local
# Edit .env.local — see Environment Variables below# Core schema (accounts, scoring)
psql $DATABASE_URL -f scripts/migrate.sql
# Outbound engine (leads, conversations, qualification, routing)
psql $DATABASE_URL -f scripts/migrate-outbound.sql
# Message queue with QStash support
psql $DATABASE_WRITE_URL -f scripts/migrate-qstash-message-id.sql
# Rate limiting
psql $DATABASE_URL -f scripts/migrate-message-queue.sql- Create a free account at console.upstash.com
- Copy your QStash Token, Current Signing Key, and Next Signing Key
- Add them to
.env.local(see Environment Variables below) - On Vercel: add via Upstash Marketplace integration or manually in Project Settings → Environment Variables
npm run devOpen http://localhost:3000.
DATABASE_URL=postgresql://user:pass@host:5432/db# Write connection (falls back to DATABASE_URL if not set)
DATABASE_WRITE_URL=postgresql://user:pass@host:5432/db
# OpenAI for LLM reply drafting
OPENAI_API_KEY=sk-...
# Slack integration (https://api.slack.com/apps)
SLACK_BOT_TOKEN=xoxb-...
SLACK_SIGNING_SECRET=...
SLACK_CHANNEL_OUTBOUND=replybot
SLACK_CHANNEL_INBOUND=replybot
# Lemlist (https://app.lemlist.com/settings/integrations)
LEMLIST_API_KEY=...
LEMLIST_WEBHOOK_SECRET=your-shared-secret
LEMLIST_CAMPAIGN_IDS=camp_abc,camp_def
# Deepline gateway — routes to Lemlist/SmartLead/Instantly/HeyReach
DEEPLINE_API_KEY=...
DEEPLINE_CLI_PATH=/usr/local/bin/deeplineGet these from console.upstash.com/qstash:
QSTASH_TOKEN=...
QSTASH_CURRENT_SIGNING_KEY=sig_...
QSTASH_NEXT_SIGNING_KEY=sig_...# API key for dashboard routes (leave empty in dev to skip auth)
INTERNAL_API_KEY=your-secret-api-key
# Message queue delay in seconds (default: 60)
MESSAGE_SEND_DELAY_SECONDS=60
# Enable test endpoints in production (default: disabled)
ALLOW_TEST_ENDPOINTS=false# Anthropic (for AI qualification)
ANTHROPIC_API_KEY=sk-ant-...
# Exa web search (fallback enrichment)
EXA_API_KEY=...# HubSpot
ENABLE_HUBSPOT=false
HUBSPOT_ACCESS_TOKEN=
HUBSPOT_PORTAL_ID=
# Notion
ENABLE_NOTION=false
NOTION_API_KEY=
NOTION_DATABASE_ID=
# Email (SMTP)
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=
SMTP_PASS=
SMTP_FROM="GTM Signal <noreply@example.com>"docs/SCORING_MODEL.md is a working example, not a universal template. The weights, title patterns, and thresholds are calibrated for one company's GTM motion and backtested against their pipeline data. Override them with values that reflect your ICP, deal stages, and conversion signals before deploying.
Example weights (customize in lib/scoring/scoring-config.json):
- Base: 20 points
- Tech adoption: up to +15 per tool (with time decay)
- Contact seniority: C-Level +25, VP +20, Director +15, Manager +10
- P0 engagement: +10 per qualified contact
- Company size: +5 to +20
- Max: 100 points
The scoring model and outbound engine are intentionally opinionated. See docs/CUSTOMIZATION.md to adapt:
- Atlas scoring weights (
lib/scoring/scoring-config.json) - P0 title/department patterns (
lib/scoring/scoring-config.json) - ICP definitions (
config/outbound/icp-definitions.yaml) - Qualification rules and filters (
config/outbound/qualification-rules.yaml) - Response templates and triggers (
config/outbound/response-templates.yaml) - Routing rules and rep assignment (
config/outbound/routing-rules.yaml) - Company context for LLM prompts (
config/outbound/company-context/)
| Integration | Type | Purpose | Setup |
|---|---|---|---|
| Deepline CLI | Required | Company/contact enrichment + outbound gateway | deepline.com |
| PostgreSQL / Neon | Required | Primary datastore | neon.tech |
| OpenAI | Required (outbound) | LLM reply drafting (GPT-5-mini) | platform.openai.com/api-keys |
| Slack | Required (outbound) | Approval workflow | api.slack.com/apps |
| Upstash QStash | Required (outbound) | Undo-send message queue | console.upstash.com/qstash |
| Lemlist | Outbound provider | Email/LinkedIn campaigns | app.lemlist.com |
| SmartLead | Outbound provider | Email campaigns (via Deepline) | smartlead.ai |
| Instantly | Outbound provider | Email campaigns (via Deepline) | instantly.ai |
| HeyReach | Outbound provider | LinkedIn campaigns (via Deepline) | heyreach.io |
| Attio | Optional | CRM sync for qualified leads | attio.com |
| HubSpot | Optional | CRM sync | developers.hubspot.com |
| Trigger.dev | Optional | Scheduled qualification + polling | trigger.dev |
| Notion | Optional | Database sync | notion.so |
| Anthropic | Optional | AI qualification | console.anthropic.com |
| Exa | Optional | Web search enrichment fallback | exa.ai |
npm i -g vercel
vercel link
vercel env pull # pulls env vars to .env.local
# Add QStash via Upstash marketplace (auto-provisions env vars):
vercel integration add upstash
# Or set manually in Vercel dashboard → Settings → Environment Variables:
# QSTASH_TOKEN, QSTASH_CURRENT_SIGNING_KEY, QSTASH_NEXT_SIGNING_KEY
vercel deploy --prodnpx trigger.dev@latest deploy- docs/API.md — API routes, frontend pages, webhook auth, YAML config, scheduled tasks, database schema, security details
- docs/SCORING_MODEL.md — Full Atlas algorithm documentation (backtested example)
- docs/CUSTOMIZATION.md — How to adapt scoring, ICP, and outbound config
- docs/DATABASE_SCHEMA.md — Complete schema reference
- docs/INTEGRATIONS.md — Integration setup guides
- Deepline — The enrichment engine that powers contact and company data
gtm go-to-market signal-scoring outbound lead-generation lead-qualification sales-automation account-intelligence icp-scoring deepline lemlist smartlead instantly heyreach slack attio hubspot crm ai-reply llm qstash next.js postgresql neon
MIT — see LICENSE.
Built with Deepline