A job that fell through a Tuesday afternoon
Picture a 14-truck contracting business. A salesperson closes a kitchen remodel on Tuesday morning. The customer signs the contract, pays the deposit, the salesperson celebrates, and the deal is "won" in the CRM.
Friday afternoon the customer calls Project Management to ask when the install is scheduled. Project Management has no idea this deal exists. The salesperson assumed someone would tell PM; PM assumed nobody had closed a deal that week. The hand-off was supposed to happen — and didn't, because handoffs in most CRMs happen between humans, not stages.
That phone call is the moment every service-business operator has lived through. The deal closed. The work didn't start. The customer's trust is now slightly worse than it was before they paid.
The two things we changed
A workflow in BIAB is a graph of stages. The schema has supported that since day one — you can draw the pipeline however your business actually flows, fan-out and fan-in included. What we added for handoffs is two structured ideas on top of the existing graph:
Every stage has an owner. Not just "in progress" but "in progress, owned by Project Management." The owner can be a team, a department, a specific role (every Install Lead), or a single user. When a record advances into a stage, the owner gets notified and the work shows up in their queue.
Every transition is a Boolean condition the system can evaluate. The previous automation field was freeform text — a note for humans, not something the system acted on. The new triggerExpression is a structured predicate: contract signed, deposit received, all required documents present, status equals X, payment over $Y, time since stage entered greater than Z. The platform evaluates these on every relevant event and advances the record automatically when the predicate becomes true.
Together those two changes turn a "pipeline" into a system that moves work on its own.
Linear handoffs
Imagine the simplest sales-to-install flow:
Lead → Quote → Contract → Project Management Intake → Materials Ordered → Install Scheduled → Install Complete → Invoice
Each stage has its owner: Sales owns the first three; Project Management takes over at intake; Procurement owns Materials Ordered; the Install Crew owns Install Scheduled and Install Complete; Finance owns Invoice. The transition between Contract and Project Management Intake fires when the trigger expression { contract_signed AND payment_received(min: 500) } evaluates true.
The salesperson doesn't email anyone. The contract clears, the deposit lands, the system flips the deal into Project Management's queue, PM gets a notification that reads "handed off from Sales — kitchen remodel for the Smiths," and they start work.
Parallel handoffs
Real businesses don't always run linearly. When the deal moves into Project Management Intake, three things should happen simultaneously: order the materials, schedule the site survey, file for permits. These are parallel branches off one stage.
In the workflow builder, you fan out — Project Management Intake has three outgoing edges to Materials Ordered, Site Survey, and Permits. The platform creates three active stage rows on that record, each owned by a different department, each watching its own trigger:
- Procurement watches for the supplier confirmation event.
- The site-survey team watches for "survey_complete" to flip true.
- The permits coordinator watches for the issuing authority's status webhook.
When all three branches exit (each one's trigger fires and the stage marks complete), the record advances into Install Scheduled — the fan-in stage that waits for every inbound branch. The dispatcher doesn't have to remember whether materials AND permits AND survey are all done; the system knows because every branch's exit timestamp is recorded, and the merge stage only activates when the last one lands.
That's a 2→1 handoff (and the fan-out before it is 1→3). The graph language is general enough to express 2→2 (parallel branches that don't merge) or any other topology — chains of fan-out and fan-in compose freely.
What counts as a trigger
The predicate language ships with these primitives:
- Field equals / not equals / present / absent / greater than — works against any field on the record, native or custom.
- Status is X — first-class because status checks are the most common case.
- Contract signed — fires when any contract (or a named one) attached to the record gets an e-signature.
- Invoice paid / payment received over $X — fires on the Stripe payment event.
- All required files present — for stages that need signed photos, customer signatures, or compliance documents.
- Linked workflow completed — for cross-workflow advancement (Install workflow completion triggers Warranty workflow start).
- AND / OR / NOT — compose predicates arbitrarily.
- Manual — the trigger is "a human clicks advance."
The list grows one record-shape at a time. Anything Boolean-evaluable can become a trigger.
How the handoff actually feels
When a record advances from a stage owned by Sales to a stage owned by Project Management, the new owner gets the notification on whichever channels they've configured — in-app, email, SMS, outbound webhook. The notification copy names the chain of custody explicitly: "Kitchen remodel for the Smiths — handed off from Sales (Jordan) to Project Management. Stage: Project Management Intake."
The receiving team sees the work in their queue. The sending team sees the green checkmark on the stage they completed. Nobody had to remember to email anyone.
Why this changes a service business
The single feature that most consistently turns a CRM into "the place where work actually happens" is when the platform moves work between departments instead of asking humans to remember to. Without it, a CRM is a place to log activity. With it, a CRM runs the operation.
If your sales-to-install handoff fired automatically the moment the deposit cleared, you'd want that, right? If the Friday afternoon "where's my install?" phone calls stopped because PM already had the deal in their queue Tuesday morning? If the parallel branches of materials, permits, and survey all converged on Install Ready without anyone tracking the merge? That's the workflow loop we wanted, and it's why we wired ownership + triggers into the workflow engine instead of leaving the handoffs to humans.

