agentsclimarketplace

Whatsteam customer support

Skill whatsteamhq/whatsapp-claude-skills/skills/whatsteam-customer-support

Agent Skills for WhatsTeam — automate WhatsApp Business (official API) by chatting with Claude, Cursor, Codex or any Agent Skills client. 23 skills + the WhatsTeam MCP.

Install
npx -y skills add whatsteamhq/whatsapp-claude-skills --skill whatsteam-customer-support

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Run a WhatsApp customer support operation with WhatsTeam — multi-agent inbox, auto-replies, business-hours, SLA tracking (first-response, resolution), escalation rules, ticket lifecycle, FAQ deflection, and reporting on team performance. Use when the user runs (or is building) a customer support team that handles tickets over WhatsApp and needs to organize the inbox, hit SLAs, and report on CSAT and workload.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

9.4 KB, as published. Nobody here has run it

WhatsTeam for Customer Support

A complete playbook for running customer support on WhatsApp with a team — from the moment a customer messages in, to ticket resolution and reporting.

When to use

Activate when the user:

  • Operates a support team, helpdesk, customer service, or success function on WhatsApp.
  • Asks about SLAs, first-response time, resolution time, escalation, CSAT, tickets.
  • Mentions auto-reply, business hours, out-of-office, FAQ, bot handoff.
  • Wants routing by language, product, region, or department.
  • Asks "how do I report on what my team is doing?"

For outbound sales / lead qualification, route to whatsteam-sales-bot. For broadcasts, use whatsteam-campaigns. For order-related support inside an e-commerce flow, see whatsteam-ecommerce Recipe 5.

Prerequisites

  • whatsteam-setup complete.
  • Team members configured at https://app.whats.team/team.
  • (Recommended) Departments configured at https://app.whats.team/device/departments (Tier 1, Billing, Tech, …).
  • (Optional) A knowledge base / FAQ source for deflection.
  • For WABA: pre-approved Utility templates for out-of-hours, escalation acknowledgement, ticket-closed-feedback.

The support lifecycle

NEW ─► PENDING ─► IN PROGRESS ─► WAITING ON CUSTOMER ─► RESOLVED ─► CLOSED
            │           │              │
            └──────► escalate ──► assigned to senior agent / dept

Map this to WhatsTeam primitives:

Lifecycle stageWhatsTeam state
NEW / PENDINGchat.status = active, no assignedTo
IN PROGRESSchat.status = active, assignedTo = agent
WAITING ON CUSTOMERlabel waiting-customer, status still active
RESOLVEDchat.status = resolved
CLOSEDchat.status = archived (no further action expected)
ESCALATEDlabel escalated + reassign

Recipes

Recipe 1 — Auto-reply on first contact

"When a brand-new customer messages us, send a greeting and tell them what to expect."

on message:in:new where chat.messageCount == 1:
  if within_business_hours():
    reply: "Hi! Thanks for reaching out. An agent will respond within 15 minutes."
    label chat "new-contact"
  else:
    reply: "Hi! Our hours are 9am-7pm CET, Mon-Fri. We'll reply first thing tomorrow."
    label chat "out-of-hours"
  ack 200

Use your own DB to track "first message" — chat.messageCount is not a reliable first-contact signal (it may include outbound messages, depending on how the chat was created). For "is this the first inbound?" logic, track first-inbound in your own DB, or fall back to chat.lastInboundAt (which exists) being unset before this event.

Recipe 2 — Business hours + holiday calendar

function within_business_hours():
  now = utcnow()
  local = now.in_timezone("Europe/Madrid")
  if local.weekday() in [Saturday, Sunday]: return false
  if local.date in holiday_calendar: return false
  return 9 <= local.hour < 19

# On message:in:new outside business hours:
  send template "out_of_hours" with [agentName, next_business_day]
  label chat "out-of-hours"

Don't auto-reply twice to the same out-of-hours window for the same chat. Track last-auto-reply timestamp per chat.

Recipe 3 — Route to the right department

"Messages mentioning billing → Finance dept. Messages mentioning technical issues → Tech."

on message:in:new:
  intent = classify(message.body)   # rule-based or LLM
  if intent == "billing":
    assign chat to Finance dept
    label "intent:billing"
  elif intent == "technical":
    assign chat to Tech dept
    label "intent:technical"
  else:
    assign to Tier 1 round-robin

