How API Keys and Credentials Are Managed in the Hiring-Agent Using config.py

The config.py file in the interviewstreet/hiring-agent repository does not store any API keys or credentials; it only defines a DEVELOPMENT_MODE flag, while all sensitive secrets are injected at runtime via environment variables read through os.getenv().

The interviewstreet/hiring-agent project implements a strict separation between configuration flags and sensitive credentials to prevent accidental exposure of secrets. Rather than hard-coding API keys or storing them in version-controlled files, the application relies on environment variable injection, allowing seamless operation across local development, CI pipelines, and production deployments without code changes.

The Limited Role of config.py

The config.py module serves exclusively as a global configuration flag holder. According to the source code, it contains a single boolean value that indicates the application's runtime environment:


# config.py

DEVELOPMENT_MODE = True

This flag tells the rest of the application whether it is running in development mode, but it does not contain any API keys, tokens, or passwords. By keeping config.py free of secrets, the codebase remains safe to commit to public repositories while sensitive data stays outside version control.

Environment Variable Pattern for Secrets

Actual credentials—including LLM provider API keys—are read from environment variables at runtime using Python's os.getenv() function. This centralized pattern appears throughout the codebase wherever third-party services require authentication.

Loading Credentials in prompt.py

In prompt.py, the application retrieves configuration values and the Gemini API key through explicit environment variable lookups:


# prompt.py

import os

DEFAULT_MODEL = os.getenv("DEFAULT_MODEL", DEFAULT_MODEL_NAME)
PROVIDER = os.getenv("LLM_PROVIDER", DEFAULT_PROVIDER.value)
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "")

Each call specifies a fallback value—either a default constant or an empty string—ensuring the application can start even if variables are missing. When the key resolves to an empty string, authenticated operations are forced to fail gracefully, preventing runtime errors while requiring explicit credential provision for production use.

Local Development Setup with .env.example

The repository provides a template file, .env.example, that documents all required environment variables without containing actual values:


# .env.example (template)

DEFAULT_MODEL=gemini-pro
LLM_PROVIDER=gemini
GEMINI_API_KEY=your-gemini-api-key-here

Developers copy this template to a local .env file and populate it with their own keys. To configure the application locally, set your variables and run the code:


# Copy the template and edit with your values

cp .env.example .env

# Export variables manually or use python-dotenv

export GEMINI_API_KEY=abcd1234efgh5678
python main.py

Runtime Configuration Benefits

When initializing external clients, the application passes the retrieved environment variable directly to the service constructor:

import os

# Retrieve the key with fallback to empty string

GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "")

# Configure the client using the runtime value

client = GeminiClient(api_key=GEMINI_API_KEY)

This architecture provides three critical advantages:

  1. No secrets in source control – The codebase contains only placeholder values and templates, eliminating the risk of credential leakage through git history.
  2. Deployment flexibility – The same code runs in development, staging, and production environments, with each target injecting its own secrets through environment-specific configurations.
  3. Centralized access – Any module requiring credentials simply calls os.getenv, eliminating duplicated configuration logic and ensuring consistent secret handling across the application.

Summary

  • config.py contains only the DEVELOPMENT_MODE boolean flag and stores no API keys or credentials.
  • Secrets are injected at runtime via environment variables read through os.getenv() calls in modules like prompt.py.
  • .env.example provides a template for required variables, allowing developers to configure local environments without modifying source code.
  • Empty string fallbacks prevent runtime crashes when variables are missing, though authenticated operations require valid keys to function.
  • This pattern ensures the hiring-agent follows security best practices by keeping sensitive data out of version control while maintaining deployment flexibility.

Frequently Asked Questions

Does config.py store API keys in the hiring-agent?

No. The config.py file only defines a DEVELOPMENT_MODE flag. It contains no API keys, tokens, or credentials. All sensitive configuration is loaded from environment variables at runtime to prevent secrets from being committed to source control.

How do I configure API keys for local development?

Copy the .env.example template to a new .env file in the project root and populate it with your actual credentials. The application reads these variables at runtime using os.getenv(). Alternatively, export variables directly in your shell before running the application.

What happens if an environment variable is missing?

The code uses os.getenv("VARIABLE_NAME", "") with fallback values—typically empty strings or default constants. If a required API key is missing, the application will start but operations requiring authentication will fail or be skipped, forcing explicit credential configuration for sensitive actions.

Why use environment variables instead of storing keys in config.py?

Environment variables keep secrets out of the codebase, allowing the same code to run safely across development, staging, and production environments without modification. This pattern prevents accidental credential leaks through version control and enables different deployment targets to inject their own secrets securely.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →