# How to Add or Customize Portal Skills in the AI Job Search Framework

> Easily add or customize portal skills in the AI Job Search Framework. Learn to create skill descriptors, define search templates, and validate your configuration for enhanced job searching.

- Repository: [Mads Lorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search)
- Tags: how-to-guide
- Published: 2026-09-03

---

**To add or customize portal skills in the AI Job Search Framework, create a new directory under `.agents/skills/`, author a [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) descriptor with search templates and extraction rules, and validate your configuration using [`tools/lint_skills.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/lint_skills.py).**

The MadsLorentzen/ai-job-search repository implements a modular architecture where each job portal integration is encapsulated as a standalone skill. This design allows developers to add or customize portal skills by modifying structured descriptor files rather than editing core framework code. All portal skill definitions reside in the `.agents/skills/` directory and follow a strict schema enforced by built-in validation tools.

## Portal Skill Architecture Overview

Each portal skill is a self-contained package stored in its own subdirectory under `.agents/skills/`. The framework uses a thin-pointer architecture where the skill directory contains all logic required to search, scrape, and interact with a specific job board.

Every skill requires a [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file that serves as the single source of truth. This descriptor contains:

- **Metadata** including the portal name, description, and base URL
- **Search query templates** with interpolation variables for keywords, location, and seniority
- **Extraction rules** using CSS or XPath selectors to parse job titles, company names, locations, and job IDs
- **Optional CLI scripts** placed in a `cli/` subdirectory for custom authentication or rate-limit handling

The framework automatically discovers any folder containing a [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file during initialization, requiring no manual registration in central configuration files.

## Adding a New Portal Skill

### Create the Skill Directory

Begin by creating a new folder inside `.agents/skills/` named after the target portal. Use lowercase letters and hyphens for consistency with existing skills.

```bash
mkdir -p .agents/skills/example-jobs

```

### Configure the SKILL.md Descriptor

Create a [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file in your new directory. This markdown file defines the contract between the framework and the job portal.

```markdown
name: Example Jobs
description: A small demo portal used for testing.
baseUrl: https://www.example.com
searchEndpoint: /search
searchTemplate:
  query: "{{keyword}}"
  location: "{{location}}"
extract:
  title: "h1.job-title"
  company: ".company-name"
  location: ".job-location"
  id: "data-job-id"

```

The `searchTemplate` section maps user inputs to URL parameters or request bodies. The `extract` section provides CSS selectors that the scraper uses to parse HTML responses into structured data fields.

### Integrate Optional CLI Components

If your portal requires custom command-line utilities for authentication or session management, place these scripts in a `cli/` subdirectory within your skill folder. Reference these utilities in [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) using relative paths to ensure the framework locates them during execution.

### Validate the New Skill

Run the schema validator to ensure your [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) syntax complies with framework requirements.

```bash
python tools/lint_skills.py .agents/skills/example-jobs

```

After validation, update [`.claude/commands/add-portal.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/add-portal.md) to document the new portal. This ensures users can discover the skill using CLI commands like `ai-job-search add-portal example-jobs`.

## Customizing Existing Portal Skills

To customize an existing portal skill, edit its [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file directly within `.agents/skills/<portal-name>/`. Common customizations include refining search parameters or updating selectors after a target website redesign.

### Update Search Queries

Modify the `searchTemplate` section to add filters for contract type, remote work options, or date ranges. Ensure placeholder variables like `{{keyword}}` and `{{location}}` remain intact to maintain compatibility with the framework's query builder.

### Refine Data Extraction

When a job portal updates its HTML structure, adjust the CSS selectors in the `extract` section. Test changes locally before committing to ensure the scraper correctly identifies job titles, company names, and locations.

## Testing and Validation

Always verify new or modified skills using the provided test suite. Create a unit test file following the naming convention `tests/test_<portal>_skill.py` that asserts the search function returns expected fields for known queries.

Run the full validation pipeline:

```bash
python tools/lint_skills.py
pytest tests/test_example_jobs_skill.py -v

```

The linter checks every [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) against the required schema, while unit tests ensure the extraction logic functions correctly against live or mock HTML responses.

## Summary

- Portal skills reside in `.agents/skills/<portal-name>/` directories with a mandatory [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) descriptor
- The framework automatically discovers skills containing valid [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) files without requiring manual registration code
- Use [`tools/lint_skills.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/lint_skills.py) to validate schema compliance before deploying new skills
- Update [`.claude/commands/add-portal.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/add-portal.md) to document new portals for CLI users
- Customize existing skills by editing `searchTemplate` and `extract` sections within their respective [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) files

## Frequently Asked Questions

### Where are portal skill files located in the repository?

Portal skill files are located in the `.agents/skills/` directory. Each skill occupies its own subdirectory containing a [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) descriptor and optional `cli/` scripts. The framework scans this location during initialization to build the available portal registry.

### What is the purpose of the SKILL.md file?

The [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file serves as the single configuration source for a portal skill. It defines metadata, search query templates, CSS extraction selectors, and optional CLI tool references. This file must conform to the schema enforced by [`tools/lint_skills.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/lint_skills.py) for the skill to load correctly.

### How do I validate a new portal skill before using it?

Run `python tools/lint_skills.py .agents/skills/<your-portal>` to validate the [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) syntax and schema compliance. Additionally, create unit tests in `tests/test_<portal>_skill.py` and execute them with `pytest` to verify that search and extraction logic returns valid data structures.

### Can I customize an existing portal without creating a new one?

Yes. Navigate to the existing portal's directory under `.agents/skills/` and edit its [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file directly. You can modify search templates, update CSS selectors when websites change their layout, or add rate-limit handling without affecting other portal integrations.