Product & Engineering

Auto-Apply: what worked, and what didn’t

A spreadsheet pilot and four product versions taught us when to apply on a clinician’s behalf, when to pause, and when to ask.

On this page

A clinician we work with told us, almost in passing, that she had matched a shift she would have taken in a heartbeat---and didn’t see the listing for two days. By then it was filled. The job had been right for her on rate, on radius, on specialty. She had texted us a week earlier saying she was ready to work. The listing went live at 11pm on a Sunday. She opened the app on Tuesday afternoon, on a break, and scrolled past the row where it used to be.

Clinicians are looking for work around the demands of their current jobs. They may check listings on a break, while a good match opens late on Sunday or during a busy Wednesday morning. Being interested and being online at the right moment are different things.

Better recommendations and notifications help clinicians find those jobs, but they still have to see the listing and apply before it closes.

The inversion

A two-panel figure. On the left, a clinician scrolls a vertical list of job listings and abandons at the third unmatched row, with most listings dimmed. On the right, a preference card showing specialty, role, radius and a concurrent cap of five feeds into an auto-apply tile, which fans out as applications to matched jobs. Caption: BROWSE to APPLY.

Auto-Apply is the opposite of a recommendation feed. Instead of asking the clinician to browse and decide, the system applies on her behalf, based on a preference profile: specialty, role, radius, rate floor, concurrent application cap. The clinician opts in once. The system runs from there.

The default cap is five simultaneous live applications; the system refills the slot when one closes. The clinician sets the floor on rate, the radius around their preferred location, the role types they’ll take. The system fills the rest.

The clinician now makes one decision about the preferences the system can act on, rather than initiating each application. A matching listing that appears at 11 p.m. on Sunday can receive an application before the clinician wakes up.

This is the same posture we wrote about in Built for the frontier: when the system is competent enough to act, the right move is to let it act. The form gets filled out by an agent, the application gets submitted by an agent, the clinician confirms the parts that need human judgment.

It took a manual pilot and four product versions to learn what that arrangement required.

V0: the pilot was a spreadsheet

The first version of Auto-Apply wasn’t a feature. It was a Google Sheet, a 30-minute polling habit, and a canned message.

In Q1 2023, a small CX pilot ran the whole thing by hand. Clinicians opted in over the phone with their advocate. Preferences (location, pay range, shift, specialty) went into a shared sheet. Every half hour, a teammate refreshed it, watched for newly ingested jobs that matched, and manually created the application in our system. The application got tagged for follow-up. A canned message went out to the clinician: “we submitted you to this job; here’s the window to withdraw.”

It worked. Submission speed went up. Clinicians liked not having to initiate every application themselves. The manual version surfaced the demand before anyone wrote a line of code.

It also surfaced the problems. Candidates sometimes didn’t want the jobs they’d been submitted to. References weren’t ready. Skills checklists had expired. Advocates spent time fielding withdrawals. Submission-to-offer rate on auto-submissions trailed the rate on clinician-initiated applications. Setting a preference profile three weeks ago is not the same signal as tapping Apply on the listing in front of you.

We knew that going in, in the abstract. Running the thing for a few months taught us how much it mattered.

V1 through V4, in order

A four-column evolution timeline of Auto-Apply versions. V1 in late 2023, the first in-product fire with minimal safeguards. V2 in 2024, placement and offer guards stopping fires on jobs already won. V3 in 2024, a pre-qualification check that fires only when qualification would pass. V4 in 2025, hard constraints: exclusions, caps, radius, and a working-clinician guard. Caption: every guardrail has a story.

V1 shipped into the product in late 2023 with safeguards kept minimal on purpose: get the loop in production, watch what happens, add guardrails to fit the actual failure surface rather than the imagined one. Each subsequent version added guardrails in response to what broke.

Version Guardrail added Failure that prompted it
v1 Opt-in plus a five-application cap, nothing else Applied to any matching job for opted-in clinicians, with no placement, offer, or qualification checks
v2 Auto-deactivation on entering a placement phase, active-offer protection, seven-day stale-preferences timer Applications going out for clinicians already on placement or with offers in hand
v3 Pre-qualification check against the role experience rule before applying Advocates spending afternoons clearing applications that would never have passed qualification
v4 Facility exclusions, MSP exclusions, configurable per-clinician cap (5 to 25), radius filtering, working-clinician guard (placement end after job start) Clinicians submitted to hospitals they’d explicitly excluded; queue patterns that didn’t match reality

We added each safeguard after seeing a specific production problem. We would have preferred to anticipate them in the first design. Looking back at the deactivation list shows where the original feature created work or confusion for clinicians, Advocates, and facilities.

A historical window we learned from

A deeper issue surfaced in mid-2025. The clinician base on Auto-Apply had been growing, the feature had been generating applications at scale, and the validation workflow that turns applications into submission-ready packets had just been overhauled.

In the 30 days after the new validation workflow shipped, submission rate on auto-applied applications fell from around 42% to around 30% (historical figures from that specific window, not current benchmarks). Operational load roughly doubled on the validation side. The applications themselves weren’t worse; the analysis on a sample looked like the previous month’s. The throughput to move them through to submission was the bottleneck.

