# How Portal Search Skills Work in the AI Job Search Framework: Auto-Discovery and Configuration

> Discover how portal search skills in the AI Job Search Framework auto-discover and configure integrations without code changes. Easily add new job portals.

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

---

**Portal search skills in the AI Job Search Framework are self-contained integrations that live in `.agents/skills/` and are auto-discovered at runtime via their [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) metadata files, allowing new job portals to be added without any code changes.**

The MadsLorentzen/ai-job-search repository implements a modular, plug-and-play architecture where each job portal is treated as a portable skill. Understanding how these **portal search skills** are defined, discovered, and executed is essential for extending the framework with new data sources or customizing existing integrations.

## Portal Skill Architecture and Metadata Schema

Each portal search skill resides in its own subdirectory under `.agents/skills/` and is defined by a **[`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md)** file. According to the source code, this file follows a strict YAML front-matter schema that controls everything from CLI invocation to runtime enablement.

### Required SKILL.md Front-Matter Fields

The framework parses the following fields from every portal skill's metadata:

- **`name`**: Human-readable identifier (e.g., `linkedin-search`)
- **`version`**: Semantic version string (e.g., `1.0.0`)
- **`description`**: Short text used for trigger matching and documentation
- **`enabled`**: Boolean toggle determining participation in `/scrape` (defaults to `true`)
- **`allowed-tools`**: Declares the exact CLI command permitted (e.g., `Bash(bun run skills/<name>/cli/src/cli.ts *)`)
- **`context`**: Marks origin such as `fork` or `official`

### Directory Structure and Conventions

Portal skills follow a strict directory convention. The framework searches for files matching the glob pattern `.agents/skills/*/SKILL.md`. The body of each [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) documents CLI flags, usage examples, and links to [`url-reference.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/url-reference.md) files for API documentation.

## Auto-Discovery Mechanism During Scraping

When you execute the `/scrape` command, the job-scraper skill ([`.claude/skills/job-scraper/SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-scraper/SKILL.md)) orchestrates the discovery process. This implementation enables the framework to detect new portal search skills automatically without requiring restarts or recompilation.

### The Four-Step Discovery Process

The auto-discovery algorithm follows this exact sequence:

1. **Glob the skills directory** – The framework searches for all files matching `.agents/skills/*/SKILL.md`.
2. **Parse YAML front-matter** – Each file is read and parsed; the `enabled` field determines if the portal participates in the current scrape.
3. **Extract CLI invocation** – The `allowed-tools` entry provides the exact command string and expected flags.
4. **Execute portal CLI** – The scraper calls the command with query parameters transformed into portal-specific arguments.

### Conditional Execution via the Enabled Flag

The `enabled` boolean acts as a soft deletion mechanism. When set to `false`, the portal remains installed but the scraper skips it during execution. This allows users to temporarily disable underperforming portal search skills without removing configuration files from the filesystem.

## Implementing and Extending Portal Skills

Adding support for new job portals requires no modifications to the core codebase—only adherence to the [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) contract.

### Creating a New Portal Integration

To add a new portal search skill, create a directory under `.agents/skills/<portal-name>/` containing:

- A [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file with valid YAML front matter
- An optional CLI implementation (typically TypeScript/Bun-based)
- Documentation referencing the portal's API endpoints

Once dropped into place, the next `/scrape` execution automatically discovers and invokes the new skill.

### LinkedIn Search Skill Example

The LinkedIn integration at [`.agents/skills/linkedin-search/SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.agents/skills/linkedin-search/SKILL.md) demonstrates the implementation pattern:

```yaml
---
name: linkedin-search
version: 1.0.0
description: Search LinkedIn job listings using the public `jobs-guest` endpoint.
enabled: true      # set to false to keep installed but skip during /scrape

allowed-tools: Bash(bun run skills/linkedin-search/cli/src/cli.ts *)
---

```

When `/scrape` runs, the framework reads this file, verifies `enabled: true`, extracts the `bun run` command, and executes it with translated query flags. The `/add-portal` command (documented in [`.claude/commands/add-portal.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/add-portal.md)) uses identical glob logic to list available skills by reading `.agents/skills/*/SKILL.md` and printing tables of name, market, and data source.

## Summary

- Portal search skills in the AI Job Search Framework are self-describing units located in `.agents/skills/`.
- Each skill requires a [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file with YAML front matter specifying metadata, enablement status, and CLI invocation via `allowed-tools`.
- The job-scraper skill auto-discovers portals by globbing `.agents/skills/*/SKILL.md` and respecting the `enabled` toggle.
- New portals require zero code changes—simply add a properly formatted skill directory to participate in `/scrape`.
- The `allowed-tools` field declares exact Bash commands, enabling secure, declarative CLI execution without hardcoding portal logic into the scraper.

## Frequently Asked Questions

### What file format defines a portal search skill?

Portal search skills are defined by a [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file containing YAML front matter between triple dashes, followed by Markdown documentation. The front matter must include fields like `name`, `version`, `enabled`, and `allowed-tools` to be recognized by the discovery mechanism in the job-scraper skill.

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

Set `enabled: false` in the skill's [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) front matter. The framework will skip this portal during `/scrape` execution while preserving the skill's files and configuration for future reactivation, effectively disabling the integration without removal.

### Where is the portal discovery logic implemented?

The discovery algorithm resides in [`.claude/skills/job-scraper/SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-scraper/SKILL.md). This skill globs the `.agents/skills/` directory, parses each [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file, and orchestrates CLI invocation based on the `allowed-tools` declarations found in valid, enabled portal definitions.

### Can I add a custom job portal without modifying the framework source code?

Yes. The architecture supports plug-and-play portal search skills. Create a new directory under `.agents/skills/` with a valid [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file and optional CLI code. The `/scrape` command automatically discovers and executes it on the next run, requiring no changes to the core job-scraper implementation.