# AI-Job-Search Extension Points: Portals, Templates, and Evaluation Criteria Explained

> Discover the three extension points of AI-Job-Search: portals, templates, and evaluation criteria. Customize your job search easily without altering core code.

- Repository: [Mads Lorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search)
- Tags: deep-dive
- Published: 2026-08-05

---

**The AI-Job-Search framework provides three extension points—portal skills, document templates, and evaluation criteria—that let you customize your job search without modifying core code.**

The [MadsLorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search) repository implements a modular architecture where all customizations happen through well-defined **AI-Job-Search extension points**. Whether you need to scrape a new job board, generate branded application documents, or enforce personal deal-breakers, the framework exposes clear interfaces for each capability.

## Portal Skills: Adding New Job Boards

**Portal skills** are self-contained CLI tools that query external job boards. Each skill lives in its own folder under `.agents/skills/` and follows a strict contract for discoverability.

### How Portal Skills Work

The framework automatically discovers any installed portal skill that conforms to this contract. According to the source code in [`README.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/README.md) lines 300-308, portal skills must implement:

- `search` and `detail` commands
- Multiple output formats: JSON, table, and plain text
- An `enabled:` flag in their [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) configuration

### Adding a New Portal

Use the built-in generator to scaffold a new portal:

```bash
/add-portal

```

This interactively creates:

```text
.agents/skills/<portal-name>/
├── SKILL.md          # Configuration with enabled: true

├── cli/
│   ├── package.json  # Zero dependencies

│   └── src/
│       ├── search.ts # Query the job board API

│       └── detail.ts # Fetch full job descriptions

```

The `/scrape` command then automatically includes your new portal in its execution cycle.

## Document Templates: Customizing CV and Cover Letter Output

**Document templates** control how the framework compiles application materials to PDF. The template extension point handles LaTeX, Typst, or other document systems through a standardized registration process.

### Registering a Custom Template

The `/add-template` command records:

- **Source file extension** (`.tex`, `.typ`, etc.)
- **Compile command** with full flags
- **Required fonts and style rules**
- **Page limit enforcement**

Example registration session:

```bash
/add-template

# • Source file: my_template.tex

# • Compile command: lualatex -interaction=nonstopmode my_template.tex

# • Fonts: Lato, Raleway

# • Page limit: 2

```

The template is stored under `templates/` and immediately wired into the `/apply` workflow. A test compile runs during registration to catch errors early.

## Evaluation Criteria: Defining Deal-Breakers and Preferences

**Evaluation criteria** shape how the framework scores and filters job postings. Unlike the structural extension points, criteria are defined declaratively in your profile and evaluated at runtime.

### Where Evaluation Criteria Are Defined

The primary location is [`.claude/skills/job-application-assistant/04-job-evaluation.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/04-job-evaluation.md). Edit this file to add personal rules:

```markdown

## Deal-breakers

- Salary must be ≥ 45,000 DKK per month
- Must not require on-call work
- Language: English (fluent) required

```

The language gate implementation in this file provides a concrete example: it hard-rejects postings requiring undeclared languages and flags borderline level mismatches.

### How Criteria Are Applied

Both `/rank` and `/apply` commands evaluate these criteria:

1. **Hard rejections** remove jobs from consideration entirely
2. **Scoring adjustments** alter ranking positions
3. **Flagged items** appear in human-readable output for manual review

## Key Files for Each Extension Point

| Extension Point | Primary File | Purpose |
|-----------------|--------------|---------|
| Portal skills | `.agents/skills/*/SKILL.md` | Contract definition per portal |
| Document templates | [`templates/README.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/templates/README.md) | Template setup instructions |
| Evaluation criteria | [`.claude/skills/job-application-assistant/04-job-evaluation.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/04-job-evaluation.md) | Scoring and filtering rules |

All three extension points are documented together in [`README.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/README.md) at lines 300-308, providing the architectural overview that ties the system together.

## Summary

- **Portal skills** extend job source coverage through CLI tools in `.agents/skills/` with automatic discovery via `/scrape`
- **Document templates** register compile pipelines for PDF generation through `/add-template`, storing assets in `templates/`
- **Evaluation criteria** define personal deal-breakers and scoring rules in [`04-job-evaluation.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/04-job-evaluation.md), consumed by `/rank` and `/apply`

## Frequently Asked Questions

### How do I disable a portal without deleting it?

Set `enabled: false` in the portal's [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file. The `/scrape` command skips any portal with this flag, preserving the skill for future use without removal.

### Can I use multiple template engines simultaneously?

Yes. The template extension point records the compile command per template, so you can register LaTeX-based CVs alongside Typst cover letters. Each document type uses its registered engine independently.

### Where should salary requirements be specified?

Place absolute minimums in [`04-job-evaluation.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/04-job-evaluation.md) as deal-breakers. For flexible preferences that affect scoring but don't auto-reject, add weighted criteria in the same file under a preferences section—the framework applies both during `/rank` evaluation.