A language model inside a workflow is just another integration that can return the wrong thing. The difference is that a bad HTTP response is obvious and a plausible paragraph is not.
Constrain the shape
const Verdict = z.object({
segment: z.enum(["smb", "mid_market", "enterprise", "not_a_fit"]),
score: z.number().int().min(0).max(100),
confidence: z.number().min(0).max(1),
reasoning: z.string().max(400),
});Now the AI step has a contract. Anything outside it is a failure with a clear handler, not a surprise three nodes downstream.
Confidence is the useful field
In practice the label matters less than how sure the model is. Confidence is what decides whether a result flows straight through or lands in a review queue — and it is the cheapest safety mechanism available.
Test it like code
- Keep a fixture set of hard inputs and run it on every prompt change.
- Assert schema validity separately from answer quality.
- Track the malformed-output rate; it is an early warning for prompt drift.