Support reference

Config

categories is classification; the guard and the verdicts are provenance; inboundAddresses is bounded by the MX constraint. Refusals carry an ordinary error code.

support({
  inboundAddresses: ["support@help.example.com"],
  ai: { enabled: true, model: "@cf/meta/llama-3.1-8b-instruct" },
  categories: defineSupportCategories({ /* yours, merged over the eight */ }),
  guard: {
    maxRawBytes: 2_000_000,
    maxPerSenderPerHour: 20,
    maxPerHour: 500,
    archiveSpam: true,
  },
})

Until inboundAddresses is set the inbox is inert — it ignores every message and says so once in the log.

Enums

Priority — urgent (today) · normal (this week) · low (when there is time)

Sentiment — angry · frustrated · neutral · positive

Direction — inbound (arrived from the customer) · outbound (a reply this Worker sent)

Channel — email · app

Account link source — session · email_address · null

Categories — billing · account_access · bug_report · feature_request · abuse_report · privacy_request · spam · uncategorized, plus your own.

Routes

RouteVerified by
POST /support/feedbackuser — open or append to your own thread
GET /support/feedbackuser — my threads
GET /support/feedback/:iduser
GET /support/threadscontrol-plane
GET /support/threads/:idcontrol-plane
GET /support/repliescontrol-plane
POST /support/threads/:id/archivecontrol-plane
POST /support/threads/:id/replycontrol-plane
POST /support/threads/:id/reclassifycontrol-plane
POST /support/threads/:id/flagscontrol-plane

Scopes

Scope
support:threads:read
support:threads:archive
support:threads:reply
support:threads:reclassify
support:threads:flag

Error codes

Code
support/not_found
support/invalid_categoryA declared key outside the effective taxonomy
support/rejectedThe guard refused it
support/unparseable_message
support/classification_failed
support/reply_failed

Thread columns worth knowing

Column
declaredCategoryThe submitter’s claim. Written once, never by the classifier
categoryThe model’s judgment. Overwritten on every classification
accountLinkSourcesession, email_address, or null
channelOn the thread and on every message
emailJobIdPresent exactly when a row is outbound and email. Ask channel, not this

Threading

On In-Reply-To and References. Never on the subject.

An app submission is minted a message id on the way in, so a mailed reply threads back rather than opening a new conversation.

Recipient matching

On the SMTP envelope recipient. Never on a To: header.

What provisioning creates

An R2 bucket (only if something writes to it), a classification Worker per environment, and — only when you pass all three routing flags — an Email Routing rule named <project>-global-support-inbound.

License

MIT, like most of the kit. Nothing here is unlocked by a hosted dashboard — every route is reachable with a credential you issued.

ESC