Intent classification
firstflow_conversation_messages, builds a forced-choice prompt over your branches, parses the chosen label into a confidence, reconciles against the conversation’s sticky state, and writes the result to firstflow_conversations.state (and the intent column if alsoSetIntentColumn). Pass recentMessages directly to skip the DB read.
Hysteresis
A raw per-message classification would flip-flop. The reconciler holds the active intent unless a new one is clearly better:Using intent in a flow
Step branches readtraits, user, session, and answers not the classifier directly. Bridge it as a trait:
Cost
Roughly $0.0003 per call withclaude-haiku-4-5 over a 10-message window. Run it every turn, every Nth turn, or on demand your choice. Set confidenceFloor to skip writes when uncertain.
Intent and
state persistence requires migration
0007_conversation_signals.sql. If classifyIntent returns a value but the
conversation row never updates, apply it. See Set up Supabase.Sentiment (no LLM call)
classifySentiment is a pure lexical scorer over the user’s messages free and synchronous:
sentiment is positive | neutral | negative; score ranges roughly -1..1. It needs no model, so it runs anywhere with no cost.
Building “classify → trigger an experience”
Compose the classifier with the client’semit: classify on the server, return an event name, and emit it on the client to fire a matching custom_event experience.