NewTriage Workflow

Trigger phrases: "go after new jobs", "new job triage", "check for new jobs", "job sweep", "full triage cycle", "sweep inbox for jobs"

Purpose: Full end-to-end job triage cycle - archive old emails, find new job alerts, scrape JDs, evaluate, produce structured review notes with folder structure.


Overview

This workflow runs a complete job triage cycle in 6 phases: 1. Setup and label discovery 2. Email cleanup (archive old investigation emails, label new ones) 3. Extract job URLs from emails and scrape JDs via Playwright 4. Evaluate each job against profile 5. Build structured output (folder note + individual job files) 6. Archive emails and update status

Runtime: Typically 20-45 minutes depending on number of new jobs found.


Phase 1: Setup

``` 1. slswitchuser(name: "matthias") 2. listgmaillabels(mnott@mnott.de) - find label IDs: - Jobs/01 - Investigating = Label_14 - Jobs/05 - Archived = Label_18 3. Find existing triage files in Notes/2026/MM/ 4. slgetpreferences() for evaluation criteria ```

Gmail label IDs (as of 2026-03-21): - Label_14 = Jobs/01 - Investigating - Label_15 = Jobs/02 - Applied - Label_16 = Jobs/03 - Interview - Label_17 = Jobs/04 - Rejected - Label_18 = Jobs/05 - Archived


Phase 2: Email Discovery and Label Management

CRITICAL: Email Label Workflow

``` Inbox → 01 - Investigating (Label14) → [triage/analyze] → 05 - Archived (Label18) ``` NEVER skip 01-Investigating. Every job alert email goes to Investigating first, regardless of age. Only move to 05-Archived AFTER the email has been fully triaged (all jobs extracted, evaluated, and recorded in the triage file). Putting unanalyzed emails directly into Archived is WRONG.

DO NOT archive old investigation emails automatically

Previous versions of this workflow archived everything in 01-Investigating. That's wrong - old emails may not have been triaged yet. Leave them in Investigating until this sweep processes them.

Find new job emails in inbox

Run ALL of these searches in parallel to catch every source:

``` # Core job platforms in:inbox from:linkedin.com in:inbox from:glassdoor in:inbox from:jobup in:inbox from:experteer in:inbox from:xing in:inbox from:jobscout24 in:inbox from:indeed

Recruiter platforms and staffing agencies

in:inbox from:mail.michaelpage.ch in:inbox from:sword OR from:tellentalerts.com in:inbox from:hays in:inbox from:robertwalters in:inbox from:randstad in:inbox from:adecco in:inbox from:manpower

ATS platforms (application confirmations, status updates)

in:inbox from:greenhouse.io in:inbox from:lever.co in:inbox from:workday in:inbox from:successfactors in:inbox from:smartrecruiters in:inbox from:teamtailor in:inbox from:personio in:inbox from:avature

Company career sites

in:inbox from:jobs2web in:inbox from:microsoft.com subject:career in:inbox from:cargill subject:job

Catch-all subject searches

in:inbox subject:"job alert" in:inbox subject:"nouvelles offres" in:inbox subject:"new jobs" in:inbox subject:"neue Stellen" in:inbox subject:"Stellenangebote" in:inbox subject:"Suggestions d'offres" ```

For each relevant email found: - ADD Label_14 (01 - Investigating) - REMOVE INBOX label - Do NOT add Label_18 (05 - Archived) - that happens AFTER triage

Email triage rules - what to label

Label as Investigating: - LinkedIn Job Alerts (jobalerts-noreply@linkedin.com, jobs-listings@linkedin.com) - Glassdoor job digests - JobUp alerts ("nouvelles offres", "Suggestions d'offres") - Experteer alerts ("Karrieremoglichkeiten") - Michael Page alerts (from: mail.michaelpage.ch) - Sword Services alerts (from: tellentalerts.com) - Google Job Alerts - XING job recommendations - JobScout24 recommendations - Company career site notifications (jobs2web, avature, etc.) - Direct company emails about specific job openings

Leave in inbox (DO NOT label): - Rejection emails (containing "unfortunately", "regret", "Absage", "leider", "rejection", "Votre candidature") - Interview invitations (handle separately) - Personal correspondence from recruiters

Skip/ignore (but still move to Investigating for completeness): - LinkedIn newsletters ("tips for job seekers") - XING birthday notifications - Generic career advice emails


Phase 3: Extract Jobs from ALL Email Sources

CRITICAL: Read full email bodies - ALWAYS

Every job alert email contains job data in the body text. NEVER rely on subject lines alone. Use get_gmail_message_content(message_id) for each email to extract ALL jobs.

Source-specific extraction patterns

LinkedIn Job Alerts: - Parse full body for URLs: linkedin.com/jobs/view/XXXXXXXXXX - Extract ALL job IDs (typically 5-15 per email) - Each email contains: job title, company, location, and LI job ID

JobUp.ch Alerts ("nouvelles offres", "Suggestions d'offres"): - Job titles, companies, locations, and full JobUp URLs are IN THE EMAIL BODY - URLs follow pattern: jobup.ch/fr/emplois/detail/{UUID}/ - DO NOT say "need Playwright to fetch" - the data is right there in the email - Extract: title, company, location, and full URL for each listing

Michael Page (from: mail.michaelpage.ch): - Job titles and links are in the email body - Extract all listed positions with URLs

Experteer: - Job titles may be in the email or may require login to see details - Extract what's available from the email body first

Glassdoor: - Daily digests contain company names and locations - Usually junior roles - scan quickly, most will be below threshold

Sword Services (from: tellentalerts.com): - Job titles and links are in the email body

XING: - Job recommendations with company names - Skip birthday/social notifications

ATS platforms (Greenhouse, Lever, Workday, etc.): - These are typically application status updates, not job alerts - Route to UpdateStatus workflow if they're rejection/interview notifications

Build master job list with REAL LINKS

EVERY job in the triage file MUST have a clickable link AND a verified JD. Never list a job based solely on an email digest title. The actual job page must be visited (via Playwright for LinkedIn) and the JD confirmed to exist before adding to the triage. Email digests (especially Sunday JYMBII weekly digests) often contain stale, closed, or non-existent listings. Subagents have been caught hallucinating job IDs from digest emails. Trust but verify - scrape the JD, then list.

