What SupportOps is
Link to section “What SupportOps is”In 30 seconds
Link to section “In 30 seconds”SupportOps (support operations) is the discipline of designing and running the system that customer support works inside: how requests arrive, how they are classified and routed, which clock each one is measured against, how many people are needed in each half hour, which tools and automations they use, how quality is checked, and how the numbers reach the people who can fix the causes. Support agents answer customers; SupportOps makes sure the right agent gets the right ticket at the right time, with the knowledge and tools to solve it, and that leaders can see whether the promise to customers is being kept.
A short way to hold it: support is a queue (work arriving at random), measured by clocks (service levels), improved through loops (insight flowing back to product, knowledge and staffing). SupportOps owns all three.
Written for beginners, support ops managers, workforce management analysts, helpdesk administrators, and the product and engineering leaders who receive escalations. Sources were last verified on 2026-10-23.
At a glance
Link to section “At a glance”| Question | Answer |
|---|---|
| Goal | Predictable response and resolution times at a sustainable cost, with customer insight reaching the teams that can remove the causes |
| Who does it | Support operations managers and analysts, workforce management (WFM) analysts, helpdesk administrators, QA leads, support tooling engineers |
| Scope | Channels and intake, triage and routing, tiers and escalation, SLA policies, macros and automation, self-service and AI agents, quality assurance, staffing and scheduling, support data and reporting |
| Not in scope | Account health and renewals (CustomerOps), survey design and journey-wide feedback (CXOps), the knowledge practice itself (KnowledgeOps), production incident command (IncidentOps) |
| Prerequisites | None. Basic spreadsheet skills help; the labs use Python’s standard library |
| Key outputs | SLA policies, routing rules, staffing plans and schedules, a metric dictionary, QA scorecards, an escalation interface, a change log for the helpdesk |
| Term status | Established as “support operations” (a recognised team and job family); the one-word “SupportOps” is informal and has no standards body |
The problem it solves
Link to section “The problem it solves”Without an operations layer, a support team that grows from five people to fifty usually hits the same walls, in roughly this order:
- Nobody can say how many people are needed. Headcount requests are argued from anecdote (“we are drowning”) rather than from volume, handle time and a stated service level. The answer arrives after the backlog does.
- Clocks disagree. One report says 92% of tickets got a first reply within eight hours, another says 61%. Both are right: one counts business hours and lets an autoreply stop the clock; the other counts calendar hours and waits for a human.
- Work lands on whoever looks first. The hardest tickets sit untouched because everyone cherry-picks easy ones; specialists answer password resets while integration problems wait.
- The helpdesk becomes an archaeological site of triggers and macros nobody can explain.
- Insight leaks. The same bug is reported 300 times, solved 300 times, and engineering hears about it from a sales call.
- Cost rises faster than volume, because every new channel and every new product line gets its own queue and its own staff, and pooled capacity is lost.
SupportOps is the response: treat support as a service system with demand, capacity, routing rules and feedback loops, and give someone the job of designing and running that system.
What SupportOps is not: naming and boundaries
Link to section “What SupportOps is not: naming and boundaries”- Not the support team. Agents and support engineers resolve customer problems. SupportOps designs their environment. A vendor blog captures the remit well: support operations as “a team of seasoned experts dedicated to providing your agents with the tools they need to do their job”.[1] In a small company the same person does both, and that is fine.
- Not CustomerOps or CXOps (editorial distinction). The labels overlap in the market: “customer operations” is used as an umbrella for all customer-facing operations, as a synonym for support operations, and for customer success operations. This Atlas assigns reactive service (tickets, SLAs, queues) to SupportOps, proactive post-sale success (health scores, renewals) to CustomerOps, and measurement and governance across the whole journey to CXOps. No standard defines this boundary; it is a way to teach each part once.
- Not ITOps. The internal IT service desk uses the same queueing maths and similar tools, but it serves employees, works inside IT service management practices (incident, request, problem, change), and is taught on ITOps.
- Not incident management. When production is down, an incident commander runs the response on IncidentOps. SupportOps runs the customer side: mass-ticket handling, status messages and the link between hundreds of tickets and one engineering incident.
- Not the knowledge practice. Support is the largest producer and consumer of knowledge, but Knowledge-Centered Service (KCS) and article lifecycle are taught on KnowledgeOps. This page owns the self-service channel and its deflection metrics.
Where SupportOps comes from and where it sits
Link to section “Where SupportOps comes from and where it sits”Origins and evolution
Link to section “Origins and evolution”The practices are older than the label. Telephone call centres created the core problem (random arrivals, expensive staff, a promise about waiting time) and an academic field grew around it: forecasting, staffing, scheduling and routing are a well-studied area of operations research.[2] The staffing mathematics goes back to A. K. Erlang’s work on telephone traffic; a 2007 survey notes that the square-root safety-staffing rule “was first observed by Erlang (1948) and was later formalized by Halfin and Whitt (1981)”.[2] Professional bodies grew up around the support centre: HDI’s support-centre manager course, for example, covers service level management, performance results and workforce management.[3] International standards followed for contact centres (ISO 18295, 2017) and for complaints handling (ISO 10002).[4][5]
Three shifts produced the modern support operations role: software helpdesks turned every ticket into timestamped data, so clocks and routing became configuration; digital and asynchronous channels broke the single phone queue into many queues with different clocks; and technical products put support next to engineering, so someone had to own that interface.
The job title followed: GitLab’s public handbook, for example, shows a “Support Operations” unit and a team that owns the support tooling, now called “Customer Support Systems” (see Use case 1).[6][7]
Glossary and mental model
Link to section “Glossary and mental model”| Term | Meaning | Why it matters |
|---|---|---|
| Ticket / case / conversation | One customer request and its history | The unit of work |
| Triage | Classifying a request: type, product area, priority, language | Wrong triage means wrong queue and wrong clock |
| Routing | Assigning work to a queue or agent by rules (skills, capacity, priority) | Who works on what, in which order |
| Tier (L0–L3) | L0 self-service, L1 front line, L2 specialists, L3 engineering or product experts | Each tier adds a queue |
| Swarming | Bringing the right people to a case instead of escalating it through tiers | Alternative to tiers for complex work |
| SLA policy | Targets per priority for reply, update and resolution clocks | The promise, encoded in the tool |
| OLA | Operational level agreement between internal teams (for example support and engineering) | Makes the internal half of an SLA visible |
| First reply time (FRT) | Time from creation to first public reply (tools differ on what counts) | The most common SLA metric |
| Requester wait time | Time the customer is waiting for you (pauses while you wait for them) | Close to the customer’s experience |
| AHT | Average handle time: talk or work time plus wrap-up per contact | Drives staffing directly |
| Offered load | Arrivals per minute × AHT in minutes, in erlangs | The minimum number of busy agents the work needs |
| Service level (SL) | Share of contacts answered within a target time, such as 80% in 20 seconds | The live-channel clock; its definition matters |
| Shrinkage | Paid time when agents cannot take contacts (breaks, training, absence) | Turns “agents needed” into “agents to schedule” |
| Occupancy | Handling time ÷ (handling time + idle time) | Too high burns people out; too low wastes money |
| FCR | First contact resolution: solved without the customer coming back | Hard to measure; best proxied by re-contact |
| Deflection | A customer solving the problem without creating a ticket | Easy to over-claim; measure with re-contact |
| Macro, trigger, automation | Saved reply; event-driven rule; time-driven rule | Consistency, and where hidden behaviour lives |
| Backlog | Open tickets waiting for agent action, usually with an age profile | The asynchronous waiting queue |
| WFM | Workforce management: forecasting, staffing, scheduling, intraday control | The capacity half of SupportOps |
A mental model: a queue, a clock and a loop
Link to section “A mental model: a queue, a clock and a loop”- Queue. Requests arrive at random; capacity is people × time. When arrivals briefly exceed capacity a queue forms, so every design question (how many people, pooled or specialised queues) is a queueing question first.
- Clock. Each ticket carries clocks with start, pause and stop rules. The SLA is the promise; the clock definition decides whether you can see if you kept it.
- Loop. Every ticket is evidence about a defect, a confusing screen, a missing article or a wrong forecast; SupportOps turns it into fixes, articles and better forecasts.
How SupportOps relates to other Ops
Link to section “How SupportOps relates to other Ops”Diagram source (Mermaid)
flowchart TB CX["CXOps: journey-wide feedback, survey design"] SUP["SupportOps: tickets, SLAs, routing, staffing"] CO["CustomerOps: health, renewals, success plans"] KO["KnowledgeOps: KCS articles, runbooks"] INC["IncidentOps: production incidents"] PR["Product and engineering"] IT["ITOps: internal IT service desk"] CX -->|survey method| SUP SUP -->|ticket insight| CX SUP -->|escalations, risk signals| CO SUP <-->|capture and reuse| KO INC -->|status, ETA| SUP SUP -->|bugs, requests| PR IT -.->|shared queueing maths| SUP classDef core fill:#e8f3f2,stroke:#16756f,color:#122029 classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029 class SUP core class CX,CO,KO,INC,PR,IT neutral
Text equivalent: SupportOps sits in the middle. CXOps supplies survey method and receives ticket insight. SupportOps sends escalations and risk signals to CustomerOps, exchanges knowledge with KnowledgeOps (capturing articles while solving and reusing them), receives status and estimated fix times from IncidentOps during outages, and sends bugs and feature requests to product and engineering. ITOps is a sibling that uses the same queueing maths for internal users (dashed line).
| Neighbour | Shared scope | SupportOps focus | Neighbour’s focus | Hand-off |
|---|---|---|---|---|
| CustomerOps | Existing customers | Reactive requests, SLAs | Health scores, renewals, success plans | Ticket trends and escalations feed health scores |
| CXOps | CSAT and feedback | Transactional CSAT after a ticket | Survey design, NPS/CES, journey-wide loop | CXOps sets method; SupportOps applies it |
| KnowledgeOps | Articles, KCS | Self-service channel, deflection metrics | Knowledge lifecycle, KCS practice | Agents capture and improve articles in the flow of work |
| IncidentOps | Outages | Mass tickets, customer status, problem linking | Incident command, mitigation, reviews | Liaison role; one incident ↔ many tickets |
| ITOps | Ticket queues, SLAs | External customers | Internal IT service desk, ITSM practices | Same staffing maths; different users and processes |
| RevOps | Customer data in the CRM | Support data model, entitlements | Revenue definitions, GTM stack decision rights | Entitlements and account data flow from the CRM |
| ChatOps | Chat-driven work | Customer messaging channels | Operating systems through team chat | Escalation alerts often land in team chat |
| LLMOps | AI answers | Governance of AI agents in support | Operating LLM applications (evaluation, retrieval) | SupportOps sets resolution and safety rules; LLMOps runs the system |
Principles and operating model
Link to section “Principles and operating model”Charter and principles
Link to section “Charter and principles”The charter below is this Atlas’s proposal; no industry body publishes one for SupportOps.
Principles, each with the trade-off it accepts:
- Define the clock before you set the target. Start, pause and stop rules, business or calendar hours, and what counts as a reply are written down before anyone promises “four hours”. Trade-off: slower first SLA launch.
- Pool capacity unless a skill really differs. Queueing maths rewards pooling (Lab 2); split queues only for language, regulated data or genuinely different skills. Trade-off: some loss of specialisation.
- Measure outcomes the customer would recognise. Re-contact and requester wait time beat “tickets closed” and “assumed resolutions”. Trade-off: harder data work.
- Every rule has an owner and a reason. Triggers, automations, macros and routing rules are changed through a change log, like code. Trade-off: some admin overhead.
- Protect people from the maths. Occupancy near 100% is possible only briefly; schedules that assume it burn out the team.[8] Trade-off: higher cost per contact.
- Escalation is an interface, not a favour: template, severity rubric, internal target and feedback channel. Trade-off: engineering must agree to an OLA.
- Automation must be reversible and visible. Every bot or macro answer can reach a human, and every automated close can be reopened. Trade-off: lower headline deflection.
Fundamentals and building blocks
Link to section “Fundamentals and building blocks”| Building block | What it contains | Typical owner |
|---|---|---|
| Channel and intake design | Which channels exist, hours, forms and required fields, identity and entitlement lookup | SupportOps with support leadership |
| Taxonomy | Ticket types, product areas, reasons, priorities, tags | SupportOps (data owner) |
| Routing and queues | Skills, groups, capacity rules, queue order, overflow | SupportOps |
| SLA and OLA policies | Targets per priority and customer tier; internal targets with engineering | Support leadership approves; SupportOps encodes |
| Workforce management | Forecasts, staffing models, schedules, intraday adjustments | WFM analyst (inside SupportOps or alongside) |
| Agent tooling | Macros, side panels, integrations (CRM, billing, issue tracker), AI assistance | SupportOps / support tooling engineers |
| Self-service and AI agents | Help centre, community, bots, their hand-off rules | SupportOps with KnowledgeOps |
| Quality assurance | Scorecards, sampling, calibration, coaching inputs | QA lead |
| Data and reporting | Metric dictionary, dashboards, warehouse exports | SupportOps analyst |
| Change management | Requests, testing in a sandbox, release notes, rollback | SupportOps |
Roles, ownership and RACI
Link to section “Roles, ownership and RACI”Common roles (titles vary): support operations manager; systems administrator or analyst for the helpdesk; support tooling engineer (integrations, scripts, apps); WFM analyst (forecasting and scheduling); QA lead; support data analyst; trainer. Use case 1 shows how one company documents the systems part.
The RACI below is this Atlas’s proposal for a mid-sized organisation (R = responsible, A = accountable, C = consulted, I = informed).
| Activity | Support ops mgr | WFM analyst | Helpdesk admin | Support team leads | Head of support | Engineering lead |
|---|---|---|---|---|---|---|
| SLA policy targets | R | C | C | C | A | I |
| Encoding SLAs and clocks in the tool | A | I | R | I | I | I |
| Volume forecast and staffing plan | C | R | I | C | A | I |
| Schedules and intraday changes | I | R | I | A | I | I |
| Routing rules and skills | A | C | R | C | I | I |
| Macros and automations | A | I | R | C | I | I |
| Escalation template and OLA | R | I | C | C | A | C |
| Bug triage of escalations | C | I | I | C | I | A, R |
| QA scorecard and calibration | A | I | I | R | C | I |
| Metric dictionary and dashboards | A, R | C | C | C | I | I |
| AI agent rules and hand-offs | A, R | C | R | C | C | C |
The engineering lead is accountable for triaging escalations because only engineering can decide what a defect is; support is accountable for the quality of the escalation it sends.
The ticket lifecycle
Link to section “The ticket lifecycle”Most helpdesks use a variant of the same statuses. Zendesk’s are New, Open, Pending (waiting for the customer), On-hold (waiting for a third party), Solved and Closed, and its SLA metrics are defined by which statuses each clock counts.[9][10]
Diagram source (Mermaid)
stateDiagram-v2 [*] --> New: arrives New --> Open: picked up Open --> Pending: ask customer Pending --> Open Open --> OnHold: third party OnHold --> Open Open --> Solved Solved --> Open: reopen Solved --> Closed: after N days Closed --> [*]
Text equivalent: a request arrives as New and becomes Open when an agent picks it up. From Open it can go to Pending when the agent asks the customer something (back to Open when the customer replies), to On-hold while waiting on a third party such as engineering (back to Open when answered), or to Solved when the agent solves it. Unlabelled arrows are these returns and the solve. A solved ticket can be reopened by the customer or closes automatically after a set number of days. In Zendesk’s definitions, requester wait time counts New, Open and On-hold; agent work time counts New and Open; total resolution time counts everything until Solved.
The lifecycle matters because each status is also a clock rule. In Zendesk, requester wait time “starts when the ticket is created and stops once the ticket is solved. It pauses when the ticket has a Pending status”, while total resolution time does not pause except in Solved.[9] A team that parks tickets in Pending to stop a clock improves one metric and harms the customer; the assurance checks later on this page look for exactly that.
Operating model and governance
Link to section “Operating model and governance”A workable cadence (this Atlas’s proposal; adjust to volume):
| Cadence | Forum | Inputs | Decisions |
|---|---|---|---|
| Every 15–30 minutes (live channels) | Intraday check | Arrivals vs forecast, queue length, agents available | Move people between channels, delay breaks, open overflow |
| Daily | Queue stand-up | Backlog by age and priority, breaches, escalations waiting | Reassign, swarm, chase engineering |
| Weekly | Support operations review | SLA attainment, re-contact, QA, forecast error, top contact reasons | Staffing changes, routing fixes, top-5 problem list to product |
| Monthly | Service review with engineering and product | Escalation volume and age, defect themes, deflection results | OLA changes, bug priority, article gaps |
| Quarterly | Capacity and SLA planning | Forecast, hiring lead time, price/plan changes | Headcount, SLA tiers, channel hours |
Architecture and workflow
Link to section “Architecture and workflow”Reference architecture
Link to section “Reference architecture”The architecture below is a process-and-systems view, vendor-neutral. Boxes are capabilities; one product may provide several.
Diagram source (Mermaid)
flowchart TB CH["Channels: email, form, chat, phone, in-app"] ID["Intake: identity, account, entitlement"] SS["Self-service and AI agent"] TR["Triage: type, product area, priority"] RT["Routing: skills, capacity, queue order"] AG["Agents: L1 front line, L2 specialists"] ESC["Escalation to engineering issue tracker"] KB["Knowledge base"] WFM["Workforce management: forecast, schedule"] AN["Data and reporting: metric dictionary"] CH --> ID ID --> SS SS -->|needs a human| TR TR --> RT RT --> AG AG -->|defect or expert need| ESC ESC -->|fix, workaround| AG KB --> SS AG -->|capture, improve| KB WFM -->|staffed capacity| RT AG -->|events, timestamps| AN AN -->|actuals| WFM classDef core fill:#e8f3f2,stroke:#16756f,color:#122029 classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029 class TR,RT,WFM,AN core class CH,ID,SS,AG,ESC,KB neutral
Text equivalent: requests arrive through channels and pass intake, which identifies the customer and their entitlement. Self-service and an AI agent try the knowledge base; anything needing a human goes to triage and then routing, which uses skills, staffed capacity and queue order to assign an agent. Agents escalate defects to the engineering issue tracker and get fixes or workarounds back, and they improve knowledge articles. Workforce management supplies staffed capacity to routing; events flow to data and reporting, whose actuals feed the next forecast. Triage, routing, workforce management and data are highlighted as the capabilities SupportOps designs most directly.
Design notes for each component:
- Intake should resolve identity and entitlement before routing. Routing by plan or contract needs that data, and the SLA policy usually depends on it.
- Triage can be done by form design, rules, agents or a classifier; whatever does it, the taxonomy must stay small enough to be used consistently.
- Routing decides which queue (skills, language, customer tier) and which order inside it (oldest first, priority, or nearest SLA breach); see the triage and routing playbook.
- Escalation crosses a trust and tooling boundary. The support ticket stays the customer-facing record; the engineering issue is the defect record; they are linked, and the support side owns customer communication.
- Reporting needs the event history (status changes with timestamps), not just the final state of each ticket; SLA clocks and re-contact cannot be rebuilt from final states.
Alternatives. A small team can run everything inside one helpdesk. A large or regulated operation often adds a WFM platform, a QA tool and a data warehouse, and manages the helpdesk configuration as versioned code. Outsourced front lines add a second organisation and an ISO 18295-2-style client relationship.[11]
End-to-end workflow: happy path and exception path
Link to section “End-to-end workflow: happy path and exception path”Diagram source (Mermaid)
%%{init: {"sequence": {"actorMargin": 24, "width": 110, "messageMargin": 30, "noteMargin": 6, "diagramMarginX": 8}}}%%
sequenceDiagram
autonumber
participant B as AI agent
participant C as Customer
participant A as L1 agent
participant S as L2 expert
participant E as Engineering
C->>B: problem
B->>C: article
C->>B: not solved
Note over B,A: hand-off + transcript to L1
A->>C: asks for logs
C->>A: logs
A->>S: escalates
S->>E: files defect
E-->>S: workaround
S-->>A: workaround, ETA
A->>C: workaround, ETA
E-->>S: fix shipped
S-->>A: fix live
A->>C: confirms, solves
Text equivalent: the customer describes a problem to an AI agent, which suggests an article. The customer says it is still broken, so the AI agent hands the conversation to the L1 agent with the transcript on the ticket (the note in the diagram). The L1 agent sends the first reply and asks for logs; the customer sends them. The L1 agent escalates to an L2 expert (a specialist) using the escalation template, and the specialist files a defect in engineering’s tracker linked to the ticket. Engineering returns a workaround now and a fix in a later release; the specialist passes this to the L1 agent, who gives the customer the workaround and an expectation. When the fix ships, engineering tells the specialist, the specialist tells the L1 agent, and the L1 agent confirms with the customer and solves the ticket.
Happy path. Most tickets never leave L1: routed to the right skill, answered with a reviewed macro or article, solved in one or two exchanges, not reopened.
Exception paths SupportOps must design explicitly:
| Exception | Detection | Designed response |
|---|---|---|
| Bot cannot help, customer asks for a person | Hand-off intent, repeated question, negative sentiment | Hand-off with transcript; no forced loop back to the bot |
| Ticket in the wrong queue | Agent re-routes; re-route rate per category | Fix the triage rule; measure re-routes weekly |
| SLA about to breach | Clock alert (time-based automation) | Notify lead; queue ordering by nearest breach |
| Many tickets about one cause | Spike in a category; agent flags | Link as incidents to one problem ticket; status message; see IncidentOps |
| Engineering does not answer | Escalation age past OLA | Escalate to engineering manager; visible in the monthly service review |
| Customer goes silent while Pending | Pending age | Reminder automation, then solve with a reopen window |
For mass issues, Zendesk’s problem/incident model is a concrete mechanism: link each incident ticket to one problem ticket, and solving the problem solves the linked incidents and copies the solving comment; Zendesk advises to “Refrain from solving any of the incident tickets directly”.[12]
Capacity: the queueing maths behind every SLA
Link to section “Capacity: the queueing maths behind every SLA”This part is the centre of gravity of the page. Most support arguments (“we need more people”, “the SLA is unrealistic”, “AI will halve the team”) are capacity questions, and they can be answered with a few formulas and honest inputs.
Offered load, Little’s law and the shape of demand
Link to section “Offered load, Little’s law and the shape of demand”Offered load is the arrival rate multiplied by the average handle time, in the same time unit. Koole’s call-centre handbook describes it as “the number of agents needed to be able to handle all incoming calls” if nothing were random; because arrivals cluster and handle times vary, you need more.[8] Example from that book: 100 contacts forecast for a 15-minute interval with an AHT of 3 minutes 30 seconds gives λ = 100 ÷ 15 = 6.67 contacts per minute and a load of 6.67 × 3.5 = 23.33 erlangs, so at least 24 agents must be busy just to keep up.[8]
Little’s law links the three quantities every backlog report shows: L = λW, where L is the average number of items in the system, λ the average arrival rate and W the average time an item spends in the system.[13] It is a theorem, not a rule of thumb, and it needs no assumption about the arrival pattern. For support it gives two quick checks:
- 400 tickets a day that each stay open 1.5 days on average imply an average backlog of 600 open tickets.
- To bring the average time open down to 0.5 days at the same arrival rate, the average backlog must fall to 200. A team that says “we will cut resolution time by two-thirds” without planning to hold one-third of today’s backlog has not yet made a plan.
Demand has shape. Volumes follow time-of-day, day-of-week and annual patterns, plus events (releases, outages, billing runs, holidays). In a textbook data set of five-minute call volumes to a North American commercial bank, Hyndman and Athanasopoulos show a strong daily pattern and a weaker weekly one, with Mondays tending to be busier.[14] Staffing therefore works per interval (usually 15 or 30 minutes), not per day.[8]
Erlang C: from load to agents
Link to section “Erlang C: from load to agents”The Erlang C model (a queue with Poisson arrivals, meaning contacts arrive randomly and independently at a steady average rate; exponential handle times; identical agents; first come first served; no hang-ups) gives the probability that a contact waits, the average speed of answer (ASA) and the service level for a given number of agents.[2] In words: compute the load A; for N agents above A, the probability of waiting P(wait) comes from the Erlang C formula; the share answered within t is 1 − P(wait) × e^(−(N − A) × t ÷ AHT); and ASA = P(wait) × AHT ÷ (N − A). Lab 2 implements it in about twenty lines and reproduces Koole’s numbers.
For Koole’s example (load 23.33 erlangs), Lab 2 gives 20.6% answered within 20 seconds with 24 agents, 62.0% with 26 and 83.0% with 28; Koole reports “only around 21%” at 24 agents and that 28 agents are needed for 80% in 20 seconds.[8]
Four lessons follow, all visible in Lab 2:
- The cliff. With 24 agents (just above the load) the queue barely works; four more agents change service from terrible to good. Small staffing errors at high load produce large service errors.
- Non-linear sensitivity. A 10% longer AHT moves the requirement from 28 to 31 agents; 20% more volume moves it to 33.
- Pooling. Two separate queues of 50 contacts per interval need 30 agents in total; one shared queue needs 28. Every split (by product, by plan, by language) costs capacity; split only when the skill or the rule really differs.
- Economies of scale. At the same 80/20 target, 25 contacts per interval need 9 agents (65% occupancy) and 1,000 need 243 (96% occupancy). The safety margin grows roughly with the square root of the load, the “square-root safety-staffing rule” that operations research traces from Erlang to Halfin and Whitt.[2] Large pools reach occupancy people cannot sustain for long; Koole notes that occupancy near 100% “can only occur for short periods”.[8]
Service level: one name, several formulas
Link to section “Service level: one name, several formulas”“80% answered within 20 seconds” is so common that Koole calls it the “industry standard” in quotation marks, while noting that other targets are possible.[8] What matters more is the formula. Koole gives three ways to count abandoned contacts in the service level and a worked example: 510 contacts, 460 answered (410 within 20 seconds), 50 abandoned (30 of them within 20 seconds) give 89%, 85% or 80% depending on the definition.[8] The first definition ignores abandoned calls; it “clearly gives a perverse incentive” because a long-waiting caller who hangs up improves the number.[8] Write the formula into the metric dictionary and report the abandonment rate next to it. Koole reports that abandonment limits are “often in the order of 3 or 5%”; treat that as common practice, not a target.[8]
Shrinkage, occupancy and schedules
Link to section “Shrinkage, occupancy and schedules”Erlang C answers “how many agents must be available in this interval”. People also take breaks, attend training and coaching, are sick or on holiday. Shrinkage is the share of paid time not available for contacts; Koole writes that “A shrinkage of 40% is not exceptional”.[8]
- Agents to schedule = agents needed ÷ (1 − shrinkage). With 28 needed and 35% shrinkage, schedule ⌈28 ÷ 0.65⌉ = 44.
- Occupancy = handling time ÷ (handling time + available idle time).[8] It falls out of the staffing, so it should be monitored rather than targeted: pushing occupancy up by under-staffing degrades service and wears people out.
- Koole also points out a trap: lower first contact resolution raises occupancy, because repeat contacts fill the idle time.[8] Occupancy that rises while re-contact rises is bad news dressed as efficiency.
Schedules turn interval requirements into shifts, breaks and days off. Doing this well (part-time shifts, split shifts, break placement, overtime rules, labour law, preferences) is the job WFM software and analysts exist for; the mathematics is covered in the operations research literature on scheduling and rostering.[2]
Diagram source (Mermaid)
flowchart TB H["History: volume and AHT per interval"] F["Forecast: volume and AHT, with events"] R["Required agents per interval (Erlang C, simulation, workload)"] SH["Add shrinkage: agents to schedule"] SC["Schedule: shifts, breaks, skills"] ID["Intraday: compare actuals, adjust"] V["Variance review: forecast error, adherence"] H --> F F --> R R --> SH SH --> SC SC --> ID ID --> V V -->|update models and events| H classDef core fill:#e8f3f2,stroke:#16756f,color:#122029 classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029 class F,R,SH,SC core class ID,V decision
Text equivalent: history of volume and handle time per interval feeds a forecast that includes known events. The forecast turns into required agents per interval (Erlang C for live channels, simulation or workload calculations otherwise), then into agents to schedule after shrinkage, then into a schedule of shifts, breaks and skills. During the day, intraday management compares actuals with the plan and adjusts. A variance review measures forecast error and schedule adherence and updates the models and event list, which closes the loop back to history.
Asynchronous work: email, forms and backlog
Link to section “Asynchronous work: email, forms and backlog”Erlang C fits contacts that wait in a live queue for seconds or minutes. Email and web-form tickets wait for hours, and agents can defer them, so the working model is workload plus a backlog constraint:
- Workload hours = tickets × AHT. Example: 1,200 emails a week at 9 minutes = 180 hours.
- Productive hours per agent = contracted hours × (1 − shrinkage) × the share of available time you can realistically spend on tickets. Example: 40 × 0.65 × 0.85 ≈ 22.1 hours, so 180 ÷ 22.1 ≈ 8.1, which rounds up to 9 agents for the average week.
- Check the clock, not just the average: if the SLA is a first reply within 8 business hours, the team must clear each morning’s overnight arrivals before they age out. Model the hourly arrivals against hourly capacity, or simulate.
- Check the backlog with Little’s law: if 240 tickets arrive per business day and the target average time to first reply is 4 business hours (half a day), the average number awaiting a first reply must stay near 120.
Blended agents (live chat plus email) let email absorb idle time between chats; Koole’s book treats channel blending as its own staffing problem.[8] The risk of blending is that email clocks breach silently whenever chat is busy; give email its own clock alerts.
Global coverage. Customers in several time zones raise two design choices. Follow-the-sun pools one queue across regional teams, which gains the pooling effect above, but needs a written handover (open urgent tickets, promised updates, live incidents) at each shift change. Regional queues keep language and local hours, at the cost of smaller pools. Either way, business-hour clocks need the right time zone and holiday calendar per region: in Zendesk, a schedule has one time zone, holidays count as outside business hours, and more than one schedule needs an Enterprise plan (as of October 2026).[15]
Forecasting demand
Link to section “Forecasting demand”A support forecast is a time series with several seasonalities and many interventions. Practical guidance:
- Forecast volume and AHT separately, per channel and per interval; AHT changes with product releases and new agents.
- Keep an event calendar: releases, price changes, billing runs, marketing campaigns, known outages, holidays. Most large forecast misses in support are events nobody told the WFM analyst about.
- Start with simple, explainable methods (seasonal naive, exponential smoothing, regression with event dummies) and measure them; Forecasting: Principles and Practice covers these and multiple seasonality with a call-centre example.[14]
- Track forecast error and bias per interval and per day. A forecast that is right on average but wrong at 9:00 on Mondays still breaches the SLA at 9:00 on Mondays.
- Forecast the effect of deflection conservatively (Lab 3 shows claimed deflection overstating real deflection).
Practices, frameworks and tools
Link to section “Practices, frameworks and tools”Core practices and playbooks
Link to section “Core practices and playbooks”Each playbook lists the goal, the steps and the acceptance criteria. Owners follow the RACI above.
Playbook: triage and routing
Link to section “Playbook: triage and routing”Goal: every ticket reaches the right queue with the right priority within minutes, without agents cherry-picking.
- Design the intake form first: required fields for product area and impact, a severity question in customer language (“Is your production system down?”), attachments for logs. Every field you require removes a triage step; every field you add lowers completion.
- Keep the taxonomy small: one contact-reason field with 15–40 values, owned by SupportOps, reviewed quarterly. A reason list with 300 values is not used consistently, so it measures nothing.
- Write a priority rubric in observable terms (impact × urgency), not in emotions. Example: urgent = production unusable for many users with no workaround; high = major function impaired, workaround exists; normal = question or minor defect; low = feedback.
- Encode routing: queue by skill and language, order by nearest SLA breach for queues with SLAs, assign by spare capacity or round robin; set a skills timeout so that, once it expires, a ticket can go to agents without the optional skills instead of waiting for the one expert. In Zendesk, required skills never time out; the defaults are one hour for email and 30 seconds for messaging and calls, in calendar hours; skills-based routing needs a Professional plan or above, and ordering by SLA breach a Team plan or above (as of October 2026).[16]
- Measure re-routes (tickets moved between groups) by reason; a high re-route rate for one category means the rule or the form is wrong.
Acceptance: re-route rate stable and low; no queue where the oldest ticket is much older than its SLA; agents rarely choose their own tickets.
Playbook: SLA policy design
Link to section “Playbook: SLA policy design”Goal: a promise customers understand, measured by a clock that cannot be gamed.
- Pick the metrics. First reply time is the usual starting point. For resolution, Zendesk’s guidance is to “Pick only one resolution time metric” among requester wait time, agent work time and total resolution time.[9] Add a periodic-update target for long-running tickets so customers are not left in silence.
- Define the clock. Business or calendar hours per priority (urgent tickets usually run on calendar hours); which statuses pause it; what stops it. In Jira Service Management these are explicit start, pause and stop conditions.[17]
- Decide what counts as a reply. Tools disagree. In Zendesk, first reply time ends at the first public comment from an agent “(or autoreply)”; Zendesk notes that reply-time metrics are fulfilled by a trigger that autoreplies with a public comment, and that “Autoreplies are available with the Copilot add-on only”. SLA policies themselves need Suite Growth or Support Professional and above (as of October 2026).[9] Freshdesk does not count replies sent by its automation “Send Reply” action, which are “treated as system-generated messages rather than agent responses”.[18] An autoreply that stops the SLA clock measures your autoreply, not your service (Lab 1 shows attainment jumping from 5/8 to 8/8).
- Make priority reliable. In Zendesk, SLA targets depend on the system Priority field; a ticket with no priority gets no SLA, so a trigger should set one at creation.[9]
- Order policies from most to least restrictive when a tool applies the first match.[9]
- Pair the SLA with an OLA for escalations: if support promises a periodic update every 24 hours on urgent defects, engineering must commit to an internal update cadence.
- Report attainment with open tickets included. Tickets still waiting past target are breaches now, not when they are finally answered.
Acceptance: written clock definition per metric; a sample of 20 tickets re-timed by hand matches the tool; breached-but-open tickets appear on the daily report.
Playbook: macros, triggers and automations
Link to section “Playbook: macros, triggers and automations”Goal: consistency without hidden behaviour.
- Know the two engines. In Zendesk, ticket triggers “run every time a ticket is created or updated”, while automations are time-based and “run every hour on all your tickets that are not closed”.[19] Order and conditions matter: two triggers that both set priority will fight.
- Naming and ownership: prefix by purpose (
route.,notify.,sla.), one owner per rule, a one-line reason in the description, and a change log entry for every edit. - Test before production: use a sandbox or a test brand with synthetic tickets that exercise each path; keep the test cases.
- Review macros on a schedule. A macro is a cached answer; when the product changes, it is wrong in hundreds of replies at once. Give each macro an owner or article, review usage quarterly and retire unused ones. Prefer fewer, explicit rules: if nobody can explain why a ticket was routed somewhere, the rules have outgrown their governance.
Playbook: self-service and deflection
Link to section “Playbook: self-service and deflection”Goal: customers solve what they can solve alone, and reach a person easily when they cannot.
Gartner reported in 2019 that “Only 9% of customers report resolving their issues completely via self-service”, and that its poll of service leaders found live channels cost an average of $8.01 per contact against about $0.10 for self-service; it advised managing self-service “like a product”.[20] The figures are from 2019 and have not been re-measured here; this Atlas treats them as directional design guidance: self-service is cheap per contact but often incomplete, so its quality decides whether it saves money or just adds a step before the ticket.
- Start from contact reasons: the top ten reasons by volume are the self-service backlog.
- Write or fix articles with the agents who answer those tickets; the knowledge practice behind this (KCS) is on KnowledgeOps.
- Put search and suggested articles in the contact form, not only in a help-centre homepage.
- Measure deflection honestly: a session counts only if the customer does not contact you on the same topic within a window (seven days is common). Report claimed and verified deflection side by side (Lab 3).
- Keep a visible way to reach a person. Hiding the contact option raises measured deflection and lowers trust.
Playbook: quality assurance
Link to section “Playbook: quality assurance”Goal: catch what clocks miss: wrong answers, poor tone, policy breaches, missed escalations.
- A scorecard of 5–8 criteria tied to outcomes (template in Templates).
- Sampling: random per agent per week, plus targeted samples (reopened tickets, low CSAT, escalations, AI agent hand-offs).
- Calibration: reviewers score the same tickets monthly and discuss differences; without calibration, QA scores measure the reviewer.
- Use for coaching and system fixes, not only for individual ratings. A criterion that fails across many agents points to a macro, a policy or a product problem.
Playbook: escalation to engineering
Link to section “Playbook: escalation to engineering”Goal: engineers get reproducible problems once; customers get honest updates.
- Template (see Templates) with impact, linked tickets, reproduction steps and requested severity.
- Severity rubric shared with engineering, and an OLA for acknowledgement and update cadence per severity.
- One defect, many tickets: link tickets to the engineering issue (and in Zendesk to one problem ticket), so the fix can be communicated to all affected customers at once.[12]
- Feedback both ways: engineering marks “not a defect / needs more info / duplicate” with a reason; SupportOps tracks the rejection rate per team as a quality signal for escalations.
- Top-problems list to product monthly, ranked by tickets, customer impact and time spent, not by who shouts loudest.
Playbook: tiers or swarming
Link to section “Playbook: tiers or swarming”Tiers (L1 front line, L2 specialists, L3 engineering) are the default. The Consortium for Service Innovation, which advocates the alternative called Intelligent Swarming, says the tiered model is efficient “if the majority (95% or more) of issues are simple and known, and resolved during the customer’s first contact”, and that tiers create “organizational silos and handoffs/escalations that inhibit the exchange of information and knowledge” and multiple queues.[21] Swarming keeps one owner per case and brings skilled people to it instead of passing it down a chain.
| Choose tiers when | Choose swarming (or a hybrid) when |
|---|---|
| Most issues are known and repeatable | Many issues are new, complex or span products |
| Front-line turnover is high and training is short | Experts are few and needed across queues |
| Cost per contact is the main constraint | Time to resolution of hard cases is the main constraint |
| Outsourced L1 with clear scope | In-house teams with shared tooling and culture |
A hybrid is common: tiered handling for known issues, swarming for new or high-impact cases. The decision framework includes this choice.
Methods, standards and frameworks
Link to section “Methods, standards and frameworks”Separate what is normative (you must comply because you chose to be certified or a contract requires it) from frameworks (optional practice guidance) and models (mathematics).
| Item | Type | What it covers | Use it for |
|---|---|---|---|
| ISO 18295-1:2017 | International standard (certifiable) | “service requirements for customer contact centres”, in-house and outsourced, all channels; specifies KPIs “as and where required”; confirmed in 2023[4] | Contact-centre management system and audits |
| ISO 18295-2:2017 | International standard | Requirements for organisations using contact-centre services[11] | Contracting and governing outsourced support |
| ISO 10002:2018 | International guidelines | “guidelines for the process of complaints handling”[5] | Complaint process design |
| COPC CX Standard | Proprietary industry standard | “a performance management system used to improve operations that support the customer experience”;[22] Release 8.0 (current as of October 2026) adds “New requirements for AI ethics, technology planning, and performance verification”, and all certifications use it from January 2027[23] | Performance management, outsourcer certification, governance of AI agents |
| KCS v6 | Practice framework (Consortium for Service Innovation) | Solve Loop and Evolve Loop for knowledge in service work[24] | Knowledge capture and reuse; taught on KnowledgeOps |
| Intelligent Swarming | Practice framework (same Consortium) | Collaboration model replacing tiered escalation[21] | Complex-case handling |
| Queueing models (Erlang C, Erlang A, Little’s law) | Mathematics | Staffing, waiting, backlog[2][13] | Capacity planning |
| ITIL 4 practices | IT service management framework | Incident, problem, request, service desk | Internal IT service desks; see ITOps |
None of these defines “SupportOps”. ISO 18295 is the closest thing to a requirement set for a contact centre; the standard’s full text is paid and was not read for this page, so no clause-level claims are made here.
Tooling landscape
Link to section “Tooling landscape”Vendor-neutral categories first, examples second. Product names are examples verified to exist (as of October 2026), not recommendations; no prices are compared except where quoted from the vendor with a date.
| Category | Job it does | Examples | Selection criteria | Lock-in and risk |
|---|---|---|---|---|
| Helpdesk / ticketing | Tickets, channels, SLA clocks, business rules, macros, reporting | Zendesk, Freshdesk, Jira Service Management, Salesforce Service Cloud, HubSpot Service Hub, Help Scout; open source Zammad (AGPL-3.0), osTicket (GPL-2.0), FreeScout (AGPL-3.0), Chatwoot[25][26][27][28] | Clock definitions match yours; API and export of full event history; sandbox; routing model | Configuration lives in the vendor; export rules, macros and history regularly |
| Routing and WFM | Forecasts, schedules, intraday, capacity-aware routing | Helpdesk-native routing (for example Zendesk omnichannel routing; Jira Service Management Workforce Management); dedicated WFM suites (for example NICE, Verint, Calabrio, Assembled)[16][29] | Interval granularity, multi-skill support, schedule rules for your labour law | Forecast models can be opaque; keep your own baseline |
| Knowledge and self-service | Help centre, community, search, article lifecycle | Helpdesk-native help centres, documentation platforms | Search quality, analytics on failed searches, link from tickets to articles | Content portability (export format) |
| AI agents and agent assist | Automated answers, drafting, summarisation, classification | Helpdesk-native AI, Intercom Fin, others | Definition of “resolution”, hand-off quality, audit logs, data use terms | Outcome-based pricing ties cost to the vendor’s definition |
| Data and analytics | Warehouse, metric dictionary, dashboards | Warehouse plus BI; see AnalyticsOps | Event-level data, not only snapshots | Metric definitions drifting between tools |
Capability claims need dates: Atlassian documents that Jira Service Management’s Workforce Management routes work using each agent’s “capacity, shift schedule, and availability”, that some features need Premium or Enterprise plans, that the feature “is not HIPAA compliant”, and that its routing is “a basic AI feature that consumes Rovo credits”.[29] Intercom’s pricing page offers “Fin AI Agent on all plans for $0.99 per outcome” and, when Fin runs on another helpdesk, notes “Minimum monthly commitment applies (e.g. 50 outcomes)” (as of 2026-10-23).[30]
Automation and AI
Link to section “Automation and AI”The operational question is not “should we use AI” but “which work, measured how, with which guardrails”.
What the evidence says.
- Assisting agents. In a study of 5,172 customer support agents at one firm, access to a generative-AI assistant raised issues resolved per hour by 15% on average. Less experienced and lower-skilled agents gained in both speed and quality, while the most experienced and highest-skilled saw “small gains in speed and small declines in quality”.[31] (The 2023 working-paper version reported 14% and 5,179 agents.) One firm, one tool: assistance seems to help most where training time is short, and assisted answers from experienced agents still need QA sampling.
- Replacing conversations. Klarna’s 2024 claims for its AI assistant and its 2025 return to hiring human staff are set out in Use case 2. Read together, they describe a hybrid, not a full replacement.
What “resolution” means. Vendors define it. Intercom counts a resolution when, after Fin’s last answer, the customer either confirms the answer or “exits the conversation without requesting further assistance (assumed resolution)”; a resolution is deducted if the customer returns to the same conversation.[32] A customer who gives up and emails instead does not return to it, so measure AI agents with the same re-contact window as self-service (Lab 3: a claimed 87.5% falls to 50%).
Accountability. A tribunal has held a company responsible for its chatbot’s wrong answer (Use case 3); the general point is covered on LLMOps. Treat AI answers on policy, prices, refunds and legal rights as company statements.
Transparency (EU). Article 50(1) of the EU AI Act requires providers to design AI systems that interact directly with people so that those people are informed they are interacting with an AI system, unless that is obvious in context; it applies from 2 August 2026, and a law-firm alert reports it was not delayed by the 2026 AI Omnibus amendment.[33][34] A provider develops the system, or has it developed, and places it on the market or puts it into service under its own name or trademark.[35] A team running a vendor’s agent is normally a deployer and the vendor carries this duty; a company that builds its own agent, or runs one under its own name, may be the provider. Disclose AI either way as good practice. This is orientation for the EU, not legal advice.
Guardrails SupportOps owns (this Atlas’s proposal):
| Guardrail | Why | How to check |
|---|---|---|
| Disclosed as AI; human reachable in one step | Trust; EU AI Act Art. 50(1) where you are the provider | Test script monthly; count “agent” requests that loop |
| Topics the AI must not answer alone (refunds, legal, safety, account security) | Liability (Use case 3) | Hand-off rules; QA sample of AI transcripts |
| Answers grounded in approved, current articles | Stale knowledge becomes confident errors | Article freshness; citation to source in transcript |
| Resolution measured by re-contact, not vendor outcome | Vendor definitions include “assumed” outcomes | Lab 3 method weekly |
| Every automated action reversible and logged | Errors at scale | Audit log review; reopen path |
| Cost per verified resolution, not per claimed resolution | Outcome pricing follows vendor counts | Monthly reconciliation |
Organisations certified to the COPC standard will also meet its Release 8.0 AI-governance requirements.[23] Operating the language-model system itself (evaluation sets, retrieval quality, prompt changes) is covered on LLMOps; SupportOps sets the business rules and measures the service.
SupportOps in practice
Link to section “SupportOps in practice”Reference implementation: operating artefacts
Link to section “Reference implementation: operating artefacts”The artefacts below are the minimum written system for a support operation of roughly 10–100 people. They are this Atlas’s templates; field names in Artefact 1 follow Zendesk’s published API, everything else is tool-neutral.
Artefact 1: an SLA policy as code (Zendesk API)
Link to section “Artefact 1: an SLA policy as code (Zendesk API)”Keeping SLA policies in version control makes the clock definition reviewable. Zendesk’s SLA Policies API accepts a JSON object
with a filter (all/any conditions) and policy_metrics (priority, metric, target in minutes, business hours or not); it is
available to administrators on Support Professional or Suite Growth plans and above (as of October 2026).[36]
Save the JSON below as sla-policy.json. It covers every ticket type on tickets tagged plan_standard (set, for example, by a
trigger at creation; the tag name is this example’s choice); current_tags with includes is listed in Zendesk’s conditions
reference.[37] Zendesk’s own API example filters on ticket type Incident, which would leave Questions,
Problems and Tasks with no SLA.
Example status: JSON syntax-checked; not executed (requires a Zendesk account and an OAuth token).
{
"sla_policy": {
"title": "Standard plan - all ticket types",
"description": "First reply by priority; periodic updates for urgent tickets",
"filter": {
"all": [
{ "field": "current_tags", "operator": "includes", "value": "plan_standard" }
],
"any": []
},
"policy_metrics": [
{ "priority": "urgent", "metric": "first_reply_time", "target": 60,
"business_hours": false },
{ "priority": "high", "metric": "first_reply_time", "target": 240,
"business_hours": true },
{ "priority": "normal", "metric": "first_reply_time", "target": 480,
"business_hours": true },
{ "priority": "low", "metric": "first_reply_time", "target": 960,
"business_hours": true },
{ "priority": "urgent", "metric": "periodic_update_time", "target": 240,
"business_hours": false },
{ "priority": "urgent", "metric": "requester_wait_time", "target": 1440,
"business_hours": false }
]
}
}
Example status: bash syntax-checked; not executed. Needs an admin’s OAuth access token limited to the sla_policies:write
scope (for OAuth clients created on or after 30 April 2026, access tokens expire after 30 minutes by default).[38] Replace
example with your subdomain; keep the token in an environment variable, never in the repository; run it against a sandbox
first.
# Create the policy from the reviewed file (token in ZENDESK_TOKEN); --fail-with-body
# (curl 7.76+) makes an HTTP error fail the script and still prints Zendesk's message
curl --fail-with-body "https://example.zendesk.com/api/v2/slas/policies" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${ZENDESK_TOKEN}" \
-X POST -d @sla-policy.json
Review points before applying: treat a created policy as live for matching tickets; it is matched at the list position you give
(the last position if omitted);[36] tickets that match no policy get no SLA at all, so end the list with a catch-all policy
(for example current_tags not_includes an exemption tag); the policy only applies to tickets that have a system Priority
value, so a trigger must set one; policies apply in order, most restrictive first; autoreplies count as replies for Zendesk
reply-time metrics, so decide whether your autoreply should exist at all.[9]
Artefact 2: a metric dictionary
Link to section “Artefact 2: a metric dictionary”One file defines every number on the dashboard. Tool-neutral YAML; the validator checks its syntax.
Example status: YAML syntax-checked; definitions are this Atlas’s proposal.
metrics:
- id: frt_attainment
name: First reply SLA attainment
formula: tickets_with_first_agent_reply_within_target / tickets_due_in_period
includes_open_breaches: true # unanswered tickets past target count as misses
autoreply_counts: false
clock: per priority (urgent calendar hours; others business hours)
owner: support-ops
- id: recontact_7d
name: Re-contact within 7 days
formula: solved_contacts_followed_by_same_customer_same_reason_7d / solved_contacts
applies_to: [agent, ai_agent, self_service]
owner: support-ops
- id: requester_wait_p80
name: Requester wait time, 80th percentile (hours)
formula: p80(time in new, open, on-hold until solved)
owner: support-ops
- id: backlog_age
name: Open tickets by age bucket
buckets_days: [0-1, 2-3, 4-7, 8-14, 15+]
owner: support-ops
- id: csat_transactional
name: Transactional CSAT
formula: good_ratings / all_ratings
report_with: [response_rate, interval_95, n]
survey_design_owner: cxops
- id: service_level_live
name: Live-channel service level (SL2)
formula: answered_within_t / (answered + abandoned_after_t)
t_seconds: 20
report_with: [abandon_rate, asa_seconds]
owner: wfm
- id: cost_per_resolved
name: Cost per resolved contact, by channel
formula: (people + platform + vendor cost) / contacts_resolved_without_recontact
owner: support-ops
Artefact 3: priority rubric and routing rules (tool-neutral)
Link to section “Artefact 3: priority rubric and routing rules (tool-neutral)”Example status: YAML syntax-checked; illustrative configuration to translate into your helpdesk’s rule engine.
priority_rubric: # impact x urgency, written in observable terms
urgent: "Production unusable for many users, no workaround"
high: "Major function impaired or one user blocked; workaround exists"
normal: "Question, minor defect, configuration help"
low: "Feedback, feature request, cosmetic issue"
routing:
queue_order: nearest_sla_breach # alternatives: oldest_first, priority_first
assignment: most_spare_capacity # alternative: round_robin
rules: # first match wins
- when: {contract: enterprise, priority: urgent}
queue: l2-critical
notify: [support-manager-on-call]
- when: {language: de}
queue: l1-german
- when: {reason: billing}
queue: l1-billing
overflow_after_minutes: 30 # design choice, not Zendesk: then l1-general
- when: {}
queue: l1-general
capacity:
email_open_tickets_per_agent: 12
chat_concurrent_per_agent: 2
Artefact 4: intake form for a technical product
Link to section “Artefact 4: intake form for a technical product”| Field | Type | Required | Why |
|---|---|---|---|
| Product area | Pick list (10–20 values) | Yes | Routing and reporting |
| What were you trying to do? | Text | Yes | Intent, for triage and search |
| What happened instead? | Text | Yes | Symptom |
| Is a production system affected? | Yes / No | Yes | Drives priority with the rubric |
| How many users are affected? | One / some / all | Yes | Impact |
| Version or environment | Text or detected | If technical | Reproduction |
| Attachments (logs, screenshots) | Files | No | Saves a round trip |
| Contact preference and time zone | Pick list | No | Clock and follow-up |
The form should search the help centre as the customer types the first two answers; that is the cheapest deflection you can build.
Hands-on labs
Link to section “Hands-on labs”Four labs on synthetic data only: bash, Python 3.8 or later, standard library only, no accounts and no cost. Each lab was run on 2026-10-23 exactly as printed (Python 3.8.10, Ubuntu Linux, scratch directory); the expected outputs are copied from those runs.
Lab 1 (beginner): SLA clocks and what they hide
Link to section “Lab 1 (beginner): SLA clocks and what they hide”Objective. Compute first-reply SLA attainment from a ticket event log in business and calendar hours, see how an autoreply and unanswered tickets change the result, and compute requester wait time with Pending pauses. Prerequisites. bash and Python 3.8+. Time. 25 minutes. Risk. None.
- Create the folder and the data.
Example status: verified by execution on 2026-10-23 (bash, Linux).
mkdir -p ~/supportops-labs/lab1 && cd ~/supportops-labs/lab1
cat > events.csv <<'CSV'
ticket,priority,time,event
T1,urgent,2026-10-12 10:00,created
T1,urgent,2026-10-12 10:00,autoreply
T1,urgent,2026-10-12 10:40,agent_reply
T1,urgent,2026-10-12 10:40,pending
T1,urgent,2026-10-12 13:00,customer_reply
T1,urgent,2026-10-12 13:20,solved
T2,urgent,2026-10-16 16:30,created
T2,urgent,2026-10-16 16:30,autoreply
T2,urgent,2026-10-16 18:10,agent_reply
T2,urgent,2026-10-16 18:10,solved
T3,normal,2026-10-09 16:00,created
T3,normal,2026-10-09 16:00,autoreply
T3,normal,2026-10-12 10:00,agent_reply
T3,normal,2026-10-12 10:00,solved
T4,normal,2026-10-13 09:30,created
T4,normal,2026-10-13 15:00,agent_reply
T4,normal,2026-10-13 15:00,pending
T4,normal,2026-10-14 10:00,customer_reply
T4,normal,2026-10-14 10:30,solved
T5,normal,2026-10-14 08:00,created
T5,normal,2026-10-14 09:20,agent_reply
T5,normal,2026-10-14 09:20,solved
T6,high,2026-10-15 11:00,created
T6,high,2026-10-15 11:00,autoreply
T6,high,2026-10-15 15:30,agent_reply
T6,high,2026-10-15 15:30,solved
T7,low,2026-10-10 12:00,created
T7,low,2026-10-12 11:00,agent_reply
T7,low,2026-10-12 11:00,solved
T8,normal,2026-10-15 16:50,created
T8,normal,2026-10-15 16:50,autoreply
CSV
- Save the script as
sla.py.
Example status: verified by execution on 2026-10-23 (Python 3.8.10, standard library).
"""First-reply SLA and requester wait time from a ticket event log."""
import csv
from collections import defaultdict
from datetime import datetime, timedelta
SNAPSHOT = datetime(2026, 10, 16, 17, 0) # report run on Friday 17:00
OPEN, CLOSE = 9, 17 # business hours, Mon-Fri, one time zone
TARGETS = { # priority: (minutes, clock)
"urgent": (60, "calendar"),
"high": (240, "business"),
"normal": (480, "business"),
"low": (960, "business"),
}
def business_minutes(start, end):
total, day = 0, start.replace(hour=0, minute=0)
while day < end:
if day.weekday() < 5:
lo = max(start, day.replace(hour=OPEN))
hi = min(end, day.replace(hour=CLOSE))
total += max(0, (hi - lo).total_seconds() / 60)
day += timedelta(days=1)
return int(total)
def elapsed(start, end, clock):
if clock == "calendar":
return int((end - start).total_seconds() / 60)
return business_minutes(start, end)
tickets = defaultdict(list)
with open("events.csv", newline="") as f:
for r in csv.DictReader(f):
when = datetime.strptime(r["time"], "%Y-%m-%d %H:%M")
tickets[r["ticket"]].append((when, r["event"], r["priority"]))
met_agent = met_auto = met_closed_only = closed = 0
not_due = set() # no agent reply yet and still inside target: not yet due
print("ticket prio clock target agent-FRT result autoreply-counts")
for tid, ev in sorted(tickets.items()):
ev.sort()
created, prio = ev[0][0], ev[0][2]
target, clock = TARGETS[prio]
agent = next((t for t, e, _ in ev if e == "agent_reply"), None)
auto = next((t for t, e, _ in ev if e in ("autoreply", "agent_reply")), None)
frt = elapsed(created, agent or SNAPSHOT, clock)
ok = frt <= target
result = ("met" if ok else "BREACH") if agent else ("running" if ok else "BREACH*")
if result == "running":
not_due.add(tid)
print(f"{tid:6} {prio:7} {clock:9} {target:6} {frt:9} {result}")
continue
ok_auto = auto is not None and elapsed(created, auto, clock) <= target
met_agent += ok
met_auto += ok_auto
if agent:
closed += 1
met_closed_only += ok
print(f"{tid:6} {prio:7} {clock:9} {target:6} {frt:9} {result:8} "
f"{'met' if ok_auto else 'BREACH'}")
n = len(tickets) - len(not_due) # tickets due: replied, or past target unanswered
print(f"\nNot yet due (running), left out of every rate : {len(not_due)}")
print(f"Attainment, agent reply, open breaches counted: {met_agent}/{n}")
print(f"Attainment, replied tickets only : {met_closed_only}/{closed}")
print(f"Attainment, autoreply counts as a reply : {met_auto}/{n}")
cal = sum(elapsed(ev[0][0], next((t for t, e, _ in ev if e == "agent_reply"), SNAPSHOT),
"calendar") <= TARGETS[ev[0][2]][0]
for tid, ev in tickets.items() if tid not in not_due)
print(f"Attainment, every target on a calendar clock : {cal}/{n}")
print("\nResolution clocks for solved tickets (calendar minutes)")
for tid, ev in sorted(tickets.items()):
if ev[-1][1] != "solved":
continue
waiting, wait, last = True, 0, ev[0][0]
for t, e, _ in ev:
if waiting:
wait += (t - last).total_seconds() / 60
if e == "pending":
waiting = False
elif e == "customer_reply":
waiting = True
last = t
total = (ev[-1][0] - ev[0][0]).total_seconds() / 60
if total != wait:
print(f"{tid}: total resolution {int(total)}, requester wait {int(wait)}")
- Run
python3 sla.py.
Expected output.
ticket prio clock target agent-FRT result autoreply-counts
T1 urgent calendar 60 40 met met
T2 urgent calendar 60 100 BREACH met
T3 normal business 480 120 met met
T4 normal business 480 330 met met
T5 normal business 480 20 met met
T6 high business 240 270 BREACH met
T7 low business 960 120 met met
T8 normal business 480 490 BREACH* met
Not yet due (running), left out of every rate : 0
Attainment, agent reply, open breaches counted: 5/8
Attainment, replied tickets only : 5/7
Attainment, autoreply counts as a reply : 8/8
Attainment, every target on a calendar clock : 3/8
Resolution clocks for solved tickets (calendar minutes)
T1: total resolution 200, requester wait 60
T4: total resolution 1500, requester wait 360
Validation. Check three tickets by hand. T3 was created on Friday 9 October at 16:00 and answered on Monday at 10:00: one
business hour on Friday plus one on Monday is 120 minutes, although 66 calendar hours passed. T6 waited 4.5 business hours against a
4-hour target: a breach, which the autoreply hides. T8 has no human reply at the Friday 17:00 snapshot; 490 business minutes have
already passed, so it is a breach now (BREACH*), and a report that only counts replied tickets (5/7) hides it. T1’s requester wait
time is 40 minutes before Pending plus 20 after the customer’s reply: 60 of 200 calendar minutes.
What to notice. The same eight tickets give 5/8, 5/7, 8/8 or 3/8 depending on four definitional choices. Agree the definition
before the target. An unanswered ticket still inside its target is running: not yet due, so the script leaves it out of every
rate, as the metric dictionary’s tickets_due_in_period does (the synthetic data has none; add one to see it).
Troubleshooting. ValueError: time data ... does not match format: a timestamp is not YYYY-MM-DD HH:MM. KeyError on a
priority: add it to TARGETS. Holidays are not modelled; real business-hour clocks need a holiday calendar and the customer’s or
team’s time zone.
Teardown. rm -rf ~/supportops-labs/lab1
Lab 2 (intermediate): Erlang C staffing, shrinkage and pooling
Link to section “Lab 2 (intermediate): Erlang C staffing, shrinkage and pooling”Objective. Turn a forecast into agents for an 80/20 service level, then test shrinkage, pooling, handle-time and volume sensitivity and scale. Prerequisites. Python 3.8+. Time. 20 minutes. Risk. None.
-
Create the folder:
mkdir -p ~/supportops-labs/lab2 && cd ~/supportops-labs/lab2. -
Save the script as
erlang.py.
Example status: verified by execution on 2026-10-23 (Python 3.8.10, standard library).
"""Erlang C staffing for one queue of live contacts (standard library only)."""
import math
def erlang_c(n, a):
"""Probability that an arriving contact has to wait: n agents, a erlangs."""
if n <= a:
return 1.0
b = 1.0 # Erlang B, built up with the stable recursion
for k in range(1, n + 1):
b = a * b / (k + a * b)
return n * b / (n - a * (1 - b))
def service_level(n, a, aht, t):
"""Share of contacts answered within t (t and aht in the same unit)."""
if n <= a:
return 0.0
return 1 - erlang_c(n, a) * math.exp(-(n - a) * t / aht)
def asa(n, a, aht):
"""Average speed of answer (mean wait, all contacts)."""
return erlang_c(n, a) * aht / (n - a) if n > a else float("inf")
def agents_needed(a, aht, t, target):
n = math.floor(a) + 1
while service_level(n, a, aht, t) < target:
n += 1
return n
VOLUME, INTERVAL_MIN = 100, 15 # contacts forecast for one 15-minute interval
AHT_MIN, T_MIN = 3.5, 20 / 60 # handle time 3:30; answer target 20 seconds
TARGET, SHRINKAGE = 0.80, 0.35 # 80/20 service level; 35% shrinkage
a = VOLUME / INTERVAL_MIN * AHT_MIN
print(f"Offered load: {a:.2f} erlangs")
print(" agents P(wait) SL(20s) ASA(s) occupancy")
for n in range(24, 31):
print(f"{n:6d} {erlang_c(n, a):7.1%} {service_level(n, a, AHT_MIN, T_MIN):7.1%}"
f" {asa(n, a, AHT_MIN) * 60:6.1f} {a / n:9.1%}")
n = agents_needed(a, AHT_MIN, T_MIN, TARGET)
print(f"Agents on the phones for 80/20: {n}")
scheduled = math.ceil(n / (1 - SHRINKAGE))
print(f"Agents to schedule at {SHRINKAGE:.0%} shrinkage: {scheduled}")
half = a / 2
split = 2 * agents_needed(half, AHT_MIN, T_MIN, TARGET)
print(f"Pooling: two separate queues of 50 need {split}; one pooled queue needs {n}")
a_slow = a * 1.10
print(f"AHT +10% (3:51): {agents_needed(a_slow, AHT_MIN * 1.10, T_MIN, TARGET)} agents")
a_peak = a * 1.20
peak = agents_needed(a_peak, AHT_MIN, T_MIN, TARGET)
print(f"Volume +20% (120 contacts): {peak} agents")
print("Scale (80/20, AHT 3:30): contacts per 15 min -> agents, occupancy")
for volume in (25, 50, 100, 200, 400, 1000):
load = volume / INTERVAL_MIN * AHT_MIN
need = agents_needed(load, AHT_MIN, T_MIN, TARGET)
print(f" {volume:5d} -> {need:4d} agents, occupancy {load / need:.1%}")
- Run
python3 erlang.py.
Expected output.
Offered load: 23.33 erlangs
agents P(wait) SL(20s) ASA(s) occupancy
24 84.6% 20.6% 266.4 97.2%
25 64.9% 44.6% 81.8 93.3%
26 49.0% 62.0% 38.6 89.7%
27 36.4% 74.4% 20.8 86.4%
28 26.5% 83.0% 11.9 83.3%
29 18.9% 89.0% 7.0 80.5%
30 13.2% 93.0% 4.2 77.8%
Agents on the phones for 80/20: 28
Agents to schedule at 35% shrinkage: 44
Pooling: two separate queues of 50 need 30; one pooled queue needs 28
AHT +10% (3:51): 31 agents
Volume +20% (120 contacts): 33 agents
Scale (80/20, AHT 3:30): contacts per 15 min -> agents, occupancy
25 -> 9 agents, occupancy 64.8%
50 -> 15 agents, occupancy 77.8%
100 -> 28 agents, occupancy 83.3%
200 -> 53 agents, occupancy 88.1%
400 -> 101 agents, occupancy 92.4%
1000 -> 243 agents, occupancy 96.0%
Validation. The load is 100 ÷ 15 × 3.5 = 23.33 erlangs. Koole’s handbook reports for the same inputs “only around 21%” answered within 20 seconds at 24 agents and 28 agents for 80%;[8] the script gives 20.6% and 28. Schedule check: 28 ÷ (1 − 0.35) = 43.08, rounded up to 44.
Troubleshooting. ZeroDivisionError or an endless loop: the number of agents must exceed the load; the function starts above
it. For multi-skill queues, chats handled concurrently or strong abandonment, Erlang C is the wrong model (Lab 4).
Teardown. rm -rf ~/supportops-labs/lab2
Lab 3 (intermediate): claimed versus verified resolution, re-contact and CSAT
Link to section “Lab 3 (intermediate): claimed versus verified resolution, re-contact and CSAT”Objective. From a ticket export, compare an AI agent’s vendor-style resolution rate with resolutions that held for seven days, and compute one-touch resolution, reopen and re-contact rates, CSAT with its uncertainty, and backlog age. Prerequisites. bash and Python 3.8+. Time. 30 minutes. Risk. None.
- Create the folder and the data.
Example status: verified by execution on 2026-10-23 (bash, Linux).
mkdir -p ~/supportops-labs/lab3 && cd ~/supportops-labs/lab3
cat > tickets.csv <<'CSV'
id,customer,topic,channel,handler,bot_outcome,created,solved,replies,reopened,csat
1,C01,login,chat,bot,assumed,2026-09-01,2026-09-01,0,0,
2,C01,login,email,agent,,2026-09-02,2026-09-02,1,0,good
3,C02,billing,email,agent,,2026-09-01,2026-09-03,2,0,good
4,C03,export,chat,bot,confirmed,2026-09-02,2026-09-02,0,0,
5,C04,api,email,agent,,2026-09-02,2026-09-05,3,1,bad
6,C05,login,chat,bot,assumed,2026-09-03,2026-09-03,0,0,
7,C06,billing,chat,bot,assumed,2026-09-03,2026-09-03,0,0,
8,C06,billing,phone,agent,,2026-09-04,2026-09-04,1,0,bad
9,C07,export,email,agent,,2026-09-04,2026-09-04,1,0,good
10,C08,api,email,agent,,2026-09-07,2026-09-09,2,0,
11,C09,login,chat,bot,escalated,2026-09-07,2026-09-07,0,0,
12,C09,login,chat,agent,,2026-09-07,2026-09-07,1,0,good
13,C10,billing,email,agent,,2026-09-08,2026-09-08,1,1,
14,C11,export,chat,bot,assumed,2026-09-08,2026-09-08,0,0,
15,C12,api,chat,bot,confirmed,2026-09-09,2026-09-09,0,0,
16,C12,api,email,agent,,2026-09-20,2026-09-21,1,0,good
17,C13,login,email,agent,,2026-09-10,2026-09-10,1,0,good
18,C05,login,email,agent,,2026-09-08,2026-09-08,2,0,bad
19,C14,billing,email,agent,,2026-09-11,,1,0,
20,C02,export,email,agent,,2026-09-14,,2,0,
21,C03,api,phone,agent,,2026-09-21,,0,0,
22,C07,login,chat,bot,assumed,2026-09-22,2026-09-22,0,0,
23,C04,billing,email,agent,,2026-09-24,2026-09-25,1,0,good
24,C11,export,email,agent,,2026-09-25,2026-09-25,1,0,
25,C13,login,email,agent,,2026-09-15,2026-09-15,1,0,good
CSV
- Save the script as
metrics.py.
Example status: verified by execution on 2026-10-23 (Python 3.8.10, standard library).
"""Support metrics from a ticket export: what the headline numbers hide."""
import csv
import math
from datetime import date
SNAPSHOT = date(2026, 9, 30)
WINDOW = 7 # days: a new contact on the same topic within this window = re-contact
with open("tickets.csv", newline="") as f:
rows = list(csv.DictReader(f))
for r in rows:
r["created"] = date.fromisoformat(r["created"])
r["solved"] = date.fromisoformat(r["solved"]) if r["solved"] else None
def recontacted(r):
"""Same customer, same topic, new contact within WINDOW days after this one ended."""
end = r["solved"] or r["created"]
later = lambda o: (o["created"], int(o["id"])) > (r["created"], int(r["id"]))
return any(later(o) and o["customer"] == r["customer"] and o["topic"] == r["topic"]
and 0 <= (o["created"] - end).days <= WINDOW for o in rows)
def wilson(k, n, z=1.96):
if n == 0:
return (0.0, 0.0)
p = k / n
centre = (p + z * z / (2 * n)) / (1 + z * z / n)
half = z * math.sqrt(p * (1 - p) / n + z * z / (4 * n * n)) / (1 + z * z / n)
return centre - half, centre + half
def pct(k, n):
return f"{k}/{n} = {100 * k / n:.1f}%" if n else "n/a"
bot = [r for r in rows if r["handler"] == "bot"]
claimed = [r for r in bot if r["bot_outcome"] in ("confirmed", "assumed")]
held = [r for r in claimed if not recontacted(r)]
print("AI agent")
print(f" {'Vendor-style resolution rate':29}: {pct(len(claimed), len(bot))}")
print(f" {f'No re-contact within {WINDOW} days':29}: {pct(len(held), len(bot))}")
back = [r["id"] for r in claimed if recontacted(r)]
print(f" {'Re-contacted resolutions':29}: {back}")
agent = [r for r in rows if r["handler"] == "agent"]
solved = [r for r in agent if r["solved"]]
one_touch = [r for r in solved if r["replies"] == "1" and r["reopened"] == "0"]
reopened = [r for r in solved if r["reopened"] == "1"]
recon = [r for r in solved if recontacted(r)]
print("Human-handled tickets")
print(f" {'One-touch resolution':29}: {pct(len(one_touch), len(solved))}")
print(f" {'Reopened':29}: {pct(len(reopened), len(solved))}")
print(f" {f'Re-contact within {WINDOW} days':29}: {pct(len(recon), len(solved))}")
rated = [r for r in solved if r["csat"]]
good = sum(r["csat"] == "good" for r in rated)
lo, hi = wilson(good, len(rated))
print(f" {'CSAT (good / rated)':29}: {pct(good, len(rated))}, "
f"95% interval {100 * lo:.1f}%-{100 * hi:.1f}%")
print(f" {'Survey response rate':29}: {pct(len(rated), len(solved))}")
backlog = [r for r in agent if not r["solved"]]
buckets = {"0-7 days": 0, "8-14 days": 0, "15+ days": 0}
for r in backlog:
age = (SNAPSHOT - r["created"]).days
key = "0-7 days" if age <= 7 else "8-14 days" if age <= 14 else "15+ days"
buckets[key] += 1
print(f"Backlog on {SNAPSHOT}: {len(backlog)} open, by age {buckets}")
- Run
python3 metrics.py.
Expected output.
AI agent
Vendor-style resolution rate : 7/8 = 87.5%
No re-contact within 7 days : 4/8 = 50.0%
Re-contacted resolutions : ['1', '6', '7']
Human-handled tickets
One-touch resolution : 9/14 = 64.3%
Reopened : 2/14 = 14.3%
Re-contact within 7 days : 1/14 = 7.1%
CSAT (good / rated) : 8/11 = 72.7%, 95% interval 43.4%-90.3%
Survey response rate : 11/14 = 78.6%
Backlog on 2026-09-30: 3 open, by age {'0-7 days': 0, '8-14 days': 1, '15+ days': 2}
Validation. By hand: bot conversations 1, 6 and 7 were counted as resolved (all three as assumed resolutions) but the same customers came back on the same topic one, five and one days later on another channel (tickets 2, 18 and 8). Conversation 15’s customer came back after 11 days, outside the window. On the human side, ticket 17’s customer came back five days later (ticket 25). Eleven of fourteen solved tickets were rated, eight good: 72.7%, but with only eleven ratings the 95% Wilson interval (a range for a proportion that stays sensible at small n) runs from 43% to 90%, so a week-on-week change of ten points means nothing at this volume.
What to notice. An “assumed resolution” (the customer left without asking for more help) is not evidence that the problem was solved.[32] Measure every automated channel with the same re-contact rule.
Troubleshooting. Real exports need timestamps, not dates, to order same-day contacts (the script breaks ties by ticket id), and a stable customer key across channels; without one, re-contact is under-counted.
Teardown. rm -rf ~/supportops-labs/lab3
Lab 4 (advanced): test Erlang C against a simulation with abandonment
Link to section “Lab 4 (advanced): test Erlang C against a simulation with abandonment”Objective. Simulate the Lab 2 queue call by call, confirm that the simulation matches Erlang C when nobody hangs up, then add impatient callers and see how far the model’s answer moves. Prerequisites. Lab 2. Time. 30 minutes. Risk. None (runs in about a second).
-
Create the folder:
mkdir -p ~/supportops-labs/lab4 && cd ~/supportops-labs/lab4. -
Save the script as
simulate.py.
Example status: verified by execution on 2026-10-23 (Python 3.8.10, standard library).
"""Check the Erlang C answer by simulation, with and without callers who hang up."""
import heapq
import math
import random
RATE = 100 / 15 # arrivals per minute (100 per 15 minutes)
AHT = 3.5 # mean handle time, minutes
T = 20 / 60 # answer target: 20 seconds
CALLS = 200_000
def erlang_c_sl(n, a):
b = 1.0
for k in range(1, n + 1):
b = a * b / (k + a * b)
c = n * b / (n - a * (1 - b))
return 1 - c * math.exp(-(n - a) * T / AHT)
def simulate(agents, mean_patience, seed=7):
"""First-come-first-served queue; a caller whose wait exceeds patience hangs up."""
rng = random.Random(seed)
free = [0.0] * agents # time at which each agent becomes free
clock = 0.0
answered = answered_in_t = abandoned = abandoned_after_t = 0
wait_sum = 0.0
for _ in range(CALLS):
clock += rng.expovariate(RATE)
patience = rng.expovariate(1 / mean_patience) if mean_patience else math.inf
service = rng.expovariate(1 / AHT)
wait = max(0.0, free[0] - clock)
if wait > patience:
abandoned += 1
abandoned_after_t += patience > T
continue
start = clock + wait
heapq.heapreplace(free, start + service)
answered += 1
answered_in_t += wait <= T
wait_sum += wait
sl2 = answered_in_t / (answered + abandoned_after_t) # Koole's SL2 definition
return sl2, abandoned / CALLS, 60 * wait_sum / answered
a = RATE * AHT
print("agents patience SL(20s) abandoned ASA(s) Erlang C SL")
for agents in (26, 28):
for patience in (None, 3.0, 1.0):
sl, ab, asa = simulate(agents, patience)
label = "infinite" if patience is None else f"{patience:.0f} min"
print(f"{agents:6d} {label:8} {sl:7.1%} {ab:9.1%} {asa:6.1f} "
f"{erlang_c_sl(agents, a):10.1%}")
- Run
python3 simulate.py.
Expected output.
agents patience SL(20s) abandoned ASA(s) Erlang C SL
26 infinite 62.6% 0.0% 41.0 62.0%
26 3 min 85.0% 4.2% 6.9 62.0%
26 1 min 93.3% 5.8% 2.9 62.0%
28 infinite 83.4% 0.0% 11.5 83.0%
28 3 min 92.0% 2.2% 3.6 83.0%
28 1 min 96.5% 3.3% 1.6 83.0%
Validation. With infinite patience the simulated service level is within one point of Erlang C (62.6% vs 62.0%, 83.4% vs 83.0%); that confirms the simulation. The fixed seed makes the output repeatable on the same Python version; other versions may differ in the last digit.
What to notice. With a three-minute mean patience, 26 agents reach 85% in 20 seconds, because 4.2% of callers hang up and stop loading the queue. That is the over-staffing Erlang C can produce when callers abandon,[2][8] and also a warning: the “better” service level is bought with hang-ups, many of whom call back (redials are not simulated here).
Troubleshooting. Slow on very old hardware: reduce CALLS to 50,000 (results move by a few tenths of a point). To model time-
varying arrivals, simulate each 15-minute interval with its own rate and carry the queue over.
Teardown. rm -rf ~/supportops-labs
Use cases and scenarios
Link to section “Use cases and scenarios”Three documented cases and two illustrative scenarios. The documented cases are described only as far as their public sources go.
Use case 1: support operations as a systems team at GitLab (documented)
Link to section “Use case 1: support operations as a systems team at GitLab (documented)”Context. In GitLab’s public handbook, Support is accounted for as Cost of Sales; support engineers are “not commissioned or bonused” for upsell; KPIs are reviewed weekly in a “Support Week-in-Review”.[6] The handbook’s naming guide shows a “Support Operations” unit inside “Support Readiness”, and the team that owns the tooling now appears as “Customer Support Systems”.[6][7]
Method. The systems team states its purpose (knowledge, tools and data for the support team), accepts changes only through templates filed by specific roles (“issues filed outside the appropriate role will be closed”), publishes a triage → plan or develop → validate → implement flow, and keeps pages on audits and change management.[7] It also publishes the definitions it uses for each Zendesk clock.[10]
Trade-offs. Restricting who can request changes slows small fixes but stops the helpdesk becoming a pile of one-off rules.
What to copy. A written purpose, a single intake for helpdesk changes, validation before release, and a public metric dictionary. What not to infer. Nothing on the public pages shows GitLab’s SLA attainment or staffing; do not quote this case as evidence of results.
Use case 2: an AI assistant at Klarna, and the human channel (documented, company claims)
Link to section “Use case 2: an AI assistant at Klarna, and the human channel (documented, company claims)”Context. Klarna said in February 2024 that its AI assistant had “2.3 million conversations, two-thirds of Klarna’s customer service chats” in its first month, doing “the equivalent work of 700 full-time agents”, with customer satisfaction “on par with human agents”, “a 25% drop in repeat inquiries” and resolution in under 2 minutes instead of 11; it estimated a $40 million profit improvement for 2024.[39] In May 2025 its CEO told Bloomberg, as reported by Entrepreneur, “I just think it’s so critical that you are clear to your customer that there will always be a human if you want”, and Klarna was recruiting human customer service staff again.[40]
Trade-offs and lessons. The 2024 figures are self-reported and the public sources do not say how “resolution” or “repeat inquiry” was measured. The 2025 statement moves the question from replacement to access: how reliably a customer reaches a person. Transferable practice: report AI performance by re-contact and hand-off quality, keep the human path visible, and plan staffing for the possibility that the contacts AI leaves behind are harder and longer, which would raise AHT for the human queue (an expectation to measure, not a sourced finding).
Use case 3: accountability for chatbot answers at Air Canada (documented, legal decision)
Link to section “Use case 3: accountability for chatbot answers at Air Canada (documented, legal decision)”Context. In Moffatt v. Air Canada (2024 BCCRT 149, 14 February 2024), a customer relied on the airline’s website chatbot, which wrongly suggested that a bereavement fare could be claimed retroactively. The British Columbia Civil Resolution Tribunal found the airline liable for negligent misrepresentation. It rejected the argument that the chatbot was responsible for its own actions: the chatbot “is still just a part of Air Canada’s website”, and “It should be obvious to Air Canada that it is responsible for all the information on its website”; it found that “Air Canada did not take reasonable care to ensure its chatbot was accurate”.[41]
Lesson for SupportOps. Treat policy answers from automation as official statements: restrict AI agents to approved, current sources for refunds, prices and rights; route such topics to humans or to deterministic flows; keep transcripts; review a sample in QA. This is a single small-claims decision in one Canadian province; it is persuasive as an example, not binding law elsewhere.
Scenario 4: a launch week that nearly doubles chat volume (illustrative)
Link to section “Scenario 4: a launch week that nearly doubles chat volume (illustrative)”Pitfall. Planning the average day; the peak interval decides the service.
Scenario 5: plan-based SLAs and an OLA with engineering (illustrative)
Link to section “Scenario 5: plan-based SLAs and an OLA with engineering (illustrative)”Pitfall. Selling an SLA before the clock, the on-call rota and the OLA exist; the first breach is then a contract issue.
Measure, govern, pay
Link to section “Measure, govern, pay”Metrics and KPIs
Link to section “Metrics and KPIs”Measure the queue, the clock and the loop. Each KPI below has a formula; definitions live in the metric dictionary (Artefact 2).
| KPI | Definition / formula | Leading or lagging | Pitfall | Review |
|---|---|---|---|---|
| SLA attainment by priority | Tickets meeting target ÷ tickets due, open breaches included | Lagging | Autoreplies, Pending parking, excluding open tickets | Daily, weekly |
| Requester wait time (p50, p80) | Time in New, Open, On-hold until solved | Lagging | Averages hide the long tail; use percentiles | Weekly |
| Backlog by age | Open tickets per age bucket | Leading | A flat count can hide an ageing tail | Daily |
| Live service level and abandonment | SL2 at target seconds; abandoned ÷ offered | Lagging (per interval) | Definition choice (SL1 rewards hang-ups) | Intraday, weekly |
| Re-contact within 7 days | Same customer and reason within 7 days ÷ solved | Lagging | Needs a customer key across channels | Weekly |
| One-touch resolution | Solved with one agent reply and not reopened ÷ solved | Lagging | Rewards premature closing if used alone | Monthly |
| Transactional CSAT | Good ÷ all ratings, with n, response rate and interval | Lagging | Small samples; survivorship; survey design is CXOps | Monthly |
| Forecast error | Mean absolute percentage error per interval and day; bias | Leading | Daily accuracy hides interval misses | Weekly |
| Occupancy and shrinkage | As defined in Capacity | Leading | Targeting occupancy degrades service | Weekly |
| Escalation acceptance and age | Escalations accepted as valid ÷ sent; age vs OLA | Leading | Engineering may close quietly | Monthly |
| Verified automation resolution | Bot or self-service sessions with no re-contact ÷ sessions | Lagging | Vendor “assumed” outcomes | Weekly |
| Cost per resolved contact, by channel | Total cost ÷ contacts resolved without re-contact | Lagging | Allocation choices; never an agent target | Quarterly |
Vanity traps. Tickets closed per agent; average handle time as an individual target (rewards rushing and transfers); deflection without re-contact; CSAT without the number of ratings.
A worked calculation
Link to section “A worked calculation”Quality, security, privacy and compliance
Link to section “Quality, security, privacy and compliance”- Personal data in tickets. Tickets collect names, emails, screenshots and logs, and often more than needed. In the EU/EEA, GDPR’s storage-limitation principle requires personal data to be kept “for no longer than is necessary for the purposes for which the personal data are processed”.[42] Set a retention period per ticket type, automate deletion or redaction, and include attachments and exports in the scope. Wider programme design is on PrivacyOps.
- Payment card data. Do not collect full card numbers in tickets. Zendesk documents a credit-card field (Enterprise plans, as of October 2026) that stores only the last four digits, states that PCI allows storing the first six and last four, and warns that following its recommendations “won’t make your Zendesk PCI-compliant”.[43] Route payment changes to the payment system, not the ticket.
- Least privilege. Contractors and outsourced agents see only their brands, groups and fields; administrators are few; API tokens are scoped and rotated; integrations are reviewed when staff leave.
- Audit trail. Keep the ticket event history and the helpdesk change log; both are evidence in disputes and in audits against ComplianceOps-style controls or ISO 18295 certification.[4]
- AI agents. Disclosure, approved sources and human hand-off, as in Automation and AI.
- Regulated sectors (health, finance, government) add complaint-handling rules, call-recording consent and data residency; check them per jurisdiction.
Cost, capacity and sustainability
Link to section “Cost, capacity and sustainability”People are most of the cost, so the levers are: fewer contacts (fix causes, better self-service), shorter but complete handling (knowledge, tools), less waste (pooling, accurate forecasts, schedules that fit demand) and the right channel for each problem; a self-service attempt that ends in a live contact costs more than either alone. Outcome-priced AI agents add a variable cost tied to the vendor’s definition of an outcome; reconcile it monthly against verified resolutions.[32] Human sustainability is the binding constraint: occupancy targets near 100%, or schedules without coaching time, raise attrition, and new agents have higher AHT, which raises the staffing need again.[8] Environmental impact is usually small; where it matters, see GreenOps.
Assurance of the operating model
Link to section “Assurance of the operating model”| Check | Frequency | Signal of trouble |
|---|---|---|
| Re-time 20 random tickets by hand against the SLA definition | Quarterly | Tool and definition disagree |
| Pending and On-hold use per agent | Weekly | Parking tickets to stop clocks |
| Rules audit: triggers, automations, macros without owner or use | Quarterly | Unknown rules, conflicting priorities |
| Forecast error and bias by interval | Weekly | Repeated misses on the same weekday or event |
| QA calibration spread between reviewers | Monthly | Scores depend on the reviewer |
| AI transcript sample against approved sources | Weekly | Answers outside policy or from stale articles |
| Escalations past OLA | Weekly | Engineering interface broken |
When things go wrong
Link to section “When things go wrong”Common failures and troubleshooting
Link to section “Common failures and troubleshooting”| Symptom | Likely cause | Diagnosis | Remediation | Prevention |
|---|---|---|---|---|
| SLA attainment high, customers angry | Clock stops on autoreply or Pending; open breaches excluded | Re-time a sample (Lab 1) | Fix definitions; report open breaches | Written clock definitions |
| Backlog grows every Monday | Weekend arrivals, weekday staffing | Arrivals and capacity by hour | Weekend or early-Monday cover; stagger | Forecast per interval |
| Hard tickets age, easy ones fly | Cherry-picking, oldest-first not enforced | Age of oldest ticket per queue | Assignment by routing, not choice | Queue order by SLA breach |
| Re-contact rises after a bot launch | Assumed resolutions, poor hand-off | Lab 3 on bot sessions | Hand-off rules; restrict topics | Measure verified resolution |
| Same bug, hundreds of tickets, no fix | No problem linking, no escalation owner | Tickets per defect | Problem ticket, engineering link, status message | Monthly top-problems review |
| Agents leaving, AHT rising | Occupancy too high, no coaching time | Occupancy and shrinkage trend | Add capacity; protect coaching | Occupancy cap in planning |
Worked runbook: a backlog surge after a release
Link to section “Worked runbook: a backlog surge after a release”Diagram source (Mermaid)
flowchart TB
A["Alert: backlog over threshold or SLA breaches rising"]
B{"One main cause?"}
C["Declare mass issue: problem ticket, link incidents"]
D["Status message and macro, engineering link"]
E["Capacity response: overtime, borrow staff, pause low priority"]
F["Recovery plan: clear by age and priority, daily burn-down"]
G["Review: forecast, release calendar, escalation timing"]
A --> B
B -->|yes| C
C --> D
D --> F
B -->|no| E
E --> F
F --> G
classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
class A risk
class B decision
class C,D,E,F,G core
Text equivalent: an alert fires when the backlog passes a threshold or SLA breaches rise. The first decision is whether one cause is behind most new tickets. If yes, declare a mass issue: create a problem ticket, link the incident tickets, publish a status message and macro, and link the engineering issue. If no, respond with capacity: overtime, borrowed staff, pausing low-priority work. Both paths lead to a recovery plan that clears tickets by age and priority with a daily burn-down, and then to a review of the forecast, the release calendar and escalation timing.
Anti-patterns and myths
Link to section “Anti-patterns and myths”- “Average handle time is the productivity metric.” As an individual target it produces rushed answers, transfers and repeat contacts, and low FCR even raises occupancy (see Capacity).[8]
- “Deflection is savings.” Only verified deflection is; the rest is moved or delayed work.
- “AI will replace the team.” The evidence supports assistance and partial automation with a human path; assistance even lowered quality slightly for the most experienced agents in the one large study.[31][40]
- “Support should not bother engineering.” Then engineering hears about defects from churn. Design the interface instead.
Deciding and adopting
Link to section “Deciding and adopting”When to use and when not to use
Link to section “When to use and when not to use”Invest in a SupportOps role or team when several of these hold: more than about ten people answer customers, or more than one channel or time zone; SLAs are sold in contracts; headcount requests cannot be answered from data; the helpdesk has rules nobody can explain; engineering complains about escalation quality or support complains about engineering silence. These thresholds are this Atlas’s judgement, not a researched cut-off.
Do not build a separate team when volume is low and one person can answer and administer; when the product is changing so fast that the real fix is in the product, not the queue; or when support is a short-lived launch function. Give one person the SupportOps hat for a few hours a week instead, using this page’s checklists.
Decision framework
Link to section “Decision framework”Diagram source (Mermaid)
flowchart TB
Q1{"10+ people or several channels?"}
Q2{"Contract SLAs or growing backlog?"}
P["Part-time owner"]
T["Dedicated SupportOps team"]
Q3{"95%+ known, solved on first contact?"}
TI["Tiers plus escalation template"]
SW["Swarming or hybrid"]
Q1 -->|no| P
Q1 -->|yes| Q2
Q2 -->|no| P
Q2 -->|yes| T
T --> Q3
Q3 -->|yes| TI
Q3 -->|no| SW
classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
class Q1,Q2,Q3 decision
class P,T,TI,SW core
Text equivalent: if fewer than about ten people answer customers on few channels, a part-time owner of clocks, taxonomy and checklists is enough. If the team is larger, the next question is whether SLAs are in contracts or the backlog keeps growing; if not, a part-time owner still suffices; if so, build a dedicated SupportOps function covering workforce management, routing, data and change control. That function then chooses a tiered model with a clear escalation template when 95% or more of issues are known and resolved on the first contact (the Consortium for Service Innovation’s condition for tiers), or swarming or a hybrid for new and complex issues.
For choosing tools or an operating model, a weighted comparison keeps the argument honest. Weights are this Atlas’s illustration; set your own before scoring.
| Criterion | Weight | Helpdesk-native only | Helpdesk + WFM suite | Helpdesk + WFM + outsourced L1 |
|---|---|---|---|---|
| Fits volume and channels | 0.25 | 3 | 5 | 5 |
| Clock and routing control | 0.20 | 4 | 5 | 4 |
| Total cost | 0.20 | 5 | 3 | 3 |
| Speed to change | 0.15 | 5 | 4 | 2 |
| Quality control | 0.20 | 4 | 4 | 3 |
| Weighted score | 1.00 | 4.10 | 4.25 | 3.55 |
Scores 1–5 for an illustrative company with three channels and about 40 agents; with 10 agents the first option wins on cost and speed.
Maturity model
Link to section “Maturity model”This is this Atlas’s model, not an industry standard.
Diagram source (Mermaid)
flowchart TB L1["1 Reactive: shared inbox, no clocks"] L2["2 Defined: helpdesk, written SLA clocks, taxonomy"] L3["3 Managed: forecasts, staffing model, QA, metric dictionary"] L4["4 Integrated: escalation OLAs, problem loop, verified automation"] L5["5 Adaptive: interval planning, experiments, causes removed"] L1 --> L2 L2 --> L3 L3 --> L4 L4 --> L5 classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029 classDef core fill:#e8f3f2,stroke:#16756f,color:#122029 class L1,L2 neutral class L3,L4,L5 core
Text equivalent: five levels in sequence. Level 1, reactive: a shared inbox and no clocks. Level 2, defined: a helpdesk, written SLA clocks and a taxonomy. Level 3, managed: forecasts, a staffing model, QA and a metric dictionary. Level 4, integrated: escalation OLAs with engineering, a problem loop and verified automation. Level 5, adaptive: interval-level planning, controlled experiments and measurable removal of contact causes.
| Level | Observable behaviour | Exit criterion to next level |
|---|---|---|
| 1 Reactive | Replies when someone notices; volume unknown | Every request is a ticket with a timestamp |
| 2 Defined | SLA targets exist; definitions written | Re-timed sample matches the tool; open breaches reported |
| 3 Managed | Staffing derived from forecast and model; QA calibrated | Forecast error tracked; occupancy and shrinkage measured |
| 4 Integrated | Engineering OLA; top-problems list acted on; AI measured by re-contact | Contact rate per customer falls for addressed reasons |
| 5 Adaptive | Changes tested (A/B or staged); routing and staffing tuned per interval | Sustained gains without rising re-contact or attrition |
Adoption roadmap: 30/60/90 days
Link to section “Adoption roadmap: 30/60/90 days”| Window | Actions | Milestones and metrics |
|---|---|---|
| Days 1–30 | Inventory channels, rules, macros and reports; write clock definitions; set priority automatically; start the daily queue stand-up; export event history | Metric dictionary v1; first honest SLA attainment with open breaches; backlog-by-age report |
| Days 31–60 | Contact-reason taxonomy; routing by skill and SLA order; escalation template and OLA draft; per-interval forecast for live channels; QA scorecard and first calibration | Re-route rate measured; staffing model for one channel; escalation acceptance rate baseline |
| Days 61–90 | Change control for the helpdesk; problem-linking SOP; verified-resolution measure for bots and self-service; monthly service review with engineering; top-five problems to product | Re-contact baseline; forecast error tracked; first cause removed and its contact rate measured |
Quick wins: autoreply no longer stops the SLA clock; oldest-ticket view per queue; one macro review pass; a visible “talk to a person” path.
Toolkit
Link to section “Toolkit”Checklists
Link to section “Checklists”Quick start (first week)
- Every channel creates a ticket with a timestamp and a customer key
- Priority is set automatically at creation
- Clock definitions written for each SLA metric
- Daily report shows open breaches and backlog by age
Before launching an SLA tier
- Entitlement lookup at intake
- Policy order tested with synthetic tickets
- Out-of-hours rota for calendar-hour targets
- OLA agreed with engineering for escalations
- Customer-facing wording matches the clock definition
Weekly operations review
- SLA attainment by priority (open breaches included)
- Re-contact within 7 days, by channel and for automation
- Forecast error and schedule adherence
- Top contact reasons and their trend
- Escalations past OLA
Before launching an AI agent
- Disclosed as AI; human reachable in one step
- Restricted topics routed to humans or fixed flows
- Approved, current sources only; owners for each source
- Re-contact measurement in place before launch
- Transcript sampling in QA and a rollback switch
Templates
Link to section “Templates”Escalation to engineering (paste into the issue tracker):
Title: [Product area] short symptom (N customers, severity S)
Customer impact: who, how many, since when, business effect
Linked tickets: IDs (problem ticket if any)
Steps to reproduce: 1. ... 2. ... 3. ...
Expected vs actual:
Environment / version / region:
Logs and screenshots: attached, personal data removed
Workaround tried / given to customers:
Requested severity and reason (rubric v2):
Support owner: name, next customer update due at: time
Helpdesk change request:
Change: what rule, macro, field, form or SLA changes
Reason and evidence: ticket IDs, metric, incident
Owner and approver:
Test: synthetic tickets used and results (sandbox)
Effect on clocks or routing: yes/no, details
Rollback: how, by whom
Release date and announcement to agents:
QA scorecard (weights are an example):
| Criterion | Weight | Pass looks like |
|---|---|---|
| Correct and complete resolution | 30 | Answer solves the stated problem; no follow-up needed |
| Policy and security | 20 | Identity checked where required; no sensitive data requested |
| Expectations set | 15 | Next step and time given when not solved |
| Clarity and tone | 15 | Plain language, customer’s terms |
| Right escalation or link | 10 | Escalated with template, or linked to problem ticket |
| Correct fields and tags | 10 | Reason, product area and priority correct |
SOP: mass issue handling (one page): trigger (three or more tickets on one new symptom within an hour, or an engineering incident); create the problem ticket; publish the agent macro and customer status; link the engineering issue; assign a support liaison to IncidentOps; update customers at the promised time; solve via the problem ticket; review within five business days.
Deep comparisons
Link to section “Deep comparisons”| Question | SupportOps | CustomerOps | CXOps | ITOps |
|---|---|---|---|---|
| Trigger | Customer contacts you | Lifecycle event or risk signal | Feedback across the journey | Employee contacts IT |
| Unit of work | Ticket | Account | Insight and action | Incident, request |
| Core measure | SLA, re-contact, cost per resolution | Retention, expansion | Measured effect of fixes | SLA, change success |
| Core maths | Queueing, forecasting | Survival, cohorts | Survey statistics | Queueing (same as support) |
Is SupportOps a job title? Yes, mostly as “support operations” (manager, analyst, specialist). The one-word form is informal shorthand.[1][6]
Do we need WFM software? Not for one channel and a stable volume: a spreadsheet with Erlang C and a per-interval forecast is enough. Multi-skill routing, many channels, labour-law constraints and hundreds of agents justify a WFM suite.
What is a good first-reply target? The one your customers value and you can staff. Industry figures vary by sector and are rarely comparable because clocks differ; this page gives none for that reason.
How do we count an AI agent’s success? Verified resolution: sessions with no contact on the same reason within a window, plus hand-off quality. A vendor’s billed “resolution” may include assumed outcomes.[32]
What if engineering will not sign an OLA? Measure escalation age anyway and bring it to the monthly service review with the breaches it causes; a contract SLA that depends on engineering is an executive decision, not a support one.
Going further
Link to section “Going further”Advanced topics and emerging direction
Link to section “Advanced topics and emerging direction”- Established: multi-skill staffing and routing, Erlang A and simulation, time-varying staffing; see the operations research survey for entry points.[2]
- Active practice, evidence still thin: AI agents with outcome-based pricing; AI drafting and summarisation for agents (one large field study in one firm);[31] automatic contact-reason classification; quality review of every conversation by models.
- Regulatory direction: AI transparency obligations (EU AI Act Article 50 from August 2026) and liability for automated answers.[33][41]
- Marketing claims to test before believing: “autonomous support”, fixed percentage deflection promises, and benchmark CSAT figures without a stated survey method.
Learning path
Link to section “Learning path”| Stage | Do this |
|---|---|
| 1-day primer | Read The ticket lifecycle and Capacity; run Labs 1 and 2 |
| 1 week | Write your team’s clock definitions; re-time 20 tickets; build the backlog-by-age report |
| 30 days | Forecast one channel per interval for four weeks and track error; run Lab 3 on an anonymised export; draft the escalation template with engineering |
| Advanced | Simulation for multi-skill queues (Lab 4 as a start), Koole’s Call Center Optimization, KCS on KnowledgeOps, AI operations on LLMOps |
| Portfolio | A metric dictionary, a staffing model with documented assumptions, and a before/after of one removed contact reason |
Wrap-up
Link to section “Wrap-up”Executive recap and cheat sheet
Link to section “Executive recap and cheat sheet”| Topic | Remember |
|---|---|
| What it is | The operations layer of customer support: queue, clock, loop |
| First decisions | Clock definitions; priority rubric; pooled vs split queues; who owns helpdesk changes |
| Capacity | Load = arrivals × AHT; Erlang C for live queues; add shrinkage; workload + Little’s law for email |
| Metrics | SLA with open breaches; requester wait p80; backlog age; re-contact 7 days; verified automation resolution |
| AI | Assist agents first; disclose; human in one step; measure by re-contact; you own its answers |
| Watch-outs | Autoreplies stopping clocks; Pending parking; occupancy targets; claimed deflection; rule sprawl |
| Next actions | Write the metric dictionary; re-time a sample; forecast per interval; agree an OLA |
A judgement call: a chat AI agent now, or fix the knowledge base first?
Link to section “A judgement call: a chat AI agent now, or fix the knowledge base first?”Situation (illustrative). A 30-agent team handles 9,000 chats a month. A vendor offers an AI agent priced per outcome, with a pilot showing a 60% resolution rate. The knowledge base has 400 articles; an audit finds a quarter are out of date. Leadership wants savings this quarter.
Option A: launch the AI agent now. Fast; the pilot looks good; some savings start immediately. Option B: spend six weeks fixing the top 60 articles and the hand-off design, then launch. Slower; costs agent time now.
Assumptions to state. The 60% is the vendor’s outcome count, including assumed resolutions; the AI answers from the knowledge base; refunds and plan changes are among the top ten reasons.
Reasoning. With stale sources, some AI answers will be confidently wrong, and the company owns them (Use case 3). The vendor’s count cannot show customers who give up and email instead (Lab 3), so the savings estimate is uncertain and its error is biased upward. Option B’s cost is known; Option A’s downside is spread across customers and hard to see.
Decision. A narrow version of A plus B: launch the AI agent only on reasons whose articles were just verified and that carry no financial or legal commitment, with re-contact measurement from day one, while fixing the rest; expand reason by reason when verified resolution holds. The attractive choice (full launch now) is wrong not because AI is bad but because the measurement would hide its failures. Uncertainty: if the stale articles are on rarely asked topics, Option A’s risk is smaller.
Learning objectives and mastery check
Link to section “Learning objectives and mastery check”After this page you should be able to: explain what SupportOps owns and where its boundaries are; calculate staffing for a live queue and a backlog; design an SLA clock that cannot be gamed; evaluate automation by verified resolution; and build an escalation interface with engineering.
1. Two reports disagree on first-reply SLA attainment (92% vs 61%). Name three definitional causes.
Business vs calendar hours; whether an autoreply stops the clock (a Zendesk autoreply, a Copilot add-on feature, does; Freshdesk’s automation “Send Reply” does not); whether unanswered tickets past target are counted.
2. 100 chats per 15 minutes, AHT 3.5 minutes. What is the load, and why are 24 agents not enough?
Load = 100 ÷ 15 × 3.5 = 23.33 erlangs. With 24 agents the margin is tiny, so random clusters create long queues: only about 21% are answered in 20 seconds; about 28 agents are needed for 80/20 (Erlang C, Koole’s example).
3. 240 email tickets arrive per business day and the target average time to first reply is half a day. What average waiting backlog does that imply?
By Little’s law L = λW = 240 × 0.5 = 120 tickets awaiting a first reply on average.
4. A bot reports an 85% resolution rate. What would you measure before believing it?
The share of “resolved” sessions with no contact from the same customer on the same reason within a window (for example seven days) on any channel, plus hand-off rate and quality. Vendor definitions can include assumed resolutions when the customer simply leaves.
5. CSAT went from 72% to 80% this week on 11 and 10 ratings. Is that an improvement?
Not demonstrably: with about ten ratings the 95% interval spans tens of points (Lab 3: 43%–90% for 8 of 11). Report n and the interval, and look at a longer period.
6. Engineering says escalations are low quality; support says engineering never answers. What do you set up?
An escalation template and severity rubric agreed by both, an OLA for acknowledgement and updates, tracking of escalation acceptance rate and age, and a monthly service review using those numbers.
Conclusion
Link to section “Conclusion”SupportOps is easy to underestimate because its outputs look administrative: a policy, a rule, a schedule, a dashboard. Underneath is a precise discipline. Demand arrives at random, so capacity is a matter of queueing maths, not effort. Promises are measured by clocks, so the definition of the clock is the real promise. Every ticket is evidence, so a support operation that only answers and never feeds the causes back is paying for the same problem again and again. The label is informal and the boundaries with customer success and CX are this Atlas’s choice; the work itself is well defined. Get the queue, the clock and the loop right, measure outcomes the customer would recognise, and let automation earn its place one verified reason at a time.
Sources and further reading
Link to section “Sources and further reading”All sources were opened on 2026-10-23. Product behaviour, plans and prices are as of October 2026; re-check them before relying on a detail. Legal sources are orientation only.
Further reading.
- Ger Koole, Call Center Optimization (MG books, 2013), the full book beyond the free chapters.
- Noah Gans, Ger Koole and Avishai Mandelbaum, “Telephone Call Centers: Tutorial, Review, and Research Prospects”, Manufacturing & Service Operations Management 5(2), 2003 (doi 10.1287/msom.5.2.79.16071); not opened for this page.
Changelog. Vendor rows (Zendesk, Freshdesk, Atlassian, Intercom) and the EU AI Act row are due for re-verification by 2027-01-23.
- 2026-10-23, first version: research and ledger (
research/supportops-ledger.md), four labs executed on synthetic data, eight diagrams; not yet independently fact-checked. - 2026-10-23, round 1 revision (
reviews/supportops-r1.md, responsereviews/supportops-r1-response.md): AI-assistance study cited in its 2025 journal version; COPC Release 8.0; Artefact 1 filter, catch-all, OAuth scope and curl error handling; Zendesk skills-timeout, autoreply and plan conditions; full swarming quote; AI Act provider and deployer; primary Air Canada decision; Klarna and Air Canada told once; Lab 1 leaves not-yet-due tickets out (re-run); global coverage; two diagram fixes. - 2026-10-23, post-score polish (
reviews/supportops-polish.md): Scenario 4 matches Lab 2 (48 agents); AI Act provider definition completed; DOI link added; Air Canada PDF re-opened.
Time to build a support operations team — Zendesk blog, Laura Shear, last updated 2021-01-26. Checked 2026-10-23. ↩︎ ↩︎
The Modern Call Center: A Multi-Disciplinary Perspective on Operations Management Research — Zeynep Aksin, Mor Armony and Vijay Mehrotra, Production and Operations Management 16(6), 665–688, 2007 (course copy). Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
HDI Support Center Manager — HDI, course page. Checked 2026-10-23. ↩︎
ISO 18295-1:2017 Customer contact centres — Part 1: Requirements for customer contact centres — ISO, 2017, confirmed 2023 (iso.org page read via the Internet Archive). Checked 2026-10-23. ↩︎ ↩︎ ↩︎
ISO 10002:2018 Quality management — Customer satisfaction — Guidelines for complaints handling in organizations — ISO, 2018 (archived page). Checked 2026-10-23. ↩︎ ↩︎
Support Team Handbook — GitLab Handbook, last modified 2026-07-29. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎
Customer Support Systems — GitLab Handbook, last modified 2026-08-17. Checked 2026-10-23. ↩︎ ↩︎ ↩︎
Call Center Optimization, first chapters (PDF) — Ger Koole, MG books, Amsterdam, 2013 (sections 1.2, 2.1–2.5). Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Defining SLA policies — Zendesk help, undated live page. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Metrics definitions (Zendesk) — GitLab Handbook, last modified 2026-07-14. Checked 2026-10-23. ↩︎ ↩︎
ISO 18295-2:2017 Customer contact centres — Part 2: Requirements for clients using the services of customer contact centres — ISO, 2017 (archived page). Checked 2026-10-23. ↩︎ ↩︎
Working with problem and incident tickets — Zendesk help. Checked 2026-10-23. ↩︎ ↩︎ ↩︎
Little’s Law as Viewed on Its 50th Anniversary — John D. C. Little, Operations Research 59(3), 536–549, 2011, doi 10.1287/opre.1110.0940 (course copy). Checked 2026-10-23. ↩︎ ↩︎
Forecasting: Principles and Practice (3rd ed.), 12.1 Complex seasonality — Rob J Hyndman and George Athanasopoulos, OTexts, 2021. Checked 2026-10-23. ↩︎ ↩︎
Setting your schedule with business hours and holidays — Zendesk help. Checked 2026-10-23. ↩︎
Managing your omnichannel routing configuration — Zendesk help. Checked 2026-10-23. ↩︎ ↩︎
Set up SLA conditions — Atlassian Support, Jira Service Management Cloud. Checked 2026-10-23. ↩︎
Understanding SLA Policies — Freshdesk Support, modified 2026-08-20. Checked 2026-10-23. ↩︎
What is the difference between ticket triggers and automations? — Zendesk help. Checked 2026-10-23. ↩︎
Gartner Says Only 9% of Customers Report Solving Their Issues Completely via Self-Service — Gartner press release, 2019-09-25 (read via the Internet Archive). Checked 2026-10-23. ↩︎
Why Intelligent Swarming? — Consortium for Service Innovation, Intelligent Swarming Practices Guide. Checked 2026-10-23. ↩︎ ↩︎
COPC Inc. Announces Release 7.0 of the COPC Customer Experience (CX) Standard — COPC Inc. press release, 2021-08-05 (superseded release). Checked 2026-10-23. ↩︎
Release 8.0 Frequently Asked Questions — COPC Inc., live page. Checked 2026-10-23. ↩︎ ↩︎
The Double Loop Process (KCS v6 Practices Guide) — Consortium for Service Innovation. Checked 2026-10-23. ↩︎
zammad/zammad — GitHub, AGPL-3.0. Checked 2026-10-23. ↩︎
osTicket/osTicket — GitHub, GPL-2.0. Checked 2026-10-23. ↩︎
freescout-help-desk/freescout — GitHub, AGPL-3.0. Checked 2026-10-23. ↩︎
chatwoot/chatwoot — GitHub (check the repository’s licence file before use). Checked 2026-10-23. ↩︎
What is Workforce Management in Jira Service Management? — Atlassian Support. Checked 2026-10-23. ↩︎ ↩︎
Generative AI at Work — Erik Brynjolfsson, Danielle Li and Lindsey R. Raymond, The Quarterly Journal of Economics 140(2), 889–942, 2025, doi 10.1093/qje/qjae044 (the Stanford page, labelled “Working Paper”, shows the published abstract; earlier: NBER Working Paper 31161, 2023). Checked 2026-10-23. ↩︎ ↩︎ ↩︎
Fin AI Agent outcomes — Intercom Help (undated). Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎
Article 50: Transparency Obligations for Providers and Deployers of Certain AI Systems — EU AI Act, unofficial consolidated text (artificialintelligenceact.eu). Checked 2026-10-23. ↩︎ ↩︎
Not Delayed, Not Deferred: EU AI Act Transparency Obligations Are Now in Force — Goodwin Procter alert, 2026-08-03. Checked 2026-10-23. ↩︎
Article 3: Definitions — EU AI Act, unofficial consolidated text (artificialintelligenceact.eu), points (3) provider and (4) deployer. Checked 2026-10-23. ↩︎
SLA Policies (API reference) — Zendesk Developer Docs. Checked 2026-10-23. ↩︎ ↩︎
Conditions reference — Zendesk Developer Docs. Checked 2026-10-23. ↩︎
OAuth Tokens for Grant Types — Zendesk Developer Docs. Checked 2026-10-23. ↩︎
Klarna AI assistant handles two-thirds of customer service chats in its first month — Klarna press release, 2024-02-27 (company claims). Checked 2026-10-23. ↩︎
Klarna Is Hiring Customer Service Agents After AI Couldn’t Cut It on Calls, According to the Company’s CEO — Entrepreneur, Sherin Shibu, 2025-05-09 (report of a Bloomberg interview). Checked 2026-10-23. ↩︎ ↩︎
Moffatt v. Air Canada, 2024 BCCRT 149 — Civil Resolution Tribunal of British Columbia (small claims), reasons for decision, 2024-02-14, paras 27–28. Checked 2026-10-23. ↩︎ ↩︎
Art. 5 GDPR: Principles relating to processing of personal data — gdpr-info.eu (unofficial text). Checked 2026-10-23. ↩︎
Adding a credit card identification field (last four digits) — Zendesk help. Checked 2026-10-23. ↩︎