Inspiration

Hundreds of thousands of people in the US work on OPT, an H-1B, an EAD or a green card. For them, every job search starts with one question: am I even allowed to take this job? The answer is buried in the posting. It might be "must be able to work without sponsorship" in a legal footer, "active Top Secret clearance" in the eighth bullet, or "must be a U.S. person as defined in 22 CFR 120.62". No job board filters on any of it, so people read every posting closely, or apply and hope. I stumbled upon this problem during my own job search.

What it does

You pick your status (EAD, OPT, H-1B or green card), then do one of three things:

  • Paste a job posting or its link: It works with LinkedIn, Greenhouse, Lever, Ashby, Wellfound and most careers pages.
  • Paste a company's careers page: SponsorLens finds the company's Greenhouse, Lever or Ashby board and checks every US job on it.
  • Read the verdict:
    • Clear: nothing in the posting stops you.
    • Unclear: the posting doesn't say, so ask the recruiter.
    • Blocked: the posting rules you out.

Every verdict quotes the exact lines that decide it and highlights them in the posting. Switching status changes the answer instantly. An "At a glance" card adds location, work mode, experience, education, salary and job type, each with its own quote. When the answer is Unclear, Tavily searches the company's sponsorship history and shows it beside the verdict, without changing it.

How we built it

Two Nemotron models, each doing what it's good at: Both run on Nebius Token Factory's OpenAI-compatible API, in JSON mode.

  • Nemotron 3 Nano reads the whole posting and copies out every sentence about visas, citizenship, clearances, export control or E-Verify.
  • Nemotron 3 Ultra classifies only those sentences into seven signal types, each with the shortest exact quote and a plain reading.

Quotes are verified, and rules decide.

  • Every quote is checked word for word against the posting. A quote that can't be found is sent back once to correct, then thrown out.
  • A fixed rules table, not the model, maps signals and status to a verdict. Every rule has a unit test, and one analysis serves all four statuses.

Tavily, twice.

  • Tavily Extract (advanced) reads pasted links, so the server never fetches arbitrary URLs itself.
  • Tavily Search finds company context for Unclear verdicts.

A hand-built engine on asyncio handles batches of hundreds of postings:

  • bounded queues on asyncio.Condition, so a full queue pushes back;
  • a worker pool held to Token Factory's measured rate limits, with retries and full-jitter backoff;
  • four shards on a consistent-hash ring;
  • a sharded LRU cache with single-flight;
  • an append-only log with group commit that resumes a batch after a crash;
  • a live dashboard over server-sent events.

Accuracy, measured in LangSmith. The model is scored on 27 labeled postings, 12 of them hard cases, with four model setups compared side by side. The app's setup got 27 of 27 right, with no invented quotes. The dashboard is public.

Frontend and hosting.

  • The frontend is React, TypeScript, Vite, Tailwind and Recharts. It works on phones and has light and dark themes.
  • It's hosted for $0 on Render, behind a daily dollar cap, an hourly request limit and an automatic shutoff after judging ends.
  • Tests: 235 in Python (pytest), 27 unit and component tests (Vitest), and 14 end-to-end tests in a real browser (Playwright).

Challenges we ran into

  • A link that lied. A tester pasted a Wellfound search link. The page was a list of other startups' jobs, not the job itself, and SponsorLens said Clear, while the real job needed a Top Secret clearance.
    • I added a rewrite that turns search links into the job's own page.
    • I added a check that refuses any page that doesn't look like a single posting. A wrong page must never get a verdict.
  • Reasoning that never finished. On a noisy page, Nano spent its whole 8,192-token budget reasoning, three times in a row, and never wrote an answer.
    • Retrying the same way just repeated the failure.
    • Retrying once with enable_thinking off answers in about a second.
    • Reasoning stays on for the first try, because LangSmith showed that turning it off misses things.
  • Rate limits and long tails. Nemotron's median call took 6.4 seconds, but the 95th percentile took 79 seconds.
    • The engine holds concurrency to the measured limits.
    • It frees a worker's slot while that worker waits to retry.
    • The benchmark replays those real latencies to measure each design choice.
  • Keeping a public demo cheap. Anyone can use the live demo, so it has a daily dollar cap checked before every model call, an hourly limit, small board scans, and a cutoff date after which it makes no paid calls at all.

Accomplishments that we're proud of

  • Every verdict shows its evidence, and the evidence is verified in code. The model can't make up a reason.
  • 27 of 27 on the labeled set, with a public LangSmith dashboard that shows exactly how it was measured, including the setup that failed.
  • 200 real postings from 20 companies in 12.5 minutes for $0.30. Running the same 200 again takes 0.2 seconds from the cache.
  • Crash recovery that works: kill the server mid-batch and it resumes without redoing any finished posting.
  • Real users shaped it. Testers asked for links, a Start over button, board scans, a cleaner phone layout and plain-language answers, and all of it is in.

What we learned

  • Let the model find evidence and let code make the decision. It's easier to trust, to test and to cache.
  • Measure before choosing models. On this dataset Nemotron 3 Nano alone matched the two-model cascade at about a sixth of the cost. Reasoning mattered most on exactly the cases that hurt users.
  • Design for the long tail. Most calls are fast, but the slow ones decide how the whole system behaves.

What's next for SponsorLens

  • A wider scope. Testers want the same quote-backed answers for remote or location limits, degree requirements and pay. The At a glance card is the start.
  • A larger accuracy set labeled from real postings, to choose between the cascade and Nano alone.
  • Work stealing between shards, to keep the isolation without losing throughput.
  • A browser extension that shows the verdict right on the job page.

Built With

  • asyncio
  • fastapi
  • langsmith
  • nebius-token-factory
  • nvidia-nemotron
  • playwright
  • python
  • react
  • recharts
  • render
  • tailwindcss
  • tavily
  • typescript
  • vite
  • vitest
Share this project:

Updates

Submission history