Skip to content

Conversation classification

The agent classifies operator Chat turns and Intake items with two Cloudflare Workers AI System One models:

  • Clef makes the decisions: route (question, status, work_request, bug, decision, chitchat, human, refuse), severity, product area, and the needs_work, asks_internals, and asks_other_project signals.
  • Clairic reads values from the text: the Steelframe version and the environment. Text answers are exact spans of the message, so Clairic cannot invent a version that was not written.

Both models share one credential. Classification is advisory unless a route is confident: it never replaces the Chat reply and never fails a turn.

conversation_classifications is keyed by subject:

SubjectIDUsed by
chat_sessionchat_sessions.idChat sidebar category and product area
intakeintake_items.idIntake kind/severity fill and the detail view

A Chat session’s latest route and product area are also copied to chat_sessions.category and chat_sessions.product_area so the sidebar can filter without a join. The full row keeps confidence, the yes/no signals, the reporting version, the environment, and the serialized classification for replay.

For an Intake, the classifier only fills kind and severity that the operator did not set explicitly. A confident bug becomes kind=bug; a work_request becomes kind=feature; a question becomes kind=question.

  1. Create a Cloudflare API token with Workers AI access.
  2. Store cloudflare_ai with the account ID in the URL field and the token in the secret field.
  3. Optionally set clef_model (clef or clef-flash) and clairic_model (clairic).

Local testing can use CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN instead of the credential. If the account ID is missing, the agent tries the token’s account list once and caches the first account; a token without Account:Read must set the ID explicitly.

MethodPathPurpose
GET/api/classifications?subject_kind=intake&limit=100Recent classifications.
GET/api/classifications/{kind}/{id}One subject’s latest answer.

Chat sessions expose category and product_area in GET /api/operator/chat/sessions. Intake items expose a classification object in GET /api/intake.

  • A route below 0.6 confidence is recorded but not treated as a decision.
  • needs_work at or above 0.6, or a confident bug/work_request, offers an Intake (the Discord 📥 reaction, or the Board composer).
  • Missing credentials, a non-2xx response, a timeout, or a malformed body logs a warning and leaves the row unclassified. The Chat turn and Intake create still succeed.

The classifier runs in the background after the Chat turn, so it never adds latency to the reply.