Context
Behind every subscription business is a long tail of operational work that nobody wants to talk about in a pitch deck. At Tumble, a big part of that tail was property maintenance: tickets coming in from the places that actually ran the machines — property managers, residents, laundromat owners — saying things like "dryer 4 won't start" or "leak under washer 12."
These tickets arrived as free text, at all hours, from a variety of channels. Each one had to be triaged, matched to the right vendor, scheduled against that vendor's availability, and then communicated to at least three different audiences: the person who reported it, the property manager, and the vendor themselves. Each audience needed a different version of the message.
For a while, we had a person whose whole job was to route these tickets. It was honest work and she was good at it. But it was repetitive, it was interrupt-driven, and it was exactly the kind of work that AI is now genuinely good at.
The challenge
The obvious reflex is "throw a language model at the tickets and tag them." That's a demo. A demo doesn't keep the laundromats running. To replace a real dispatch desk you need a system that can:
- Read a free-text ticket — often vague, often missing context, sometimes in a combination of English and emoji and partial sentences — and extract a structured classification: urgency, equipment type, vendor category, location.
- Pick the right vendor from a roster that changes every week, weighted by availability, rating, and proximity.
- Write three different messages about the same incident: one to the resident who reported it, one to the property manager who owns the relationship, one to the vendor who's going to do the work.
- Track the whole thing so that when any stakeholder asks "what's happening with ticket #4832?" there's a real answer.
Any one of these is tractable. Chaining them in production is where most systems break.
The approach
Three agents, each with a narrow job, connected by a queue.
-
Triage agent. Receives the raw ticket. Classifies urgency (routine / priority / emergency), equipment type, vendor category, and extracts any embedded details like unit numbers or contact info. Writes its classification plus the original ticket into the next queue.
-
Scheduler agent. Picks the best vendor given the triage output and the current availability roster. Considers rating, proximity, historical performance, and whether the vendor has capacity this week. Books the appointment and passes everything forward.
-
Comms agent. Generates three messages from the structured ticket + the scheduled appointment — one for each audience — in the voice and length the audience expects. Sends them. Logs them.
Between each agent is an SQS queue. That's the important part. The queue isn't just for throughput; it's the recovery mechanism. If any single stage fails — a vendor roster API goes down, the comms step hits a rate limit, the triage model gets a ticket it can't classify confidently — the message sits in the queue until the stage can process it. Nothing drops. Nothing needs to be retried by hand.
What we built
A Python service per stage, an SQS queue between each, a classification schema in a shared module, and a set of observability hooks so the team can see exactly which stage a given ticket is in at any time. Nothing exotic — the AI parts are where you'd expect the AI parts, and the pipeline parts are where you'd expect the pipeline parts.
A ticket arriving from any source lands in the first queue within seconds and flows through all three stages without a human touching it, except for the high-urgency cases the triage agent is explicitly trained to escalate to a human. That escalation path was in the design from day one, not bolted on later.
The outcome
Chained agents
3
The manual dispatch desk went away as a full-time job. The person who used to run it moved to handling the escalations the triage agent flagged, plus vendor relationship work that the agent couldn't do. Her job got more interesting; the business ran faster.
Resolution times dropped. Response quality went up (partly because every message was now consistent, partly because the comms agent actually wrote better comms than anyone had time to write when the desk was overwhelmed). And — the part we didn't expect — the log of every ticket becoming a structured record made downstream analysis possible in ways it wasn't before. We could finally see patterns in which vendors were reliable, which equipment was failing most, which properties had the most trouble.
What's different now
This one taught us more about pipeline design than any of our other agents. Three things worth writing down:
- Queues between agents, not function calls. A queue gives you retry, replay, and backpressure for free. Chaining via function calls gives you none of that and a pile of subtle failure modes.
- Escalation is a first-class output, not a fallback. Our triage agent was designed to say "I'm not confident, route to a human" from day one. That single design choice was the reason the operator team trusted the system enough to let it run unattended.
- Replacing a human dispatch desk doesn't mean the human leaves. It means the human works on the problems the agent can't handle yet — which, it turns out, are usually the interesting ones.
This was one of roughly a dozen agents we shipped at Tumble. If you have a manual routing desk sitting in the middle of your business, let's talk.