Escalated support tickets: picking specialist agents per ticket
Official cookbook recipe
- Industry
- Marketing & support · Ticket escalation
- Source
- Official open-multi-agent cookbook
- Stage
- Runnable example
This is an official open-multi-agent cookbook example, maintained by YuanASI. It gives support tickets two paths: escalated tickets go to a coordinator that picks specialists at runtime and assembles a task graph on the fly, while the high-volume fixed path is a standalone Express REST app that handles every request with a hardcoded three-step DAG.
Scenario
A typical case: most of a support team's tickets on any given day follow the same flow — classify, draft a reply, run QA. Escalated tickets each need their own lines of inquiry: a shipping ticket means checking the order and carrier records, a billing ticket means checking charges and subscriptions, and the two need entirely different specialists. Cover everything with one hardcoded flow and every ticket runs analysis steps it has no use for.
The example shows the two shapes separately: the shape that varies goes through runtime decisions, the fixed shape goes through an explicit task graph. The source comments explain the tradeoff — running the fixed path through a coordinator as well would re-derive the same graph on every request and pay for an extra synthesis call.
How it works
| Roles | Task DAG | Tools | Model | Deployment |
|---|---|---|---|---|
| triage-specialist | Generated by the coordinator at runtime; the instructions require it on every ticket | None declared | OMA_MODEL or the default gpt-5.4-mini (openai) | Local script, single run via npx tsx |
| order-specialist | Picked for shipping tickets only, skipped for billing tickets | None declared | Same | Same |
| billing-specialist | Picked for billing tickets only, skipped for shipping tickets | None declared | Same | Same |
| policy-specialist | Used on every ticket, working only from the policy text passed in | None declared | Same | Same |
| response-specialist | Depends on every selected analysis task; produces the reply and an internal handoff note | None declared | Same | Same |
| classifier | Express app: Classify ticket (root task) | None declared | deepseek-v4-flash (deepseek) | Express service, inside the POST /tickets request |
| drafter | Draft reply, depends on Classify ticket | None declared | deepseek-v4-pro (deepseek) | Same |
| qa-reviewer | QA review, depends on Classify ticket + Draft reply | None declared | deepseek-v4-pro (deepseek) | Same |
The models in the table are the example repository's defaults; the actual choice is made per scenario at the design stage.
The cookbook script uses runTeam(): the coordinator receives the ticket text, account evidence and policy excerpts, and outputs a JSON array of tasks (title, description, assignee, dependencies). The example appends the selection rules to the coordinator's system prompt through coordinator.instructions. Two built-in scenarios switch via TICKET_SCENARIO=shipping (default) or billing, and both the orchestrator and the team cap concurrency at 3.
The Express app uses runTasks(): the three tasks are declared once in the route handler, OMA runs them in topological order and injects upstream output into the downstream prompt's ## Context from prerequisite tasks section. All eight agents constrain their output with a Zod outputSchema; none declares tools or a toolPreset, so under OMA's deny-by-default grants each resolves to zero built-in tools.
Result
Runnable output and how to verify it:
Both need an API key. The cookbook script header lists OPENAI_API_KEY, and OPENAI_BASE_URL + OMA_MODEL can point it at any OpenAI-compatible endpoint; alternatively use OMA_PROVIDER=copilot with GITHUB_COPILOT_TOKEN / GITHUB_TOKEN. The Express app needs DEEPSEEK_API_KEY by default.
The coordinator's selection is visible. When the script finishes it prints the task count and lists each task's status, title and assignee — in the shipping scenario billing-specialist gets no work, and the reverse in the billing scenario. It then prints the response-specialist's structured JSON and the coordinator's synthesis; if the run fails overall, the process exit code is set to 1.
The Express app runs as its own service. After npm install && npm start it listens on 3000 (override with PORT); POST /tickets with {subject, body} returns four fields: category / urgency / draft_reply / qa_notes.
Error paths are explicit. At startup it checks each agent's provider key and exits with an error if one is missing. At request time, 400 means an invalid request body, 502 means the pipeline did not succeed or an agent produced no structured result, and 504 means the 60-second timeout was hit (the timeout aborts in-flight LLM calls).
It ships with a smoke test. npm run smoke starts the service on a temporary port, sends a login-failure ticket and validates the response against the schema; on success it prints the result and exits with code 0, on failure with code 1.
Sources
How this relates to YuanASI
The material on this page is a cookbook example and its companion Express app from the official open-multi-agent repository, maintained by YuanASI.
If you want ticket classification, specialist triage, reply drafting and QA built as a service that plugs into your existing support system — fixed flows as explicit task graphs, escalated tickets handled by runtime decisions — the matching YuanASI services are listed under Related services below; start here: Custom AI Agent Development →
Related services
Last updated
Want to know how a workflow like this would land on your side?