Install
$ agentstack add mcp-djh-001-multi-agent-job-search โ scanned ยท โ verified, works with Claude Code, Cursor, and more.
Security review
โ PassedNo issues found. Passed automated security review. ยท v0.1.0 How review works โ
- โ Prompt-injection patterns
- โ Secret / credential exfiltration
- โ Dangerous shell & filesystem operations
- โ Untrusted network calls
- โ Known-malicious package signatures
What it can access
- โ Network access No
- โ Filesystem access No
- โ Shell / process execution No
- โ Environment & secrets Used
- โ Dynamic code execution No
From automated source analysis of v0.1.0. โUsedโ means the capability is present in the source โ more access means more to trust, not that itโs unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work โAbout
multi-agent-job-search
[English](README.md) | [ไธญๆ](README.zh.md)
A standalone Python multi-agent system for job search, featuring 3 AI agents, 5 safety guardrails, and workflow orchestration.
What This Is
This repository contains a self-contained Python multi-agent pipeline that automates job-search preparation: triaging positions, tailoring resumes, and generating interview prep. It runs independently with no external platform dependencies beyond a Python environment and an LLM API key.
The project originated as a design-validated domain Skill on OpenCode (~400 lines of Markdown rules defining agent behavior, safety constraints, and workflows). That original design was battle-tested across 16+ real job applications and iteratively improved based on actual AI failure modes. The SKILL.md is preserved in docs/SKILL.md as design documentation.
This Python implementation translates those design rules into executable code:
- 3 agents (triage, resume, interview) calling an LLM via the OpenAI-compatible API
- 5 guardrails (G1-G5), 3 blocking and 2 advisory, checked deterministically after every agent step
- Workflow orchestrator coordinating the full pipeline with retry logic and state persistence
- State dual-write: every position update is saved to both a position-level JSON tracker and an aggregate dashboard
The system is self-contained: pip install -r requirements.txt, set an API key, and run python main.py apply --jd demo/jd.txt --profile demo/candidate-profile.md. No OpenCode installation is needed.
Architecture
flowchart LR
subgraph Input["Input"]
A["JD file + Candidate profile"]
B["parse_jd() / parse_profile()"]
A --> B
end
subgraph Pipeline["Agent Pipeline"]
C["TriageAgent"]
D["Track label:Safety / Stretch/ Boundary"]
F["ResumeAgent"]
G["Tailored markdownresume + ATS score"]
I["InterviewAgent"]
J["Predicted questions+ chase trees+ draft answers"]
L["StateTracker"]
C --> D
F --> G
I --> J
end
subgraph Guardrails["Guardrails"]
E["G1 (skipped)G2 (advisory)G3 (blocking)"]
H["G1 (blocking)G2 (advisory)G3 (blocking)G4 (advisory)"]
K["G1 (blocking)G2 (advisory)G3 (blocking)G5 (advisory)"]
end
subgraph Output["Output"]
M["Dual-write:position.json+ dashboard.json"]
end
subgraph Legend["Legend"]
L1["Input"]:::inputClass
L2["Triage"]:::triageClass
L3["Resume"]:::resumeClass
L4["Interview"]:::interviewClass
L5["State"]:::stateClass
L6["Blocking GR"]:::blockingClass
L7["Advisory GR"]:::advisoryClass
L8["Output"]:::outputClass
end
B --> C
D --> E
E --> F
G --> H
H --> I
J --> K
K --> L
L --> M
classDef inputClass fill:#d5d8dc,stroke:#839192,color:#1c2833
classDef triageClass fill:#d7bde2,stroke:#7d3c98,color:#1c2833
classDef resumeClass fill:#aed6f1,stroke:#2471a3,color:#1c2833
classDef interviewClass fill:#a9dfbf,stroke:#1e8449,color:#1c2833
classDef stateClass fill:#f9e79f,stroke:#b7950b,color:#1c2833
classDef blockingClass fill:#e74c3c,stroke:#c0392b,color:#fff
classDef advisoryClass fill:#f39c12,stroke:#d35400,color:#fff
classDef outputClass fill:#82e0aa,stroke:#27ae60,color:#1c2833
classDef guardrailClass fill:#f5cba7,stroke:#e67e22,color:#1c2833
class A,B inputClass
class C,D triageClass
class F,G resumeClass
class I,J interviewClass
class L stateClass
class E,H,K guardrailClass
class M outputClass
Pipeline steps:
- Parse inputs:
parse_jd()extracts title, company, responsibilities, requirements, and preferred qualifications from a markdown or plain-text JD file.parse_profile()reads a YAML, JSON, or markdown candidate profile into a typedCandidateProfiledataclass.
- TriageAgent evaluates the JD against the candidate profile along three dimensions -- hard-skill match, hold-ability (can the candidate pass now?), and salary/level gap -- and outputs a track label: ไฟๅบ (safety), ๅฒๅบ (stretch), or ่พน็ (boundary).
- ResumeAgent extracts JD keywords, selects track-appropriate bullets from the master CV, and generates a tailored resume with an AI-estimated ATS score. The output is plain markdown, no proprietary format.
- InterviewAgent predicts round-by-round interview questions, drafts answers from verified profile facts only, and builds chase trees (2-3 follow-up questions per concept).
- StateTracker writes two files after every step: a position-level JSON file (
_.json) and an aggregate dashboard (dashboard.json), maintaining consistency without a database.
Guardrails (G1-G5) wrap every agent step:
| Guardrail | Stage | Severity | What It Prevents | |:---|:---|:---|:---| | G1 Pre-promotion content firewall | Resume, Interview | Blocking | AI from writing unverified skills into resumes | | G2 Truth-source hierarchy | All stages | Advisory | Master CV from drifting away from verified facts | | G3 Real numbers only | All stages | Blocking | AI from inventing numbers to "strengthen" bullet points | | G4 Cross-track contamination | Resume | Advisory | Stretch-track framing from leaking into safety-track resumes | | G5 Rumor-vs-fact separation | Interview | Advisory | Scraped interview experiences from being treated as confirmed facts |
G1-G3 are blocking: a violation raises GuardrailViolation and halts the pipeline. G4-G5 are advisory: violations are logged as warnings but never block execution.
Quickstart
# Clone the repository
git clone https://github.com/DJH-001/multi-agent-job-search.git
cd multi-agent-job-search
# Create and activate a virtual environment
python -m venv .venv
.venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Configure your API key
copy .env.example .env
# Edit .env with your OpenAI-compatible API key and optional base URL
# Run the full pipeline with demo data
python main.py apply --jd demo/jd.txt --profile demo/candidate-profile.md
# Check pipeline status
python main.py status --output output
# Run the test suite
python -m pytest tests/ -v
Requirements: Python 3.9+, an OpenAI-compatible API key (tested with OpenAI and DeepSeek).
The .env.example file documents all configuration options:
OPENAI_API_KEY-- your API key (required)OPENAI_BASE_URL-- base URL for the API (defaults tohttps://api.openai.com/v1)LLM_MODEL-- model name (defaults togpt-4o, also tested withdeepseek-chat)
Project Structure
multi-agent-job-search/
โโโ main.py # CLI entry point (argparse: apply, status, mcp)
โโโ requirements.txt # openai, rich, python-dotenv, pytest, mcp
โโโ .env.example # API key and model configuration template
โโโ LICENSE # MIT
โ
โโโ src/
โ โโโ __init__.py
โ โโโ config.py # Loads OPENAI_API_KEY, OPENAI_BASE_URL, LLM_MODEL from env
โ โโโ schema.py # Dataclass contracts: CandidateProfile, JobDescription,
โ โ # TriageResult, ResumeOutput, InterviewPrep
โ โโโ orchestrator.py # JobSearchOrchestrator: 5 workflows (A-E),
โ โ # guardrail runner, retry logic, JD/profile parsers
โ โโโ mcp_server.py # MCP stdio server: 3 read-only tools for agent integration
โ โโโ agents/
โ โ โโโ __init__.py
โ โ โโโ triage.py # TriageAgent: JD vs profile assessment, track label output
โ โ โโโ resume.py # ResumeAgent: keyword extraction, bullet selection,
โ โ โ # ATS scoring, banned-word detection
โ โ โโโ interview.py # InterviewAgent: question prediction, draft answers,
โ โ # chase trees, round-by-round prep
โ โโโ guardrails/
โ โ โโโ __init__.py
โ โ โโโ g1_pre_promotion.py # G1: deterministic skill whitelist check (blocking)
โ โ โโโ g2_source_hierarchy.py # G2: [source:] annotation check (advisory)
โ โ โโโ g3_real_numbers.py # G3: invented-number detection (blocking)
โ โ โโโ g4_cross_track.py # G4: cross-track contamination via LLM + regex (advisory)
โ โ โโโ g5_rumor_vs_fact.py # G5: rumor-vs-fact firewall via LLM + regex (advisory)
โ โโโ state/
โ โโโ __init__.py
โ โโโ tracker.py # StateTracker: dual-write JSON persistence,
โ # JobState dataclass, dashboard aggregation
โ
โโโ tests/
โ โโโ __init__.py
โ โโโ test_guardrails_g1_g3.py # 28 tests: G1 (skill whitelist), G3 (fake numbers)
โ โโโ test_guardrails_g4_g5.py # 14 tests: G4 (cross-track), G5 (rumor-vs-fact)
โ โโโ test_tracker.py # 6 tests: save/load roundtrip, dual-write, dashboard
โ โโโ test_mcp.py # MCP server: tool registration, parsing, error handling, LLM skipif
โ
โโโ demo/
โ โโโ jd.txt # Sample JD: Senior Camera Hardware Engineer
โ โโโ candidate-profile.md # Sample profile: fictional hardware engineer
โ โโโ ็คบไพ-ๆ็ธๆบๅ
ฌๅธ-็กฌไปถๅทฅ็จๅธ/ # Example output from a completed pipeline run
โ โโโ resume.md
โ โโโ interview_prep_round1.json
โ โโโ position.json
โ
โโโ docs/
โ โโโ SKILL.md # Original OpenCode Skill design (~400 lines Markdown)
โ โ # Documents the design phase: 5 core principles,
โ โ # 5 guardrails, dual-track engine, promotion gate,
โ โ # workflows A-E, and writing rules
โ โโโ architecture.md # Detailed architecture documentation
โ
โโโ config/
โ โโโ skill.md # Copy of docs/SKILL.md (for OpenCode compatibility)
โ
โโโ scripts/
โ โโโ verify_guardrails.py # Standalone guardrail compliance verification
โ
โโโ templates/
โ โโโ position-analysis.md # Position analysis template
โ โโโ interview-prepare.md # Interview prep template
โ โโโ interview-review.md # Interview review template
โ
โโโ output/ # Created at runtime -- pipeline output directory
Platform vs My Work
This project has two layers: a design layer (the SKILL.md rules and methodology) and an implementation layer (the Python code). The table below separates what the OpenCode platform provided during the original deployment from what was designed and built independently.
| Capability | Provided by OpenCode Platform | Designed & Built | |:---|:---|:---| | Agent runtime (LLM calls, parallel dispatch, session management) | Built-in. OpenCode handles agent lifecycle, tool dispatch, and state persistence across sessions. | I designed which agent roles to dispatch for each workflow step and when to run them sequentially vs in parallel. | | SKILL.md rules (~400 lines) | Not provided. | Core design output. Domain rules: 5 principles, 5 guardrails, dual-track engine, promotion gate, workflows A-E, AI-slop ban lists. | | G1-G5 guardrails | Not provided. | Design: each guardrail addresses a real AI failure observed in practice. Implementation: src/guardrails/g1_*.py through g5_*.py -- deterministic checks with LLM assistance where needed. | | Dual-track engine | Not provided. | Three-track triage (ไฟๅบ/ๅฒๅบ/่พน็) with distinct governance strategies per track. | | Promotion gate | Not provided. | 5-step human-in-the-loop mechanism: learn, challenge list, self-certify, register, backflow. | | Python implementation | Not provided. | Entirely self-built. main.py (CLI), src/orchestrator.py (900 lines, 5 workflows), src/agents/ (3 agent files), src/guardrails/ (5 guardrail files), src/state/tracker.py (dual-write persistence), src/schema.py (dataclass contracts), src/config.py (env-based config). | | Test suite | Not provided. | Entirely self-built. 44 pytest tests across 3 test files covering G1-G5 guardrails and state management. | | State dual-write | Not provided. | Design: every update writes to two locations for distributed consistency. Implementation: StateTracker in src/state/tracker.py with atomic dual-write logic. | | File system architecture | Not provided. | Three-layer structure: truth-source (immutable facts), company/position (per-position isolation), market-research (cross-company intelligence). | | Workflows A-E | Not provided. | Five standard workflows with explicit step sequences: A (new position), B (update existing), C (re-derive all), D (detect source changes), E (interview iteration). | | Writing rules & ban lists | Not provided. | Specific rules for AI-generated professional text: banned AI-slop words, plain alternatives, bullet structure constraints. |
Bottom line: The OpenCode platform provided the agent runtime environment for the original deployment. The domain architecture, safety system, workflow definitions, and the complete Python reimplementation were designed and built independently. The Python system is fully standalone -- it requires no OpenCode installation to run.
Design Highlights
Five Core Principles
- Truth-source first. Every output (resume, cover letter, interview answer) must be traceable to verified personal data. The agent cannot invent or embellish.
- Position isolation. Preparing for one position does not give the agent access to another position's folder. No cross-contamination.
- Optional reference. If one position's output could help another, the agent must explicitly ask for permission before referencing it. No silent copying.
- State dual-write. Every progress update writes to two locations: the position-level tracker (detail) and the aggregate dashboard (summary). This is a distributed consistency problem solved through rule constraints.
- Completeness check. Before producing any material for a new position, the agent must cross-reference against the full verified facts inventory to prevent omissions.
Dual-Track Engine
Every incoming position is triaged into one of three governance tracks:
- Safety track (ไฟๅบ่ฝจ): Candidate can interview now and likely pass. Strategy: fast application, stable messaging, no over-packaging.
- Stretch track (ๅฒๅบ่ฝจ): Candidate wants the role but has a clear skill gap. Strategy: identify gaps explicitly, record genuine growth, gate new skills behind the promotion mechanism before they appear in materials.
- Boundary track (่พน็่ฝจ): Unclear fit. Strategy: default to conservative messaging, treat any new capability claims through the stretch-track promotion gate.
Tracks are determined through a 3-step evaluation (read JD, natural-language assessment, single label output) with strict rules against formulaic scoring and silent label rewriting. Label changes are append-only in a change log.
Promotion Gate
Content learned after the initial profile cannot appear in application materials until it passes the promotion gate:
- Record learning in the growth timeline (facts only, no future plans).
- AI generates a challenge list: hard questions interviewers might ask, evidence gaps, reproducibility challenges, statements that would fail under pressure.
- Human self-certifies: the candidate checks each item and confirms they can explain, reproduce, and handle pushback.
- Register the promotion: date, content, linked evidence, and the candidate's explicit confirmation statement.
- ๅๆต (backflow): promoted content flows back into the truth-source materials and master CV.
The AI never decides what is "ready." It only generates the challenge list and records the human's confirmation. This is a human-in-the-loop safety mechanism, not an AI evaluation
โฆ
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source โ we do not rehost the code.
- Author: DJH-001
- Source: DJH-001/multi-agent-job-search
- License: MIT
- Homepage: https://github.com/DJH-001/multi-agent-job-search
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.