Use the chat's analyze_whatsapp_chat_messages tool for LLM-based intent extraction. Cache the classification on the chat so subsequent messages skip the LLM call.

Recipe 4 — SLA tracking (first response time)

Define SLAs per chat tier:

TierFirst responseResolution
Standard30 min24h
Premium (label vip)10 min4h
Enterprise5 min2h

Implement via scheduled job:

every 1 min:
  pending_chats = get_whatsapp_chats_by_status(active) where assignedTo is null
  for chat in pending_chats:
    sla = sla_for(chat.labels)
    age = now - chat.firstInboundAt   # see caveat below
    if age > sla.first_response * 0.8 and not chat.sla_warned:
      ping_team_in_slack("⚠️ Chat with {customer} is {age}min old, SLA breach in {remaining}min")
      mark chat.sla_warned = true
    if age > sla.first_response:
      ping_team_in_slack("🚨 SLA BREACHED on chat with {customer} ({age}min)")
      label chat "sla-breach"

Field caveat: chat.firstInboundAt is not a reliable field — for first-contact / SLA-start logic, use chat.lastInboundAt (which exists, returned by get_whatsapp_chats action:by_id) or stamp the first-inbound time in your own DB on the message:in:new webhook. Don't assume firstInboundAt or messageCount are populated.

Recipe 5 — FAQ deflection

Before routing to a human, try to answer common questions:

on message:in:new (with bot tag enabled):
  faq_match = match_faq(message.body, threshold=0.8)
  if faq_match:
    reply with faq.answer + "Did that help? Reply YES or type AGENT to talk to a person."
    label chat "faq-attempted"
    if next inbound is "AGENT" or negative sentiment:
      remove bot tag, assign to human
  else:
    assign to human directly

Deflection reduces team load 30-50% on commodity questions. Track success rate: chats labeled faq-attempted AND ending in resolved without human assignment.

Recipe 6 — Escalation

"If an agent hasn't replied in 2 hours, escalate to senior."

every 5 min:
  in_progress = get_whatsapp_chats_by_status(active) where assignedTo not null and labels not include "resolved"
  for chat in in_progress:
    last_outbound = last message from any agent in chat
    if (now - last_outbound) > 2h:
      reassign chat to senior_agent_or_team_lead
      label "escalated"
      notify both original and new owner in Slack

Set the escalation threshold by tier. Don't auto-escalate VIPs to the same junior agent twice in a row.

Recipe 7 — Resolution + CSAT survey

When agent marks chat as resolved:

1. set chat.status = resolved
2. wait 5 minutes (let the last message land)
3. send template "csat_survey":
     "How would you rate this support experience?
      Reply 1 (bad) to 5 (excellent)."
4. on next message:in:new where chat.status == resolved:
     parse rating
     save to CSAT DB
     if rating <= 2: alert team lead for follow-up

Don't send the CSAT request more than once per chat. Track sent-at timestamp. This loop must respect the auto-reply suppression from Anti-patterns ("Auto-replying after the first message of a thread") — gate the CSAT send on bot-still-active / no-human-in-thread so the survey and a first-contact greeting don't double-fire on the same inbound.

Recipe 8 — Reporting

Daily / weekly digest queries:

- Open chats by department:
    for each dept: get_whatsapp_chats_by_status(active) filtered by dept
- Avg first response time today:
    get_whatsapp_chat_statistics with dateRange=today
- Top agents by resolved chats:
    for each agent: count get_whatsapp_chats_by_status(resolved) where assignedTo=agent
- SLA breach count:
    count chats with label "sla-breach" today

Render to a Slack message, a Google Sheet, or a Notion database via a scheduled job.

Anti-patterns

  • Auto-replying after the first message of a thread. Once the human is in, the bot should be silent. Only the first message (or after WAITING for >Xh) should trigger an auto-reply.
  • Closing chats too aggressively. Mark resolved only when the customer confirms (or after a clear "thank you"). Premature close kills CSAT.
  • No labels = no reporting. If you can't query chats by topic, intent, or status, you have no visibility. Label aggressively, even if just intent:*.
  • SLAs without escalation. SLAs that fire alerts but don't actually reassign are theater. Wire escalation to the same SLA timer.
  • Mixing sales and support in one inbox without labels. Sales reps optimize for revenue; support optimizes for resolution. Label every inbound so reports can split correctly.

See also

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.