Recruitment Workflow Automation
Execute the end-to-end recruitment pipeline without a TUI. You (the AI agent) perform candidate evaluation and email drafting directly - no external LLM calls needed.
When to Use This Skill
- Processing candidate lists from LinkedIn/Evaboot exports
- Evaluating candidates against job descriptions
- Enriching contacts to find email addresses
- Drafting and sending personalized outreach emails
- Managing recruitment campaigns stored in MinIO
Prerequisites
Environment Variables Required
# MinIO Configuration
MINIO_ENDPOINT=minio.hyperplane-minio.svc.cluster.local:9000
MINIO_ACCESS_KEY=<access_key>
MINIO_SECRET_KEY=<secret_key>
MINIO_BUCKET=candidates
MINIO_SECURE=false
# Mailgun Configuration
MAILGUN_API_KEY=<api_key>
MAILGUN_DOMAIN=<domain>
MAILGUN_FROM_EMAIL=recruiting@company.com
MAILGUN_FROM_NAME=Company Recruiting
# Clay Configuration (for contact enrichment)
CLAY_ENDPOINT=<clay_webhook_url>
# Lever Configuration (for job descriptions)
LEVER_API_KEY=<api_key>
Python Dependencies
The helper scripts use inline dependencies (PEP 723). Run with uv run:
uv run scripts/minio_client.py --help
Complete Workflow
Phase 1: Setup & Data Loading
Step 1.1: List Available Candidate CSVs
uv run scripts/minio_client.py list-csvs
Returns all CSV files in the candidates bucket under raw_data/ prefix.
Step 1.2: Download and Parse Candidate List
uv run scripts/minio_client.py download-csv "raw_data/your-list/candidates.csv"
Returns JSON array of candidate records. Each candidate has:
name,email(may be empty),linkedin_urlcurrent_company,current_title- Raw CSV data preserved
Step 1.3: Fetch Job Description from Lever
uv run scripts/lever_client.py list-postings
uv run scripts/lever_client.py get-posting <posting_id>
Or create a custom JD inline for evaluation.
Phase 2: Candidate Evaluation
YOU (the AI agent) perform this step directly. No LLM API calls needed.
For each candidate, evaluate against the job description:
Read the candidate profile:
- Name, current title, current company
- Years of experience (if available)
- LinkedIn URL for additional context
Compare against JD requirements:
- Technical skills match
- Experience level appropriate
- Industry/domain relevance
Assign fit score:
1= Qualified (proceed to outreach)0= Not qualified (skip or review later)
Write brief reasoning (2-3 sentences):
- Why they fit or don't fit
- Key strengths or gaps
Example evaluation output:
{
"email": "john@example.com",
"fit_score": 1,
"reasoning": "Strong backend experience at Series B startup. 5 years Python/Go matches our stack. Previous ML platform work aligns with role."
}
Phase 3: Contact Enrichment (If Needed)
For candidates without email addresses:
uv run scripts/clay_client.py enrich "<linkedin_url>"
Returns enriched email if found. Save enrichment results:
uv run scripts/minio_client.py save-enrichment "raw_data/your-list/candidates.csv" "<linkedin_url>" "<email>"
Phase 4: Email Drafting
YOU (the AI agent) draft emails directly.
For each qualified candidate, create a personalized outreach email:
Guidelines:
- Subject: Specific, mentions their background (not generic "Opportunity")
- Opening: Reference something specific about them (company, role, project)
- Value prop: Why this role/company is relevant to THEM
- Call to action: Clear next step (call, reply, calendar link)
- Length: Under 150 words - busy people skim
Email Template Structure:
Subject: [Specific hook related to their background]
Hi [First Name],
[1 sentence showing you know their background - current role, company, or achievement]
[2-3 sentences on the opportunity and why it's relevant to them specifically]
[Clear call to action - what do you want them to do?]
Best,
[Sender Name]
Save Draft to MinIO:
uv run scripts/minio_client.py save-draft \
--job-id "<job_id>" \
--candidate-email "<email>" \
--subject "<subject>" \
--body "<body>"
Phase 5: Email Sending
Step 5.1: Send Individual Email
uv run scripts/mailgun_client.py send \
--to "<recipient_email>" \
--subject "<subject>" \
--body "<body>"
Step 5.2: Send Follow-up (Threading)
uv run scripts/mailgun_client.py send-followup \
--to "<recipient_email>" \
--subject "Re: <original_subject>" \
--body "<followup_body>" \
--in-reply-to "<original_message_id>"
Step 5.3: Record Sent Email
uv run scripts/minio_client.py record-sent \
--campaign "<campaign_folder>" \
--candidate-email "<candidate_email>" \
--recipient-email "<recipient_email>" \
--subject "<subject>" \
--message-id "<message_id>"
Phase 6: Results & Reporting
Save Evaluation Results
uv run scripts/minio_client.py upload-results \
--source-path "raw_data/your-list/candidates.csv" \
--results '<json_array_of_results>'
Creates raw_data/your-list/candidates_results.csv with evaluation data.
Check Campaign Status
uv run scripts/minio_client.py get-sent-emails "<campaign_folder>"
Workflow Checklist
- Verify environment variables are set
- List and select candidate CSV from MinIO
- Download candidate data
- Get or create job description
- Evaluate each candidate (YOU do this directly)
- Enrich contacts missing emails (via Clay)
- Draft personalized emails (YOU do this directly)
- Send emails via Mailgun
- Record sent emails and save results to MinIO
Error Handling
Common Issues
| Error | Cause | Solution |
|---|---|---|
| MinIO connection failed | Wrong endpoint or credentials | Check MINIO_* env vars |
| CSV encoding error | Non-UTF8 file | Script auto-detects encoding |
| Clay timeout | Enrichment taking too long | Retry or skip candidate |
| Mailgun 401 | Invalid API key | Verify MAILGUN_API_KEY |
Retry Logic
All scripts include exponential backoff. If a transient error occurs, wait and retry:
# Scripts automatically retry 3 times with backoff
uv run scripts/minio_client.py download-csv "path/to/file.csv"
File Reference
scripts/minio_client.py- MinIO operations (list, download, upload, drafts)scripts/mailgun_client.py- Email sending with threading supportscripts/clay_client.py- Contact enrichment via Clay webhookscripts/lever_client.py- Fetch job descriptions from Lever APIreferences/workflow-stages.md- Detailed stage documentationreferences/email-templates.md- Email drafting best practices
Example Session
User: Process the ex-founders candidate list for the SDE role
Agent activates recruit-workflow skill:
1. Lists CSVs, finds "raw_data/ex-founders-sf/candidates.csv"
2. Downloads 47 candidates
3. Fetches SDE job posting from Lever
4. Evaluates each candidate:
- 12 qualified (fit_score=1)
- 35 not qualified (fit_score=0)
5. Enriches 8 candidates missing emails via Clay
6. Drafts 12 personalized emails
7. Sends via Mailgun (or saves as drafts for review)
8. Uploads results CSV to MinIO