Stagehand is the SDK for browser agents.
- Goal: Discover live jobs, extract structured role details, and prepare applications for human review.
- Pattern: Exa finds direct careers or ATS pages; Stagehand V4 uses
act,extract, andobserveto inspect and fill them. - Safety: Fills only non-empty supplied applicant values, uploads a test résumé when requested, and never submits.
- Plans: Sequential mode works on all plans. Bounded concurrency is opt-in and requires sufficient Browserbase concurrency.
- Docs → Stagehand V4 | Stagehand Python | Exa Search
- Discover jobs — one focused Exa search returns a small ranked set of direct company careers or recognized ATS pages.
- Inspect a role —
act()opens one live role andextract()returns its title, requirements, and responsibilities. - Inspect the application —
act()opens the form andobserve()inventories its fields. - Prepare for review —
act()fills matching non-empty applicant values; the exact file input uploads the résumé. - Report, do not submit — a final
extract()summarizes the review and the required fields that remain.
Direct page methods are limited to exact navigation, résumé upload, and session lifecycle. They do not replace Stagehand's primary interaction primitives.
cd exa-browserbaseuv synccp .env.example .env- Add
BROWSERBASE_API_KEYandEXA_API_KEYto.env. - Replace the synthetic
APPLICANTandDummy_CV.pdfwith your test data. uv run python main.py
The default run reviews one application sequentially, trying up to three ranked candidates when an earlier live result has no usable form. For a small, repeatable smoke run, set COMPANY_QUERY=Browserbase NUM_COMPANIES=1.
Set NUM_COMPANIES to review more candidates. Set CONCURRENT=true MAX_CONCURRENT_BROWSERS=2 to opt into bounded concurrent sessions.
- A run succeeds when it reaches at least one real application and returns a review.
fields_attemptedlists the fields whose Stagehand actions reported success; it is intentionally not a claim that every ATS persisted every value.resume_uploadedreports that the deterministic file-upload command completed without throwing; persistence is left to external E2E validation.- Null, empty, absent, or ambiguous fields remain outstanding instead of being invented or treated as infrastructure failures.
- The final submit button is never clicked.
📚 Stagehand Docs: https://docs.stagehand.dev/v4/first-steps/introduction 📚 Stagehand Python SDK: https://docs.stagehand.dev/v4/sdk/python 📚 Exa API: https://docs.exa.ai/reference/search 🎮 Browserbase: https://www.browserbase.com 🔧 Templates: https://www.browserbase.com/templates 💬 Discord: http://stagehand.dev/discord