See llms.txt for all machine-readable content.
Runs an e-commerce support desk end to end: it classifies each incoming message, answers what it is allowed to answer, sends the reply, escalates the rest to a human in Slack, appends every ticket to a Google Sheets log, and emails a daily operations digest. No credentials are needed to test the triage itself.
Intake and triage
Webhook - New Support Message accepts a POST with customer_name, order_id, message and an optional email.01 - Normalize Message caps the message at 2000 characters, sanitises the order number and mints a ticket_id. A malformed payload never throws.02 - Classify Intent & Priority scores the text against weighted keyword sets (order status, refund/return, product question, shipping policy, complaint), detects English vs. Chinese and computes confidence as top / (top + second).03 - Route by Intent is a Switch with four named outputs plus a fallback. Low-confidence and complaint tickets take the fallback on purpose: a wrong automated answer costs more than a fast human one.Answering
04a builds the order-status answer, 04b handles refunds (acknowledge, state the published window, escalate — never decide), 04c retrieves the approved policy from a local knowledge base, and 04d writes the holding reply for anything ambiguous.05 - DeepSeek Support Agent only re-phrases the approved policy answer; its system message forbids inventing policy, prices or dates. 06 - Compose AI Reply enforces the guarantee: model text if present, otherwise the knowledge-base answer verbatim, otherwise a handoff reply.07 merges the branches and 08 - Finalize Response builds one stable JSON envelope.Delivering (this is where the workflow stops being a demo)
10 - Route Delivery splits tickets three ways: human handoff, email reply, or fallback when the customer left no address.11b - Escalate to Slack posts ticket id, priority, intent and next action to the team channel. Refunds and complaints always land here.11a - Send Reply to Customer sends the approved answer through Gmail — but only for tickets the classifier was confident about.12 - Merge Delivery and 13 - Log Ticket to Google Sheets rejoin the branches and append one row per ticket: id, time, customer, order, intent, priority, handoff, source, next action.09 - Respond to Platform returns the envelope to the caller after delivery and logging, so a 200 means the ticket was actually handled.Reporting and resilience
S0-S3 is an independent daily flow: at 08:00 it reads the ticket log, keeps the last 24 hours and emails volume, automation rate, escalation count, urgent count and the intent/source mix.E0-E2 is the error path: a failed execution posts the failing node, execution id and error message to the same Slack channel. Select this workflow as the Error Workflow in Settings to activate it.Webhook - New Support Message.curl -X POST <your-webhook-url> -H 'Content-Type: application/json' \
-d '{"customer_name":"Ana","email":"[email protected]","order_id":"1001","message":"Where is my order? It has been a week."}'
11a and S3.13 and S1, then replace REPLACE_WITH_SPREADSHEET_ID with your spreadsheet id and create a Tickets tab with the header row ticket_id | received_at | customer_name | customer_email | order_id | intent | priority | handoff | source | next_action.11b and E2 (https://hooks.slack.com/services/REPLACE/WITH/YOURS) with your own incoming-webhook path.S3. Every delivery node is set to continue on error, so an unconfigured channel logs a warning instead of failing the customer request.INTENT_KEYWORDS and INTENT_WEIGHT in 02: add your own vocabulary and tune how strongly refunds and complaints pull the routing.AMBIGUITY_GATE (default 0.6): raise it to hand more tickets to humans, lower it to automate more.ALWAYS_HUMAN: intents that never receive an automated answer.RETURN_WINDOW_DAYS in 04b: your published return window, quoted in the reply.KB in 04c: one entry per policy with keywords, an English answer, a Chinese answer and a ref.04a contains the only mocked lookup: the tracking reference is derived locally so the workflow runs without a store. Two lines are marked MOCK — replace them with an HTTP Request to Shopify, WooCommerce or AfterShip and the rest of the branch keeps working.COLS in S2: match the column order of your ticket log if you add fields.Every response reports how the decision was made, so you can audit automation quality instead of trusting it:
{ "ticket_id": "T-...", "intent": "product", "confidence": 1, "priority": "normal",
"language": "en", "handoff": false, "source": "deepseek", "next_action": "none",
"policy_refs": ["kb/sizing"],
"diagnostics": { "matched_keywords": ["what size"], "kb_id": "sizing", "ai_used": true } }
source is one of logistics, refund, deepseek, kb_fallback, handoff or fallback, which tells you at a glance how much volume the bot answered on its own and how much went to a person.
The daily digest computes the same number for you (automation rate) from the ticket log, so the metric and the audit trail can never disagree. Tickets that never reached the log because Sheets was not configured still get a JSON response — the workflow degrades, it does not disappear.