← 返回
未分类 Key 中文

Automate Job Application

Automatically find and apply to jobs that match the user's resume using the resumex.dev API, web search, and browser automation. Use this skill whenever the...
根据用户简历自动匹配合适职位,利用 resumex.dev API、网络搜索和浏览器自动化投递。请在需要时使用此技能。
atharva-badgujar atharva-badgujar 来源
未分类 clawhub v2.1.0 1 版本 100000 Key: 需要
★ 1
Stars
📥 419
下载
💾 0
安装
1
版本
#latest

概述

Auto Job Applier Skill

This skill connects to the user's resumex.dev account, reads their resume data, matches them

to relevant jobs via web search, presents an approval list, then automatically applies to

approved jobs using browser automation — filling forms, answering screening questions, and

submitting applications. All applications are logged to the resumex.dev job tracker.

> Architecture: ResumeX stores resume data and the job tracker. OpenClaw's built-in AI

> does all the thinking and text generation (cover letters, screening answers, scoring).

> Web search finds jobs. Browser tool fills and submits applications.

> user_preferences.json remembers extra info between sessions.

> No third-party AI API keys required. This skill uses only OpenClaw's built-in LLM

> for all AI tasks (cover letter drafting, screening question answers, job scoring).

> The only external API key needed is RESUMEX_API_KEY.


Required Environment Variable

VariableRequiredDescription
---------
RESUMEX_API_KEYRequiredAPI key from resumex.dev → Dashboard → Resumex API
JOB_SEARCH_LOCATIONOptionalOverride city/country for job search
JOB_TYPEOptionalfull-time \part-time \contract \internship
REMOTE_ONLYOptionaltrue \false (default: false)
MAX_APPLICATIONSOptionalMax jobs to apply per session (default: 5)

How to set RESUMEX_API_KEY in OpenClaw:

  1. Go to resumex.dev → Dashboard → Resumex API
  2. Click Generate API Key
  3. In OpenClaw, go to Settings → Environment Variables
  4. Add RESUMEX_API_KEY with the copied key value

No other keys are needed. There is no Anthropic key, no OpenAI key, no other third-party service.


Privacy & Data Handling

> Read this before using the skill.

What data leaves your device

DataSent ToWhy
---------
Resume data (API read)resumex.devTo fetch your resume for job matching
Application logs (company, role, URL, status)resumex.devTo track your job applications
Your name, email, phone, LinkedInJob application websitesTo fill application forms
Cover letter (generated text)Job application websitesSubmitted as part of each application

Data sent to resumex.dev is governed by the resumex.dev Privacy Policy.

What stays local on your device

DataLocationWhat It Contains
---------
data/user_preferences.jsonSkill directory onlySalary expectation, visa status, notice period, address, gender, date of birth, ethnicity, veteran status, disability status, screening question answers

> ⚠️ user_preferences.json may contain sensitive personal data including date of birth,

> gender, ethnicity, veteran status, and disability status (only if you choose to save these

> when prompted during a form fill). This file is stored locally only and is **never sent

> to resumex.dev or any other server**. Review and restrict its filesystem permissions if needed:

> ```bash

> chmod 600 data/user_preferences.json

> ```

> To clear all saved preferences at any time:

> ```bash

> python3 scripts/manage_preferences.py reset

> ```

Sensitive fields in preferences

The following fields are only saved if you explicitly provide them when the agent encounters a

form field that requires them. You can decline to answer, skip the field, or delete a saved

value at any time:

  • gender — only for diversity/EEO forms
  • ethnicity — only for diversity/EEO forms (optional, you may leave blank)
  • veteran_status — only for U.S. government/contractor compliance forms
  • disability_status — only for compliance forms (optional)
  • date_of_birth — only for forms that legally require it

The agent will always tell you which form requires a sensitive field before asking for the value.

Auto-submit safeguard

The agent NEVER submits an application without your explicit approval. Step 6 of the workflow

always presents a formatted approval list and waits for your response before any browser

interaction begins. If you are testing, set MAX_APPLICATIONS=1 in your environment.


Workflow Overview

