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.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.