shouldertap.yaml, and the engine tracks live state for each — whether they’re muted, how many asks are outstanding, and how many they’ve had today. When a request arrives, the router picks the best-matched expert and the asker sends a well-formed message, subject to rate limits and quiet hours.
The registry
Each expert has an id (their Slack user ID), a name, the topics they cover, and an optional escalation target.GET /experts and PUT /experts — but note that PUT rewrites the experts: section of shouldertap.yaml, which remains the source of truth. See the Experts endpoint.
How routing works
When a request arrives, ShoulderTap resolves an expert by trying these steps in order:1
Target override
If the request names
target_experts, routing is bypassed entirely and those experts are asked directly.2
Exact topic match
The request’s topic is normalized (lowercased, whitespace-collapsed) and compared against each expert’s
topics. Among exact matches, the request goes to the expert with the fewest open asks — a simple load balancer that spreads work across equally-qualified experts.3
Fuzzy match
If no exact match exists, ShoulderTap falls back to token-overlap matching between the request topic and expert topics, accepting a match at 0.5 overlap or higher.
4
Topic fallback
If there’s still no match, the request routes to the
fallback expert configured for that topic.5
No expert found
If nothing matches, the request fails with reason
no_expert_found.The outbound ask
Every message the asker sends contains, in a fixed order that no code path can skip:- Self-identification — “I’m ShoulderTap, an automated assistant.” It never pretends to be a person.
- Why it’s asking — the requesting consumer and the reason it’s stuck (from the request’s
context.asked_because). - The question — one question, drafted by the LLM (if configured) to be answerable from memory. Without an LLM, the raw question text is sent verbatim.
- Effort framing — “A one-or-two sentence reply here is all that’s needed.”
- Attribution promise — the answer will be recorded with the expert’s name as the source, after human review.
- Opt-out — reply
muteto stop receiving asks, orskipto pass this one along.
Escalation
If an expert doesn’t reply withinescalation_after (default 2 hours), ShoulderTap re-asks their configured escalation_to. The request is marked escalated, and the original expert’s open-ask count is released. If no one replies anywhere within give_up_after (default 24 hours), the request fails with reason timeout and the consumer is notified.
Rate limits and quiet hours
ShoulderTap enforces these before every send — they are not merely advisory:Concurrent asks
max_open_asks_per_expert (default 3) caps how many unanswered asks an expert can hold at once. When all candidates are capped, the request is held rather than forced onto a busy expert.Daily asks
max_asks_per_expert_per_day (default 5) caps asks per expert per day. The count resets at the start of each day.Quiet hours
quiet_hours (for example ["18:00", "09:00"], evaluated in org.timezone) suppresses DMs outside working hours. Asks are queued and sent when the window reopens.Escalation targets
A capped or muted primary is skipped in favor of the next candidate, so a busy expert never blocks a request that someone else can take.
Opt-outs: mute and skip
Experts control their own participation by replying to any ask:mute— a standing preference. The expert is marked muted and receives no further asks until unmuted. Routing skips muted experts.skip— a one-time pass. The current request is rerouted to the expert’s escalation target (or dropped if there’s none), and the expert’s open-ask count for it is released. Unlike mute, skip does not change their standing availability.
A
mute or skip reply that arrives after a proposal has already been decided is ignored — the answer is not affected, and skip does not reroute a request that’s already resolved.