Skip to main content
The server SDK ships two classifiers: an LLM-backed intent classifier with hysteresis, and a free lexical sentiment scorer. Both are functions you call from your own routes you decide the branches, when to run them, and what to do with the result.

Intent classification

It reads recent messages from 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 read traits, user, session, and answers not the classifier directly. Bridge it as a trait:

Cost

Roughly $0.0003 per call with claude-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’s emit: classify on the server, return an event name, and emit it on the client to fire a matching custom_event experience.

Next

Attach manual outcomes & signals, or review what gets recorded.