The mistake was assuming validation could scale proportionally with application volume. It couldn’t. Each application still required a human touch. Generating twice as many applications without twice as much qualification throughput just built a bigger queue. The applications existed; the path to submission didn’t.

The fix had two parts. We pushed harder on auto-qualification so more applications cleared without human review, the same direction the rules-engine work has been pulling for a while. And we calibrated Auto-Apply volume to actual throughput, not just opt-in count. The per-clinician cap is part of this. It exists partly to protect the clinician from too many simultaneous commitments, and partly to keep the operations side from being flooded.

That 42-to-30% drop belongs to the historical window described above. The lesson was about capacity: if a feature generates work faster than the next team can process it, the queue grows even as fewer applications reach submission.

The intent signal

A three-column intent spectrum. Left: silent Auto-Apply, faster but weaker intent, with the preference profile acting on its own. Center: one-tap confirm from a job alert, the sweet spot where the system surfaces a fit and the clinician taps to confirm. Right: manual browse and apply, slower but the most deliberate signal. Caption: speed versus intent, both matter.

A preference profile tells us which jobs someone would consider when they set it up. Tapping Apply tells us they want a particular job now. Many of the safeguards address the gap between those two signals.

A clinician who taps Apply on a specific job has looked at the listing. She’s seen the pay, the facility, the unit, the start date. She’s made a per-job decision. A clinician whose Auto-Apply fired because the system found a match may not remember setting the preferences, may not be paying attention this week, may have taken another job in the meantime. Every guardrail we’ve added is a different way of asking is the preference profile still valid right now, because the system can’t observe per-job intent directly.

The stale-service timer is the clearest acknowledgment of this in the feature itself. Seven days without preference updates, and the system stops acting. It’s a crude proxy for are you still the clinician who set these preferences three weeks ago. The right answer is often mostly yes, sometimes no, and the system can’t always tell which.

The real fix, to the degree there is one, has been on the notification side. The application going out is one event. The notification reaching the clinician, and the clinician actually seeing it, is the other. We’ve put more weight on the notification flow (timing, content, channel) than on the eligibility logic at this point. A clinician who sees the notification and doesn’t withdraw is a different signal than one who never saw it.

Which is where Job Alerts comes in. Job Alerts is the closer-to-real-time sibling to Auto-Apply: the system surfaces a matching shift, the clinician taps once, and the application goes in. The honest read on the silent version is that Job Alerts plus one-tap confirmation has cleaner economics, because the intent signal is cleaner. A tap is the strongest possible per-job signal short of the clinician writing the application herself.

That doesn’t make silent Auto-Apply wrong. It makes it a different tool for a different part of the intent spectrum. A clinician who genuinely wants the system to act on her behalf, with a recent preference profile and an active engagement pattern, is well-served by silent Auto-Apply. A clinician in active search mode, refreshing the app and looking at listings, is better-served by Job Alerts plus a tap. Both have a place. Neither replaces the other.

Where the human still lands in the loop

The hardest part of building this wasn’t the apply step. It was deciding when a human still needs to be in the loop.

Most auto-applied shifts close themselves. The clinician sees the application in her queue, confirms interest, and the downstream flow takes over. But a meaningful fraction of auto-applied clinicians don’t engage. They’ve opted in, the system has applied on their behalf, and then---nothing. The clinician hasn’t opened the app or responded. The shift sits open. The facility is waiting. The system has technically done its job and the actual outcome has stalled.

For that case we ship a signal, not an action. A real-time notification lands in the clinician’s advocate thread in Front the moment a clinician under Auto-Apply hasn’t engaged with a shift the system applied to. The advocate sees it inside the tool they already live in. They can pick up the phone, send a text, escalate inside their own workflow.

The notification gives the Advocate the shift, the clinician, and the time since the last response. That lets them check whether the clinician still wants the job and help resolve whatever is holding up the application.

Where it is now

V4 Auto-Apply is the version we run today. Eligibility rules are sophisticated enough that false positives are rare. The per-clinician cap prevents queue flooding. Advocates have controls to configure the feature on behalf of clinicians where that’s appropriate. Deactivation triggers (placement, offer in flight, stale preferences) turn the system off in the situations where it should be off.

We’re still tuning application volume to the team’s capacity. Auto-Apply also gives us less certainty about a clinician’s interest than Job Alerts with a confirmation tap. The deactivation rules help us manage that uncertainty, and we expect to keep adjusting them as we learn.

A few things we’d do differently with what we know now.

Start with opt-in per-job, not opt-in per preference set. The preference-based model creates ambiguity about whether the clinician is genuinely interested in any given match. Confirming per-match before submission preserves most of the speed benefit while keeping the intent clean. Job Alerts is essentially that bet.

Build throughput capacity before turning on volume. Auto-Apply should scale with the qualification capacity available to process its output, not with the number of clinicians who opt in. The mid-2025 validation window taught us that the hard way. We’d like to learn it once.

Treat deactivation triggers as surfaced features, not silent failsafes. The stale timer, the placement deactivation, the offer guard were added reactively to stop specific problems. Designed proactively, they’d show up to the clinician as clear state: Auto-Apply is paused because you started a placement. It’ll reactivate when you’re back in search. That transparency would make the feature feel trustworthy instead of opaque.