Alert your team in Slack when a VIP customer opens a Gorgias ticket using an agent skill
low complexityCost: Usage-based
Prerequisites
Prerequisites
- Claude Code, Cursor, or another AI coding agent that supports skills
GORGIAS_EMAIL,GORGIAS_API_KEY,GORGIAS_DOMAINenvironment variablesSLACK_BOT_TOKENwithchat:writescopeSLACK_CHANNEL_ID— the channel ID for VIP escalation alertsVIP_LTV_THRESHOLD— minimum lifetime spend to qualify as VIP (default:500)
Overview
This agent skill polls Gorgias for recently opened tickets, checks each customer's order history to determine if they meet your VIP threshold, and posts a rich Slack alert with customer context when they do. Because the skill runs as a batch job rather than in response to a webhook, it's ideal for teams that want VIP alerting without setting up any webhook infrastructure.
Step 1: Create the skill directory
mkdir -p .claude/skills/vip-alert/scriptsStep 2: Write the SKILL.md
Create .claude/skills/vip-alert/SKILL.md:
---
name: vip-alert
description: Checks recent Gorgias support tickets for high-value customers and posts a Slack alert with ticket details and customer LTV when a VIP is detected.
disable-model-invocation: true
allowed-tools: Bash(python *)
---
Check for VIP customer tickets and alert the team:
1. Run: `python $SKILL_DIR/scripts/alert.py`
2. Review output — it lists each ticket checked and whether an alert was sent
3. Check your Slack channel to verify the alert format looks rightStep 3: Write the alert script
Create .claude/skills/vip-alert/scripts/alert.py:
#!/usr/bin/env python3
"""
Gorgias VIP Escalation Alert
Polls recent tickets → checks customer LTV → posts Slack alert for VIPs.
"""
import os
import json
from datetime import datetime, timezone, timedelta
from pathlib import Path
try:
import requests
from slack_sdk import WebClient
except ImportError:
os.system("pip install requests slack_sdk -q")
import requests
from slack_sdk import WebClient
GORGIAS_EMAIL = os.environ["GORGIAS_EMAIL"]
GORGIAS_KEY = os.environ["GORGIAS_API_KEY"]
GORGIAS_DOMAIN = os.environ["GORGIAS_DOMAIN"]
SLACK_TOKEN = os.environ["SLACK_BOT_TOKEN"]
SLACK_CHANNEL = os.environ["SLACK_CHANNEL_ID"]
VIP_THRESHOLD = float(os.environ.get("VIP_LTV_THRESHOLD", "500"))
BASE_URL = f"https://{GORGIAS_DOMAIN}.gorgias.com/api"
AUTH = (GORGIAS_EMAIL, GORGIAS_KEY)
# Track alerted tickets to avoid duplicate Slack messages
SEEN_FILE = Path(__file__).parent / ".alerted_tickets.json"
alerted: set = set(json.loads(SEEN_FILE.read_text())) if SEEN_FILE.exists() else set()
slack = WebClient(token=SLACK_TOKEN)
def get_recent_tickets(minutes: int = 90) -> list:
"""Fetch tickets created in the last N minutes."""
since = datetime.now(timezone.utc) - timedelta(minutes=minutes)
resp = requests.get(
f"{BASE_URL}/tickets",
auth=AUTH,
params={"status": "open", "limit": 50},
)
resp.raise_for_status()
tickets = resp.json().get("data", [])
result = []
for t in tickets:
created_raw = t.get("created_datetime", "")
if not created_raw:
continue
try:
created = datetime.fromisoformat(created_raw.replace("Z", "+00:00"))
if created >= since:
result.append(t)
except ValueError:
continue
return result
def get_customer_ltv(customer_id: int) -> tuple[float, int]:
"""Return (total_spent, order_count) from Gorgias customer meta."""
resp = requests.get(f"{BASE_URL}/customers/{customer_id}", auth=AUTH)
if not resp.ok:
return 0.0, 0
meta = resp.json().get("meta", {})
spent = float(meta.get("shopify_total_spent") or 0)
orders = int(meta.get("shopify_orders_count") or 0)
return spent, orders
def is_vip_tagged(ticket: dict) -> bool:
customer_tags = ticket.get("requester", {}).get("meta", {}).get("tags", [])
return any(t.get("name") == "vip" for t in customer_tags)
def post_slack_alert(ticket: dict, ltv: float, order_count: int) -> None:
subject = ticket.get("subject", "(no subject)")
body = (ticket.get("messages") or [{}])[0].get("body_text", "")[:400]
customer = ticket.get("requester", {})
name = customer.get("name") or customer.get("email", "Unknown")
email = customer.get("email", "")
ticket_url = f"https://{GORGIAS_DOMAIN}.gorgias.com/app/ticket/{ticket['id']}"
blocks = [
{
"type": "header",
"text": {"type": "plain_text", "text": "🚨 VIP Customer — New Support Ticket"},
},
{
"type": "section",
"fields": [
{"type": "mrkdwn", "text": f"*Customer*\n{name}"},
{"type": "mrkdwn", "text": f"*Email*\n{email}"},
{"type": "mrkdwn", "text": f"*Lifetime Value*\n${ltv:,.0f}"},
{"type": "mrkdwn", "text": f"*Total Orders*\n{order_count}"},
{"type": "mrkdwn", "text": f"*Subject*\n{subject}"},
],
},
{
"type": "section",
"text": {"type": "mrkdwn", "text": f"*Message*\n{body}"},
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {"type": "plain_text", "text": "Open in Gorgias"},
"url": ticket_url,
"style": "primary",
}
],
},
]
slack.chat_postMessage(
channel=SLACK_CHANNEL,
text=f"🚨 VIP ticket from {name}: {subject}",
blocks=blocks,
)
def main() -> None:
print("Checking recent tickets for VIP customers...")
tickets = get_recent_tickets(minutes=90)
print(f"Found {len(tickets)} recent ticket(s)\n")
alerts_sent = 0
for ticket in tickets:
ticket_id = str(ticket["id"])
if ticket_id in alerted:
continue
customer_id = ticket.get("requester", {}).get("id")
ltv, order_count = get_customer_ltv(customer_id) if customer_id else (0.0, 0)
vip_tagged = is_vip_tagged(ticket)
is_vip = vip_tagged or ltv >= VIP_THRESHOLD or order_count >= 5
subject = ticket.get("subject", "(no subject)")
print(f" #{ticket['id']} {subject[:50]!r} LTV=${ltv:.0f} VIP={is_vip}")
if is_vip:
post_slack_alert(ticket, ltv, order_count)
alerted.add(ticket_id)
alerts_sent += 1
print(f" → Slack alert sent")
# Persist alerted set (keep last 500 entries to avoid unbounded growth)
trimmed = list(alerted)[-500:]
SEEN_FILE.write_text(json.dumps(trimmed))
print(f"\nDone. {alerts_sent} alert(s) sent.")
if __name__ == "__main__":
main()Step 4: Run the skill
# Via Claude Code
/vip-alert
# Or directly
VIP_LTV_THRESHOLD=750 python .claude/skills/vip-alert/scripts/alert.pyStep 5: Schedule it
# crontab -e — run every 30 minutes during business hours
*/30 8-18 * * 1-5 cd /path/to/project && python .claude/skills/vip-alert/scripts/alert.pyOr use GitHub Actions with the same pattern as other skills in this series.
Cost
- No Claude API calls (uses Gorgias and Slack APIs directly)
- Slack SDK: free
- Gorgias API: included in your plan
Need help implementing this?
We build and optimize automation systems for mid-market businesses. Let's discuss the right approach for your team.