# How the Hiring Agent Project Authenticates with GitHub Using github.py

> Learn how the Hiring Agent project authenticates with GitHub using github.py by reading your GITHUB_TOKEN environment variable and attaching it to API requests.

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

---

**The project authenticates with GitHub through the `_fetch_github_api` function in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py), which optionally reads a personal access token from the `GITHUB_TOKEN` environment variable and attaches it as an `Authorization` header to REST API requests.**

The `interviewstreet/hiring-agent` repository interacts with the GitHub REST API to fetch repository and user data. Understanding how it handles authentication is crucial for developers who need higher rate limits or access to private repositories. This article examines the authentication mechanism implemented in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py), detailing how the code manages tokens, constructs headers, and handles rate limiting.

## Authentication Flow in github.py

### Token Retrieval from Environment Variables

The authentication process begins inside the `_fetch_github_api` function, where the code attempts to retrieve credentials from the environment. At lines 30-33, the function checks for the `GITHUB_TOKEN` variable using `os.environ.get("GITHUB_TOKEN")`. If the variable exists, the token is stored locally; if not, the request proceeds unauthenticated.

### Authorization Header Construction

When a token is present, the code constructs an **Authorization** header following GitHub's token-based authentication scheme. At lines 33-34, the header is formatted as `token <GITHUB_TOKEN>` and added to the headers dictionary:

```python
headers["Authorization"] = f"token {github_token}"

```

This header is then passed to the `requests.get` call at line 52, ensuring authenticated access to the API.

### Rate Limit Handling and Fallback Behavior

The implementation includes sophisticated rate limit management. After each API call (lines 55-98), the code parses the `X-RateLimit-Remaining`, `X-RateLimit-Limit`, and `X-RateLimit-Reset` headers. Unauthenticated requests are limited to **60 requests per hour**, while authenticated requests enjoy a **5,000 request quota**. When limits are low, the function sleeps until the reset time and logs warnings suggesting the use of `GITHUB_TOKEN` for higher throughput.

## Configuration and Development Mode

### Local Caching Behavior

Authentication state does not affect cache keys in development mode. As implemented in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py) (lines 36-44 and 104-110), the response caching mechanism stores API responses locally regardless of whether a token was used. This means the same cached file retrieves whether the original request was authenticated or not, as long as the URL matches.

### Environment Configuration Files

The repository includes an `.env.example` file demonstrating the expected `GITHUB_TOKEN` format. Additionally, [`config.py`](https://github.com/interviewstreet/hiring-agent/blob/main/config.py) defines `DEVELOPMENT_MODE`, which toggles the caching behavior used by the GitHub module.

## Practical Implementation Examples

### Running Without Authentication

```bash

# No token set – limited to 60 requests/hour

python -m github https://github.com/example_user

```

### Authenticating with a Personal Access Token

```bash
export GITHUB_TOKEN=ghp_YourPersonalAccessTokenHere
python -m github https://github.com/example_user

```

The token is automatically read inside `_fetch_github_api` and attached to every API call.

### Programmatic Access from Another Module

```python
from github import _fetch_github_api

status, data = _fetch_github_api(
    "https://api.github.com/users/octocat",
    params=None
)

if status == 200:
    print(data["name"])

```

The same authentication logic (environment variable → header) applies to all calls.

## Summary

- The `_fetch_github_api` function in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py) handles all GitHub API authentication centrally
- Authentication is optional and relies on the `GITHUB_TOKEN` environment variable
- When present, the token is formatted as `token <GITHUB_TOKEN>` in the Authorization header
- Unauthenticated requests are limited to 60/hour versus 5,000/hour for authenticated requests
- The implementation includes automatic rate-limit detection and sleep logic based on `X-RateLimit-Reset`
- Caching in development mode is independent of authentication state

## Frequently Asked Questions

### Is authentication required to use github.py?

No. The module functions without a token, falling back to unauthenticated requests limited to 60 API calls per hour according to the source code. However, for production usage or higher volume operations, setting `GITHUB_TOKEN` is strongly recommended to avoid rate-limit blocks.

### How do I configure the GitHub token for this project?

Set the `GITHUB_TOKEN` environment variable with your personal access token before running the script. The code reads this at lines 30-33 in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py) using `os.environ.get("GITHUB_TOKEN")`, then attaches it to the Authorization header at lines 33-34.

### What happens when the rate limit is exceeded?

The code automatically detects low rate limits by checking the `X-RateLimit-Remaining` header. When approaching zero, it calculates the reset time from `X-RateLimit-Reset` and sleeps until that timestamp (implemented in lines 55-98), logging the remaining wait time and suggesting authentication for higher quotas.

### Does authentication affect the local cache?

No. According to the source code in lines 36-44 and 104-110, the caching mechanism does not include the authentication state in the cache key. This means the same cached response retrieves regardless of whether the original request used a token, though the initial fetch respects the authentication provided.