# How Hiring Agent Extracts GitHub Usernames from Resume Profiles

> Learn how Hiring Agent extracts GitHub usernames from resumes by parsing profile links using regex and validation logic. Understand the technical process behind this feature.

- Repository: [HackerRank/hiring-agent](https://github.com/interviewstreet/hiring-agent)
- Tags: how-to-guide
- Published: 2026-07-17

---

**Hiring Agent extracts GitHub usernames by scanning the `profile.links` array in structured resume JSON, parsing URLs with domain-specific regex in [`transform.py`](https://github.com/interviewstreet/hiring-agent/blob/main/transform.py), and normalizing the results through validation logic in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py).**

The **interviewstreet/hiring-agent** repository processes candidate resumes to identify GitHub profiles for technical evaluation. Understanding how this open-source tool extracts GitHub usernames from resume profiles reveals a two-stage pipeline that combines flexible URL parsing with strict validation rules before storing data for downstream scoring.

## The Extraction Pipeline

### Detecting GitHub URLs in Resume Data

The extraction begins in [`transform.py`](https://github.com/interviewstreet/hiring-agent/blob/main/transform.py), where the pipeline iterates over the `profile.links` field of each resume. For every URL encountered, the system calls `extract_username_from_url(url, domain)` at line 154, passing a domain mapping that recognizes `"github.com": "GitHub"`. This function builds a domain-specific regular expression to isolate the path component representing the username.

### Parsing and Validating Usernames

Once a potential username is extracted, the raw value flows to `extract_github_username(github_url)` in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py) (line 116). This helper performs three critical operations:

- Strips trailing slashes, query strings, and fragments (`?…`, `#…`)
- Validates the string against the regex pattern `^[A-z0-9_-]+$`
- Returns the cleaned username or `None` if validation fails

### Storing Results for Downstream Processing

After validation, the username is stored in the transformed candidate record under the key `github_username`. This field feeds directly into [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) and the `GitHubProfile` Pydantic model defined in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py), enabling subsequent API calls to `https://api.github.com/users/<username>`.

## Implementation Example

The following code demonstrates the complete extraction flow according to the hiring-agent source code:

```python

# Resume structure with profile links

resume = {
    "profile": {
        "links": [
            "https://github.com/jane-doe",
            "https://linkedin.com/in/jane-doe"
        ]
    }
}

# Extraction logic from transform.py (line 154)

for url in resume["profile"]["links"]:
    domain = url.split("://")[1].split("/")[0]
    if domain == "github.com":
        username = extract_username_from_url(url, domain)
        if username:
            # Validation via github.py (line 116)

            username = extract_github_username(url)
            resume["github_username"] = username

```

Running this pipeline produces the validated username:

```python
>>> resume["github_username"]
'jane-doe'

```

## Summary

- **URL Detection**: [`transform.py`](https://github.com/interviewstreet/hiring-agent/blob/main/transform.py) scans `profile.links` and identifies GitHub URLs using domain matching at line 154
- **Username Extraction**: `extract_username_from_url()` parses the path component using regex patterns tailored to the domain
- **Validation**: `extract_github_username()` in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py) sanitizes input and enforces the `^[A-z0-9_-]+$` pattern at line 116
- **Storage**: Valid usernames are stored under `github_username` for API consumption by [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) and the `GitHubProfile` model

## Frequently Asked Questions

### What file handles the initial GitHub URL detection?

The [`transform.py`](https://github.com/interviewstreet/hiring-agent/blob/main/transform.py) module handles initial detection by iterating over `profile.links` and matching domains against a mapping that includes `"github.com": "GitHub"`, specifically through the `extract_username_from_url` function at line 154.

### How does Hiring Agent validate extracted GitHub usernames?

Validation occurs in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py) through the `extract_github_username()` function at line 116, which strips URL artifacts and validates against the regex `^[A-z0-9_-]+$`, returning `None` for invalid inputs.

### What happens if a resume contains an invalid GitHub URL?

When `extract_github_username()` cannot parse a valid username or validation fails, the function logs a warning and returns `None`, preventing corrupted data from entering the candidate record under `github_username`.

### Where is the extracted username stored in the candidate record?

The validated username is stored in the transformed candidate object under the key `github_username`, which is later used by [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) to fetch repository data via the GitHub API and populate the `GitHubProfile` model defined in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py).