All news

Agentic AI

Our own sales AI doesn't get to decide when a conversation is ready to move on

We put a real production agent on the table — the one that runs BIXSO's own consult pipeline — and read out what actually decides when it advances, quotes a number, or hands a lead to a human. The model reports a feeling. A function decides.

Our own sales AI doesn't get to decide when a conversation is ready to move on

Most “AI decides” claims fall apart the moment you ask a boring question: decides using what code? Usually there isn’t an answer, because there isn’t code — there’s a prompt asking the model to be careful, and everyone hopes it holds.

We run our own AI-run sales conversation in production — the agent behind bixso.ai/portal, which walks a prospect through five stations (Initial → Model → Analysis → Agentic → Deal) before a human ever sees the lead. So we took it apart on our own bench, on the code that ships today, not the pitch deck for it.

The five stations, and what actually moves them

The stage machine lives in one file, consultEngine.js. The comment at the top of the transition function is the whole argument:

// ── Stage transitions — THE ENGINE decides, not the model ───────────────────

Here is decideStage(), unabridged in spirit:

  • Initial → Model: only if the model said it’s ready and the dossier already has an industry or description and at least one requirement or pain point was actually captured.
  • Model → Analysis: only if the model said it’s ready and the dossier has a model type or at least one identified leak.
  • Analysis → Agentic: only if at least one finding exists.
  • Agentic → Deal: only if a pattern or at least one agent placement exists.
  • Deal → Handed off: not decided here at all — it’s decided in the route, at the moment a lead record is actually created.

The model’s stage_ready flag is one input among several, and it is never sufficient on its own. A model that says “ready!” over an empty dossier stays exactly where it is. That’s the point of building the check in a function instead of a sentence: a sentence can be persuaded, a function either finds the field or it doesn’t.

The filled boxes — what this buys, concretely

  • AI1 (decision rights): the transition authority sits in decideStage(), not in the system prompt. The model’s opinion is data; the dossier’s state is the gate.
  • Money is a harder gate still. When a lead is captured, cfo and cto drafts (csuitePipeline.js) land on the lead as status: draft — quote and proposal both. Nothing is sent to a prospect until a human reviews and approves it in the CRM. The code comment says it plainly: “money = founder’s call.” The AI drafts a number; it does not quote one.
  • Receipts, not vibes. Every completed station emits a deterministic summary object built from the dossier fields, not from the model’s last message — so what the client sees recorded as “done” is exactly what the gate function actually checked.

The one thing we found still empty

Reading the route logic straight, if a conversation jumps two stations in a single turn — say Agentic clears its gate and the lead gets created in the same reply — the code emits exactly one receipt: the final one. The intermediate station’s receipt gets skipped, even though the dossier data for it is still there and correct. Nothing is lost; one confirmation card is. It’s a small seam, and it’s the kind you only find by reading the transition function next to the route that calls it, not by reading either alone.

The takeaway

“The AI decides” is a claim you can verify or you can’t. If the answer to “decides using what code?” is a shrug, don’t trust the sentence in front of it — including ours, before we opened the file.

One more line for the record: BIXSO’s own AI drafts the quote. It does not send it. That line hasn’t moved since this system shipped, and it’s the one we’d be least willing to.