Platform Pipelines Agents Human review Self-improvement Observability Deployment Security Use cases Compare Docs Pricing Roadmap Get early access

Support triage

Tickets arrive from the helpdesk all day. Millstream classifies each one, drafts a reply with an agent, and gives support staff an inbox where they approve, edit or reject the draft, with urgent tickets in their own queue and a short timeout.


The pipeline

flowchart LR
  W(["webhook: helpdesk"]) --> D{{dedupe}} --> C["classify (agent)"] --> R["draft reply (agent)"]
  R -->|priority p1| U[/urgent review/]
  R -->|other| N[/support review/]
  U & N --> S[send reply]
pipeline: support-triage
description: Classify tickets and draft replies for review

triggers:
  ticket: { webhook: { rate: 300/min } }

streams:
  tickets.unique: { retention: 180d, redact: [/customer/email] }

steps:
  dedupe:
    action: dedupe
    in: trigger.ticket
    out: tickets.unique
    config: { key: "item.ticketId + ':' + string(item.revision)", window: 7d }
  classify:
    action: lab/classify-ticket@1
    in: tickets.unique
    out: tickets.classified
    concurrency: 8
  draft:
    action: lab/draft-reply@1
    in: tickets.classified
    concurrency: 4
    out:
      - { when: "item.priority == 'p1'", out: replies.urgent }
      - { when: "true", out: replies.normal }
  urgent-review:
    action: review
    in: replies.urgent
    out: replies.approved
    config: { inbox: support-urgent, timeout: 30m, onTimeout: { escalate: support-leads }, editable: [/reply] }
  support-review:
    action: review
    in: replies.normal
    out: replies.approved
    config:
      inbox: support
      timeout: 8h
      onTimeout: { escalate: support-leads }
      editable: [/reply, /category]
      reasons: [wrongCategory, wrongFacts, wrongTone, needsEngineer]
  send:
    action: lab/helpdesk-reply@1
    in: replies.approved

budget: { dayUsd: 30 }

What Millstream does for it

Two agents, two jobs

Staff stay in charge

Ticket text is untrusted


How it learns

Edits to /reply are attributed through lineage to draft, and recurring ones become a lessons proposal for it: rules plus corrected examples, rendered into the prompt. Edits to /category point at classify instead. classify has a bounded output (enums only) and two turns at most, the shape the distillable insight looks for: after 500 deliveries, and with 95% agreement from the reviewers who check its category, improve can draft Go code that classifies the common tickets and abstains on the rest, which go to the agent as its fallback. The code must agree on at least 98% of the holdout items it covers, and cover at least 60% of them, before a person sees the proposal.


Figures to watch

Figure What it tells you
Intervention rate and edit rate on support-review How often the draft is sent as written
Rejections by reason code Whether drafts fail on facts, tone or category
Time to decision on urgent-review Whether urgent tickets get an answer within the half hour
Cost per approved item What a sent reply costs in agent calls
Fallback coverage on classify, once distilled The share of tickets the code handles without the agent

Next

How agents run · Human review · Self-improvement