listen · signals
Routing and queues
Pain, engage, listen and launch.
In Signals
A signal is only useful if it lands where the right action happens. The router sends each one to a queue that matches what you'd do about it: answer someone talking to you, reply to someone in pain, welcome a launch, or just listen. Then it ranks each queue so the daily list starts with what's freshest and most likely to pay.
signal · judged yes → router · which queue, which rank → queue · pain, engage, listen, launch → next move · draft for the founder
rule 1 — Your own conversations first · Anything already talking to you goes to engage before any cold queue. Leaving a reply unanswered costs more than missing a stranger.
rule 2 — One person, one place · A person caught in two queues is merged by person before ranking, so they get one move, not two.
rule 3 — Log what was shown, and its odds · Every rank shown to the founder is stored with the probability it had of being shown. That's what lets a new ranking be judged on old data.
what it is
A rules cascade, then a ranker per queue.
In ops terms this is triage: an ordered set of routing rules picks the queue, and a scoring function ranks inside it.
Queue — work queue · inbox · A list of signals that want the same kind of action.
Cascade — ordered routing rules · Rules checked in order; the first that matches decides the queue.
Priority score — rank · Freshness, trigger strength, fit tier and engagement history, combined to order a queue.
Tier — fit grade · Hot, Warm or Watch from the public-pain rule. Watch is kept, never contacted.
Propensity — probability shown · The chance a card had of being shown.
Next-best-action — policy · What turns a queued signal into one ranked move per lead, under a contact policy.
how it works
The cascade, in the order it checks.
Each signal walks the rules top to bottom. The fit judge tiers it, the person merge collapses duplicates, then the queue ranks.
- Signal — judge said yes
- Talking to you? — → engage
- Launch or listing? — → launch
- States the pain? — → pain
- Otherwise — → listen
- Fit judge — Hot · Warm · Watch
- Merge by person — one card each
- Rank + log odds — the daily list
Is it already a conversation with you?
Replies, mentions, DMs, comments and threads you're in go to engage, whatever else they contain.
Is it a launch?
Launch posts, Show HN and new listings go to launch. For a product sold to founders, a launch is a buying moment.
Does it state the pain?
Asks, complaints, workarounds and competitor reviews go to pain: the main source of cold leads.
Everything else that passed the judge
On-topic but no moment goes to listen: worth reading or joining, not pitching.
Tier the person's product
The public-pain rule: Hot or Warm only when all three fit lines hold; otherwise Watch.
Merge by person
The same person in two queues becomes one card, in the higher-priority queue, with both signals attached.
Rank and log
Order each queue by priority, show the top of each, and store every card shown with its rank and its probability of being shown.
the object
The route decision.
Written when a signal is routed, updated when the founder acts on it.
One per signal. The action fields fill in later.
| Field | Type | What it holds |
|---|---|---|
route_id | uuid | |
signal_id · person_id | uuid | What was routed, and who |
queue | enum | pain, engage, listen, launch |
rule | text | Which cascade rule decided |
router_version | text | So routing changes can be split in the metrics |
tier | enum | Hot, Warm, Watch |
priority | number | The rank score, with its inputs frozen |
shown · shown_rank | bool · int | Whether and where it appeared on the daily list |
propensity | 0..1 | Probability it was shown |
action · acted_at | enum · timestamp | drafted, sent, skipped, snoozed, never |
routed_at | timestamp |
one routed signal, as data
{
"route_id": "rte_1f4",
"signal_id": "sig_7c2",
"person_id": "per_reddit_u_example",
"queue": "pain",
"rule": "states_pain",
"router_version": "cascade@4",
"tier": "Warm",
"priority": 0.72,
"priority_inputs": {
"age_h": 3.5,
"strength": "strong",
"tier": "Warm",
"stacked_signals": 1
},
"shown": true,
"shown_rank": 2,
"propensity": 0.9,
"action": "drafted",
"acted_at": "2026-10-17T13:41:10Z",
"routed_at": "2026-10-17T03:12:46Z"
}the routing rules
Twelve kinds of signal and where each goes.
Queue names are VibeDraft's.
| Queue | When | Why | First move | Act within |
|---|---|---|---|---|
| engage | a reply to your post | Someone answered something you posted. | reply in thread | within hours |
| engage | a mention of your handle | You were named or tagged. | reply, or thank and ask | within hours |
| engage | a DM or an Instagram comment | Direct contact with your account. | answer it first | same day |
| engage | a question in a thread you're already in | The conversation came back to you. | reply in thread | within hours |
| pain | asks for a tool or a recommendation | The clearest buying moment in public. | listen-and-reply | within a day |
| pain | describes the problem or a workaround | Pain without an ask. | listen-and-reply, softer | within a day |
| pain | complains about a competitor | A switching window. | comparison-interception | within a day |
| pain | a new review of a competitor | A public complaint on a review site. | review responder | within days |
| launch | a launch post or Show HN | Someone just shipped and wants users. | launch-or-launch-again plays | launch day |
| launch | a new directory listing | A product just appeared on a launch site. | reply with useful feedback | within days |
| listen | on-topic discussion, no moment | Worth reading or joining, not pitching. | reply with value, no ask | when useful |
| listen | a hiring post for the job the product does | A team paying a person for the task. | watch; note the company | within a week |
failure modes
How routing goes wrong.
Two cards, one person — The same founder is in pain and launch, and gets two drafts. · catch itMerge by person before ranking; one card, both signals attached.
Launch floods the list — Launch days bring hundreds of low-fit launches. · catch itFit tier before rank; Watch never shows; a per-queue daily cap.
Engage starves pain — A busy day of replies pushes every new lead off the list. · catch itA minimum slot count per queue on the daily list.
Silent rule changes — A routing tweak moves signals between queues and the metrics jump. · catch itrouter_version on every route; compare metrics by version.
No odds outside engage — The ranking can't be evaluated on past data. · catch itLog propensity on every queue and every next move.
data to capture
What routing records.
The same four lines every stage uses, under the guide's eight data rules: log the decision, version what decided, freeze the inputs, keep the negatives, log the odds, every human touch is a label, one chain of ids, keep the raw.
record
- every route with its rule, router version, tier and frozen priority inputs
- every card shown, its rank and its probability of being shown
- what the founder did with it, and when
label
- acted on vs skipped, per card
- a reply within 7 days, per routed lead
- founder moves a card to another queue: a routing correction
trains
- a ranker per queue (who's most likely to reply)
- a router that learns from queue corrections
- per-queue slot counts for the daily list
test
- a new ranking · off-policy estimate from logged odds, then a live slice
- queue slot counts · A/B by day
- a routing rule change · shadow, compare where signals would have gone