1. Fetch resume data from resumex.dev API
2. Load saved user preferences (salary, visa, screening answers)
3. Build a job-match profile (skills, roles, seniority, preferences)
4. Search the web for matching jobs (3–5 query permutations)
5. Score & rank each job against the resume (0–100)
6. ⛔ APPROVAL GATE — Present formatted list → wait for user selection
7. For each approved job:
   a. Generate a tailored cover letter (via OpenClaw's built-in AI)
   b. Navigate to application page via browser
   c. Fill form fields using resume data + preferences
   d. If a required field is unknown → ask the user → save to preferences
   e. Submit the application
   f. Log to resumex.dev job tracker
8. Present final summary with statuses

Step 1 — Fetch Resume from resumex.dev

Use the agent endpoint. All calls require Authorization: Bearer $RESUMEX_API_KEY.

# Fetch full resume data (GET /api/v1/agent — the correct endpoint)
curl -s -X GET "https://resumex.dev/api/v1/agent" \
  -H "Authorization: Bearer $RESUMEX_API_KEY" \
  -H "Content-Type: application/json"

> Note: The endpoint is /api/v1/agent (NOT /api/v1/agent/resume, which is deprecated).

> The helper scripts handle retries with exponential backoff automatically.

> Install dependencies first: pip3 install -r requirements.txt

Or via the helper script:

# Full resume JSON
python3 scripts/fetch_resume.py

# Extract a specific field for form filling
python3 scripts/fetch_resume.py --field email
python3 scripts/fetch_resume.py --json-path profile.phone

Expected response shape:

{
  "success": true,
  "data": {
    "activeResumeId": "...",
    "resumes": [{
      "id": "...",
      "data": {
        "profile": {
          "fullName": "...", "email": "...", "phone": "...",
          "location": "...", "summary": "...",
          "linkedin": "...", "github": "...", "website": "..."
        },
        "skills": [{"category": "...", "skills": ["...", "..."]}],
        "experience": [
          {
            "role": "...", "company": "...", "location": "...",
            "startDate": "...", "endDate": "...", "description": "..."
          }
        ],
        "education": [{"degree": "...", "institution": "...", "endDate": "...", "score": "..."}],
        "projects": [{"name": "...", "description": "...", "tags": ["..."]}],
        "achievements": [{"title": "...", "year": "..."}]
      }
    }]
  }
}

Parse the active resume:

workspace = response.data
activeResume = workspace.resumes.find(r => r.id === workspace.activeResumeId)
resumeData = activeResume.data

Error handling:

HTTP CodeCauseFix
---------
401RESUMEX_API_KEY is missing or invalidGo to resumex.dev → Dashboard → Resumex API → generate a new key
404Resume not created yetGo to resumex.dev → create and publish your resume
429Rate limitedWait 10 seconds, retry once

Step 2 — Load Saved User Preferences

Check for previously saved preferences that supplement the resume data:

python3 scripts/manage_preferences.py list

This returns any saved answers like salary expectation, visa status, notice period, etc.

If user_preferences.json doesn't exist yet, that's fine — it will be created when the

user is first asked for missing information.

Preference fields to look for:

  • salary_expectation — e.g. "8-12 LPA" or "$80,000-$100,000"
  • currency — e.g. "INR" or "USD"
  • notice_period — e.g. "30 days" or "Immediate"
  • visa_status — e.g. "No visa required (Indian citizen)"
  • work_authorization — e.g. "Authorized to work in India"
  • willing_to_relocate — true/false
  • preferred_work_type — "remote" | "hybrid" | "onsite"
  • screening_answers — dict of previously answered screening questions

Step 3 — Build Job-Match Profile

From the resume JSON and user preferences, extract and infer:

FieldHow to Derive
------
Target rolesLatest experience[0].role + adjacent titles (e.g. "Software Engineer" → "Backend Developer", "Full Stack Developer")
Key skillsTop 5–8 from flattened skills[].skills arrays + tech stack from experience[].description
SeniorityYears of experience calculated from earliest startDate to today
Locationprofile.location (override with JOB_SEARCH_LOCATION env var if set)
Job typeJOB_TYPE env var or preferred_work_type from preferences (default: full-time)
RemoteREMOTE_ONLY env var (default: false)
IndustryInfer from company names / job descriptions in experience

Example derived profile:

Roles: Software Engineer, Backend Developer, Full Stack Developer
Skills: Python, Django, React, PostgreSQL, Docker, AWS
Seniority: Mid-level (3 years)
Location: Pune, India
Type: Full-time
Remote: No preference
Salary: 8-12 LPA (from preferences)

Step 4 — Search for Matching Jobs

Use web_search to find real, current job postings. Run 3–5 targeted searches using different

query permutations to maximize coverage.

Query templates:

"{role}" "{top_skill}" jobs "{location}" site:linkedin.com OR site:naukri.com OR site:indeed.com
"{role}" "{top_skill}" "{second_skill}" hiring 2026
"{role}" remote jobs "{top_skill}" "{seniority}"
"{role}" "{top_skill}" jobs "{location}" "apply now" site:wellfound.com OR site:internshala.com

See references/job_boards.md for complete query patterns per board.

For each search result URL, use web_fetch to extract:

  • Job title
  • Company name
  • Location (or Remote)
  • Job URL (apply link)
  • Required skills (from description)
  • Nice-to-have skills
  • Experience required
  • Salary range (if visible)
  • Application method: form | easy-apply | email | redirect

Aim to collect 10–20 raw job postings before scoring.


Step 5 — Score & Rank Jobs

Score each job 0–100 against the resume profile:

FactorMax Points
------
Skill overlap (required skills matched)40
Role title match20
Seniority match15
Location / remote match15
Industry familiarity10

Formula:

score = (skills_matched / skills_required) * 40
      + role_title_match * 20    # 20 if exact, 10 if adjacent, 0 if unrelated
      + seniority_match * 15     # 15 if exact, 8 if ±1 level, 0 if 2+ off
      + location_match * 15      # 15 if match, 8 if remote, 0 if mismatch
      + industry_match * 10      # 10 if same industry, 5 if adjacent

Step 6 — Present Approval List to User ⛔

Present the top 10 matches in a formatted table. **The user MUST approve before any

applications are submitted.** Never auto-apply without explicit approval. Never skip this step.

Format:

🎯 Job Match Results for [Name]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

#   Score  Company          Role                     Location        Apply Method
──  ─────  ───────          ────                     ────────        ────────────
1   92     Acme Corp        Software Engineer        Pune (On-site)  🤖 Auto-apply
2   87     TechStartup      Backend Developer        Remote          🤖 Auto-apply
3   81     MegaCorp India   Full Stack Engineer      Mumbai          🤖 Auto-apply
4   76     DevShop          Python Developer         Pune (Hybrid)   🤖 Auto-apply
5   73     CloudCo          API Engineer             Remote          🤖 Auto-apply
6   70     DataInc          Backend Engineer         Bangalore       🔗 Manual (LinkedIn)
7   68     StartupXYZ       Software Developer       Remote          🤖 Auto-apply
8   65     BigTech          Junior SWE               Hyderabad       🤖 Auto-apply
9   62     ConsultFirm      Technical Consultant     Pune            📧 Email apply
10  58     SmallCo          Full Stack Developer     Remote          🤖 Auto-apply

🤖 = Agent will fill and submit the application automatically
🔗 = LinkedIn — agent will open the page, you submit manually
📧 = Email — agent will draft the email, you review and send

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Which jobs would you like to apply to?
Options: "all", "1,3,5", "1-5", "none", or "1-5 except 3"

Apply method classification:

  • 🤖 Auto-apply — Standard form-based application. Agent fills and submits.
  • 🔗 Manual (LinkedIn) — LinkedIn Easy Apply. Agent navigates to the page but user must submit.

(LinkedIn automated submission is disabled by default due to ToS concerns.)

  • 📧 Email apply — Agent drafts the application email for user review.
  • 🔗 Manual (redirect) — Redirects to external ATS. Agent navigates, user may need to complete.

Wait for the user to respond with their selection before proceeding.


Step 7 — Auto-Apply to Approved Jobs

For each job the user approved, execute the following sub-steps:

7a. Generate Cover Letter (via OpenClaw's built-in AI)

> No external AI API is used. Cover letters are generated by OpenClaw's own LLM.

The draft_cover_letter.py script reads resume data and job details, then outputs a structured

prompt. OpenClaw's agent uses that prompt with its built-in AI to generate the cover letter.

python3 scripts/draft_cover_letter.py \
  --resume /tmp/resume.json \
  --job_title "Software Engineer" \
  --company "Acme Corp" \
  --job_description "We are looking for..." \
  --output /tmp/cover_letter_acme.txt

The script outputs the generation prompt to stdout. The agent then:

  1. Reads the prompt
  2. Uses its built-in LLM to generate the cover letter text
  3. Saves the result to the --output path if specified

Cover letter structure:

  1. Hook (1 sentence): why this specific company/role excites the candidate
  2. Match (2–3 sentences): specific skills/experiences that directly map to job requirements
  3. Value add (1–2 sentences): a concrete result from their past work
  4. Close (1 sentence): call to action

Keep it under 200 words. Professional but human tone.

7b. Navigate to Application Page

Use the browser tool to navigate to the job's application URL:

browser: navigate to "{job_url}"

Wait for the page to load. Take a screenshot to confirm you're on the right page.

7c. Identify Form Fields

Analyze the page to identify the application form. Look for:

  • Input fields (,