Control a dedicated browser via agent-browser (Vercel). Use when automating web apps, scraping authenticated sites, filling forms, or navigating SPAs. Do NOT use for desktop apps or API-only integrations.
日本語の概要は準備中です。原文の説明を表示しています。
Searches for jobs on LinkedIn, filters by profile Must-haves, applies via Easy Apply, registers each application in DB.
日本語の概要は準備中です。原文の説明を表示しています。
実行スコア 未検証
インストール方法を見るインストールする前に、エージェントに与えられる指示の中身を確認できます。
Keyword: apply
The user says apply (or variants: "apply to N jobs", "postulate", "search jobs") and the full search and application flow is triggered.
node .agents/skills/browser-automation/scripts/browser.js open <url> --headed (Gold Rule 5) → notify user → wait for confirmationnode .agents/skills/browser-automation/scripts/browser.js for open/close/goto. See AGENTS.md "Browser session" and "Parallel execution" for details. Never call agent-browser open directly, never open Chrome directlynews or targets), pass --session apply-1 to linkedin-easy-apply.js and all browser.js exec commands. agent-browser sessions are created implicitly by the flag — no attach step needed. When done, just stop using the session (never close-all — that kills the browser for other agents too)memory skill):
node scripts/db.js "SELECT category, key, value, confidence, source FROM preferences WHERE user_id = <user_id> AND status = 'active' ORDER BY category, key"
node scripts/db.js "SELECT data->'strategy' AS strategy FROM users WHERE id = <user_id>"
Respect: apply_batch_size (max jobs per session), match_threshold (must_only / must_strong / must_strong_nice), relax_must_haves (loosen Must-have filtering). If apply_batch_size = 0, don't auto-apply, only present matches for manual approvalnode scripts/db.js "SELECT data->'profile' AS profile, data->'job_preferences' AS prefs, data->'personal_info' AS personal FROM users WHERE id = <user_id>"
node scripts/db.js "SELECT url FROM applications WHERE user_id = <user_id>"
Preferred: use the automation script (see AGENTS.md "Scripts de automatizacion"):
# Dry-run first to see what's available
node scripts/linkedin-easy-apply.js --dry-run --max 15
# Apply to top N jobs
node scripts/linkedin-easy-apply.js --max 10
# Run in a specific browser session (for parallel execution with other agents)
# Sessions are implicit in agent-browser — just pass --session apply-1 to every command
# Then run the script with --session:
node scripts/linkedin-easy-apply.js --max 10 --session apply-1
The script handles: search with Easy Apply filter, title filtering (only applies to tech roles — a job must match a tech keyword and not hit the blocklist of non-tech roles like attorney/sales/tutor/support; extendable via job_preferences.avoid in DB), form filling with standard answers, radio/combobox/checkbox handling, DB registration, and captcha detection (stops on captcha). The --session flag allows running in parallel with other agents by using an attached session instead of the default one.
Manual fallback (when script fails or forms have complex open-ended questions):
Search LinkedIn Jobs with filters:
f_AL=true)Paginate until collecting 20-30 candidates.
For each job, verify against profile Must-haves from users.data.job_preferences. Discard if:
users.data.profile.sector and job_preferences)Keep 10-15 matching positions.
Gate: only run this step if referrals is in strategy.sources_active. If not, skip to Step 3.
For each selected position, before submitting a cold application:
node scripts/linkedin-warm-sourcing.js --company "<Company>" --role "<Role>" --json
messages table (following Gold Rule 7 & user style profile).discovered.strategy.cold_outreach = false → skip recruiter outreach, proceed to Step 3 (cold apply only).strategy.cold_outreach = true → extract Recruiter / Hiring Manager info for the position, stage a recruiter outreach DM draft (Strategy #4 Multi-channel combo).For each selected job:
job_preferences.salary.value: min/max/currency). Convert to local currency if the form requires it. Never invent a salary number.personal_info.city + personal_info.country from DBjob_preferences.availability.value from DBnode scripts/db.js "INSERT INTO applications (user_id, platform, company, role, url, status, data) VALUES (<user_id>, 'linkedin', '<company>', '<role>', '<url>', 'applied', '<json>'::jsonb)" --write
data should include: match reason, method (easy_apply), location, questions_answered count.
Upon completion, present table with:
When applying directly to a company career page (not via LinkedIn Easy Apply), the same pre-flight rules apply. The flow is:
profile.full_name or personal_infoprofile.emailpersonal_info.phonepersonal_info.address, personal_info.city, personal_info.state, personal_info.postal_code, personal_info.countryjob_preferences.salary.value (min/max/currency). Convert to local currency if the form requires it.profile.linkedin_profileprofile.githubprofile.cv_path or personal_info.cv_pdf_pathprofile.experience[]profile.education[]profile.skills[] or profile.tech_stackprofile.languages[]platform = the ATS detected: 'lever', 'greenhouse', 'workday', etc.).<input type=file> value does not survive validation failures.https://api.npmjs.org/downloads/point/last-month/<package>, GitHub https://api.github.com/users/<user>/repos (stars, forks). Never invent figures (Gold Rule 5c applies to metrics too).status='pending_user_action' and data.blocker describing the exact artifact needed, then ask the user for it at the end of the round (Gold Rule 5d).onboarding (DB to register)profile (Must-haves to filter)dailyAll personal data lives in the DB, never in scripts or docs. The agent and scripts read form answers from:
| Data | DB location |
|---|---|
| Name, email, phone, CV path | users.data.profile (full_name, email, phone, cv_path) |
| Address, city, country | users.data.personal_info (address, city, state, country, postal_code) |
| Salary, availability, preferences | users.data.job_preferences (salary, availability, modalities, etc.) |
| Easy Apply form answers | users.data.form_answers (see keys below) |
| LinkedIn URL, blog URL | users.data.form_answers.linkedin_url, form_answers.blog_url |
Common Easy Apply question types and where to get the answers:
users.data.form_answers.<tech>_experienceusers.data.form_answers.english_level / spanish_levelusers.data.form_answers.locationusers.data.form_answers.current_companyusers.data.form_answers.linkedin_urlusers.data.form_answers.salary_usd / salary_cop / salary_usd_maxusers.data.form_answers.notice_period / availability_dateusers.data.form_answers.diversity_* (accessibility, gender, ethnicity)users.data.form_answers.disabilityusers.data.form_answers.genai_toolsusers.data.form_answers.aws_experienceusers.data.form_answers.english_comfortIf a key doesn't exist in form_answers: the script skips the field (doesn't invent it). The agent must stop, ask the user, save the answer to DB (jsonb_set on users.data.form_answers), then continue. Gold Rule 5c.
scripts/linkedin-easy-apply.js -- Apply via Easy ApplySearches jobs with Easy Apply filter, clicks, fills forms with standard answers, submits, registers in DB.
# Apply to the first 10 jobs (default)
node scripts/linkedin-easy-apply.js
# Keywords custom + limit
node scripts/linkedin-easy-apply.js --keywords '"<Role>" OR "<Skill>"' --max 5
# List only, don't apply
node scripts/linkedin-easy-apply.js --dry-run
# Output JSON
node scripts/linkedin-easy-apply.js --json
Flags: --keywords <q> (default: derived from DB profile.title + profile.skills), --location <loc> (default: from DB job_preferences.location), --max <n> (default 10), --dry-run, --json, --session <name> (for parallel execution)
Auto-fill: all values are read from users.data.form_answers (DB). The script fills: years of experience per tech, language level, location, current company, LinkedIn URL, salary, availability, GenAI tools, AWS, etc. Radios: Yes for skills, No for disability/sponsorship (configurable values in DB). Comboboxes: English/Spanish level, seniority (from DB).
Captcha: detects and stops with exit 1 + message. Never attempts to solve.
DB: registers each application with platform='linkedin', status='applied'.
scripts/linkedin-search.js -- Search posts for job openingsSearches LinkedIn posts, extracts author + vanity + email + content preview. Filters by relevance (AI/ML keywords) and dedupes.
# Basic search (human-readable output)
node scripts/linkedin-search.js '"<Role>" "hiring" <Region>'
# Search with more scrolls and JSON output (to pipe to other scripts)
node scripts/linkedin-search.js '"<Role>" "<City>" "hiring"' --scroll 3 --json
# Validated queries:
# '"<Role>" "hiring" <Region>' (most productive)
# '"<Role>" "<City>" "hiring"' (geo-specific)
# '"ingeniero IA" "buscamos"' (Spanish)
Flags: --scroll <n> (default 2), --json (raw JSON output)
Output JSON: [{author, vanity, email, content}, ...]
まだレビューはありません。使ってみた感想をお寄せください。
ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。
まだコメントはありません。最初のコメントを書いてみませんか。
Control a dedicated browser via agent-browser (Vercel). Use when automating web apps, scraping authenticated sites, filling forms, or navigating SPAs. Do NOT use for desktop apps or API-only integrations.
日本語の概要は準備中です。原文の説明を表示しています。
Periodic routine that runs news, cleans up inbox and applies if there's no recent activity. Designed to run 1-2 times per day.
日本語の概要は準備中です。原文の説明を表示しています。
Opens a local web dashboard that visualizes the job application pipeline, funnel stats, recent messages, and target company status. The agent opens it at the end of a round so the user can visually review the pipeline.
日本語の概要は準備中です。原文の説明を表示しています。
Safe Postgres CLI. Reads DATABASE_URL from .env, runs SQL, prints JSON. Read-only by default.
日本語の概要は準備中です。原文の説明を表示しています。
Autonomous user preference detection, storage and injection. The agent detects preferences from conversation, saves them to Postgres, and loads active ones at the start of every flow.
日本語の概要は準備中です。原文の説明を表示しています。
Reviews job application updates from Gmail, LinkedIn and platforms. Prepares drafts, presents executive summary by priority, validates with the user and sends replies.
日本語の概要は準備中です。原文の説明を表示しています。