Format: - LinkedIn: [LI XXXXXXXXXX](https://www.linkedin.com/jobs/view/XXXXXXXXXX) - JobUp: [JobUp](https://www.jobup.ch/fr/emplois/detail/UUID/) - Experteer: [Experteer](https://www.experteer.ch/career/view-jobs/SLUG) - Michael Page: [MP](URL from email) - Company sites: [Company](URL from email)

Pre-triage by title/level

CRITICAL: NEVER auto-exclude jobs. Include EVERYTHING in the triage list. Rank low if needed, but the user decides what to skip.

The user wants to see all jobs and make their own decisions. Your job is to rank, not to filter. "Head of Product Management" IS leadership. "Senior PM" IS a valid target. Do not presume to know what the user wants to skip.

Rank 4-5/5 (strong): - CIO, CTO, Director, Head of (ANY), VP, Lead, Principal, Architect (senior) - IC roles at senior+ level (Principal Engineer, Staff Architect, Lead Data Scientist, Field CTO) - Consulting, advisory roles at senior/manager+ level

Rank 2-3/5 (include but lower): - Pure coding IC roles (frontend, backend, full-stack developer) - Product management, project management (these ARE valid - never skip) - Academic positions (postdoc, PhD) - Domain stretch (different industry but transferable skills)

Rank 1/5 (include at bottom): - Junior, apprentice, intern, stagiaire, entry-level - Wrong country without remote option - Salary explicitly below CHF 150k

The ONLY thing you can omit entirely: Duplicate listings already in the triage file.

Scrape full JDs via Playwright (for promising candidates only)

LinkedIn requires logged-in session - Playwright only, no scribe/webfetch.

``` browsernavigate(url: "https://www.linkedin.com/jobs/view/{JOBID}") browser_evaluate(function: () => document.querySelector('main').innerText.substring(0, 5000)) ```

Duplicate check: Before scraping, search SeriousLetter for the company: ``` slsearchjobs(q: "{company_name}") ``` Skip if already tracked and not in "pending" state.


Phase 4: Evaluate

Score each job 1-5 against Matthias's profile:

Profile Summary (for scoring)

Scoring Rubric

| Score | Meaning | Criteria | |-------|---------|---------| | 5/5 | Pursue immediately | Perfect title + location + domain alignment | | 4/5 | Strong pursue | Good title + location, minor gaps | | 3/5 | Consider | Title or location mismatch, otherwise good fit | | 2/5 | Low priority | Multiple mismatches, some relevance | | 1/5 | Skip | Wrong domain, wrong level, or irrelevant |

Threshold

Only include in triage file if score >= 3/5. Jobs scoring 2/5 or below are noted briefly in the "below threshold" table and ignored.


Phase 5: Build Output

Triage File Location and Carry-Forward Logic

CRITICAL: Date-based triage files with carry-forward.

``` Notes/2026/MM/YYYY-MM-DD/Job Triage YYYY-MM-DD/ Job Triage YYYY-MM-DD.md ```

Rules: 1. Same date as previous sweep: Update the existing triage file in-place. Add new finds, update statuses. 2. New date: Create a new date folder, create a new triage file, and CARRY FORWARD the entire previous triage file as the base. Then add new finds on top. 3. Carry-forward means: Copy the full master list (all tiers, all links, all statuses) from the previous triage into the new file. The new file is the single source of truth. 4. ALL links must be preserved. When carrying forward, keep every column including Type and Link. Never strip links when copying tables.

Finding the previous triage file

```bash # Find the most recent triage file find "Notes/2026/" -name "Job Triage*" -type f | sort | tail -1 ```

File structure

Main file (folder note) structure

```markdown # Job Reviews YYYY-MM-DD

[Brief intro - emails processed, sources]

New Jobs (YYYY-MM-DD batch)

| # | Company | Title | Location | Score | Status | Notes | |---|---------|-------|----------|-------|--------|-------| | 1 | [[01 - Company - Title|Company]] | Title | Location | X/5 | New | Key notes | ...

Evaluated but below threshold

[Table of jobs scored < 3/5 with brief reason]

Pending from Previous Triage

[Table of jobs from old triage still needing action]

Already Applied / Closed / Not Pursuing

[Status summary of active pipeline]

Review Notes

[Counts: emails processed, jobs scraped, new jobs found, priorities for next session] ```

Individual job file structure

```markdown # NN - Company - Title

Date found: YYYY-MM-DD Source: [where found] URL: [LinkedIn/company URL] Location: [city, country] ([work arrangement]) Type: [Full-time/contract], [permanent/fixed-term] Score: X/5 Status: New / Pending / Applied


Job Description

[Company, title, key facts]

Key Responsibilities

[Bullet points from JD]

Requirements

[Key requirements]


Evaluation

Fit factors: [Why this fits Matthias] Concerns: [Gaps or issues] Next step: [Concrete action] ```

Note numbering

Individual job files within the review folder use sequential 2-digit numbers: 01, 02, 03... These are NOT the global 4-digit note numbers (those are used for applied job folders 0XXX).


Phase 6: Email Archiving (Post-Triage)

ONLY NOW move emails from 01-Investigating to 05-Archived. This is the final step, after all jobs have been extracted and recorded.

For each email that was fully processed in this sweep: ``` modifygmailmessage_labels: add: Label_18 (05 - Archived) remove: Label_14 (01 - Investigating) ```

Do NOT archive: - Rejection emails (leave in inbox for separate handling) - Emails that weren't fully processed in this sweep - Interview invitations

Completion notification

Send ntfy notification: "Job triage complete - N new jobs found, M emails archived"


Gmail Search Queries Reference

``` # Core job platforms in:inbox from:linkedin.com in:inbox from:glassdoor in:inbox from:jobup in:inbox from:experteer in:inbox from:xing in:inbox from:jobscout24 in:inbox from:indeed

Recruiter agencies (CRITICAL - easily missed)

in:inbox from:mail.michaelpage.ch in:inbox from:sword OR from:tellentalerts.com in:inbox from:hays in:inbox from:robertwalters in:inbox from:randstad

ATS and career platforms

in:inbox from:greenhouse.io in:inbox from:lever.co in:inbox from:workday in:inbox from:successfactors in:inbox from:smartrecruiters in:inbox from:teamtailor in:inbox from:personio in:inbox from:avature in:inbox from:jobs2web

Company-specific

in:inbox from:microsoft.com subject:career in:inbox from:cargill subject:job

Catch-all (run last to pick up stragglers)

in:inbox subject:"job alert" in:inbox subject:"nouvelles offres" in:inbox subject:"Suggestions d'offres" in:inbox subject:"new jobs" in:inbox subject:"neue Stellen" in:inbox subject:"Stellenangebote"

Currently in investigation label

label:Jobs/01---Investigating

Rejections (leave in inbox)

in:inbox (subject:rejection OR subject:Absage OR subject:"Votre candidature" OR subject:unfortunately) ```


Notes and Lessons Learned