代理的环境变量
os.environ、os.getenv(),以及为什么绝不能在源代码中硬编码密钥。
代理的环境变量 是 CoddyKit 上的免费 AI Agents 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Agents 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Agents 课程共包含 4 节课。
为什么不能将 API 密钥硬编码
直接将 API 密钥硬编码到源代码中,是最常见且代价最高的安全错误之一。提交到版本控制系统的密钥对所有有权访问该仓库的人可见,包括未来的贡献者、持续集成系统以及任何在网上找到该仓库的人。
Git 历史记录问题
即使之后从代码中删除硬编码的密钥,它仍会保留在 Git 历史记录中。任何克隆该仓库并运行 git log 或 git show 的人都能找到它。密钥绝不能进入版本控制系统。
import os
os.environ['OPENAI_API_KEY'] = 'sk-proj-abc123def456' # simulate deployment env
OPENAI_API_KEY = os.environ['OPENAI_API_KEY']
print('Key loaded from environment — never hard-coded')os.environ[] 与 os.getenv()
读取环境变量有两种方式。变量缺失时,os.environ['KEY'] 会引发 KeyError,适用于必需密钥。变量缺失时,os.getenv('KEY', default) 会返回默认值,适用于可选设置。
import os
os.environ['OPENAI_API_KEY'] = 'sk-proj-demo-key'
try:
openai_key = os.environ['OPENAI_API_KEY']
except KeyError:
print('ERROR: OPENAI_API_KEY environment variable is not set!')
raise
model = os.getenv('AGENT_MODEL', 'gpt-4o-mini')
timeout = float(os.getenv('AGENT_TIMEOUT', '30'))
log_level = os.getenv('LOG_LEVEL', 'INFO')
max_steps = int(os.getenv('AGENT_MAX_STEPS', '20'))
print(f'Model: {model}, Timeout: {timeout}s, Log: {log_level}')启动时验证必需的环境变量
最佳实践之一是在启动时检查所有必需的环境变量,并通过清晰的错误消息快速失败。这样可以避免密钥缺失时,代理循环运行到深层位置才发生难以调试的运行时错误。
import os
import sys
REQUIRED_VARS = [
'OPENAI_API_KEY',
'SEARCH_API_KEY',
'DATABASE_URL'
]
def check_required_env_vars():
missing = [var for var in REQUIRED_VARS if not os.getenv(var)]
if missing:
print('FATAL: Missing required environment variables:')
for var in missing:
print(f' - {var}')
print('\nSet these in your .env file or shell environment.')
sys.exit(1)
print(f'All {len(REQUIRED_VARS)} required environment variables are set.')
# Call this at the very start of your agent:
# check_required_env_vars()
if __name__ == '__main__':
for var in REQUIRED_VARS:
os.environ.setdefault(var, 'demo-value')
check_required_env_vars()
12-Factor App 原则
12-Factor App 方法论为现代软件定义了最佳实践。第三项原则:将配置存储在环境中。所有因部署环境而变化的内容(开发、预发布、生产环境),包括 API 密钥、URL 和功能开关,都应来自环境变量,而不是代码。
import os
os.environ['OPENAI_API_KEY'] = 'sk-proj-demo'
os.environ['SEARCH_API_KEY'] = 'tvly-demo'
os.environ['DATABASE_URL'] = 'postgresql://user:pass@localhost/agentdb'
config = {
'openai_key': os.environ['OPENAI_API_KEY'],
'search_key': os.environ['SEARCH_API_KEY'],
'database_url': os.environ['DATABASE_URL'],
'redis_url': os.getenv('REDIS_URL', 'redis://localhost:6379'),
'enable_caching': os.getenv('ENABLE_CACHING', 'true') == 'true',
'max_results': int(os.getenv('MAX_RESULTS', '10')),
'log_level': os.getenv('LOG_LEVEL', 'INFO'),
'env': os.getenv('ENV', 'development')
}
print('Config loaded from environment:', config['env'])在 Shell 中设置环境变量
使用 export(Mac/Linux)或 set(Windows)在终端会话中设置环境变量。这些变量可供该会话中运行的任何程序使用。
# Mac/Linux (bash/zsh):
# export OPENAI_API_KEY='sk-proj-your-key-here'
# export AGENT_MODEL='gpt-4o-mini'
# python agent.py
# Windows (Command Prompt):
# set OPENAI_API_KEY=sk-proj-your-key-here
# python agent.py
# Windows (PowerShell):
# $env:OPENAI_API_KEY = 'sk-proj-your-key-here'
# python agent.py
# One-liner (temporary, only for this command):
# OPENAI_API_KEY='sk-proj-...' python agent.py
print('Shell exports set env vars for the current session only')在代码注释中列出必需变量
直接在源代码中记录代理所需的环境变量。新开发者只需阅读代理文件的开头,就应能准确知道需要配置哪些内容。
# agent.py
#
# REQUIRED ENVIRONMENT VARIABLES:
# OPENAI_API_KEY OpenAI API key (get from platform.openai.com)
# SEARCH_API_KEY Tavily search API key (get from tavily.com)
#
# OPTIONAL ENVIRONMENT VARIABLES:
# AGENT_MODEL LLM model (default: gpt-4o-mini)
# AGENT_MAX_STEPS Max loop iterations (default: 20)
# LOG_LEVEL Logging verbosity: DEBUG|INFO|WARNING (default: INFO)
# DATABASE_URL PostgreSQL URL (default: none, disables memory storage)
#
# EXAMPLE SETUP:
# cp .env.example .env
# Edit .env with your keys
# python agent.py --query 'Your question'
print('Document required variables at the top of each agent file')安全访问嵌套配置
对于包含许多配置选项的代理,可以构建一个配置类,在同一位置读取并验证所有环境变量。这样可以集中进行验证,并使其余代码更加整洁。
import os
class AgentConfig:
def __init__(self):
self.openai_key = self._require('OPENAI_API_KEY')
self.search_key = self._require('SEARCH_API_KEY')
self.model = os.getenv('AGENT_MODEL', 'gpt-4o-mini')
self.max_steps = int(os.getenv('AGENT_MAX_STEPS', '20'))
self.log_level = os.getenv('LOG_LEVEL', 'INFO')
self.env = os.getenv('ENV', 'development')
def _require(self, key: str) -> str:
value = os.getenv(key)
if not value:
raise EnvironmentError(
f'Required environment variable {key} is not set. '
f'See .env.example for setup instructions.'
)
return value
# config = AgentConfig() # raises clear error if any key is missing
# client = openai.OpenAI(api_key=config.openai_key)
if __name__ == '__main__':
os.environ.setdefault('OPENAI_API_KEY', 'sk-demo-1234')
os.environ.setdefault('SEARCH_API_KEY', 'demo-search-key')
config = AgentConfig()
print(f'Model: {config.model}, max_steps: {config.max_steps}, env: {config.env}')
在日志中隐藏密钥
绝不要记录原始 API 密钥。如果需要为调试记录配置,请隐藏除最后 4 个字符之外的全部内容。这样既能确认密钥已加载,又不会暴露密钥。
import os
def mask_key(key: str) -> str:
if not key or len(key) < 8:
return '****'
return '*' * (len(key) - 4) + key[-4:]
def log_config_summary(config: dict):
print('Agent configuration:')
for name, value in config.items():
if 'key' in name.lower() or 'secret' in name.lower() or 'token' in name.lower():
print(f' {name}: {mask_key(value)}')
else:
print(f' {name}: {value}')
config = {
'openai_key': os.getenv('OPENAI_API_KEY', ''),
'model': 'gpt-4o-mini',
'max_steps': '20'
}
log_config_summary(config)
# openai_key: ****abcd
# model: gpt-4o-miniDocker 和 CI 中的环境变量
在 Docker 中,使用 -e 标志或 --env-file 传入环境变量。在 GitHub Actions 中,将其存储为 Secrets,并在工作流 YAML 中引用。绝不要将它们打包进 Docker 镜像。
# Docker run with env vars:
# docker run -e OPENAI_API_KEY='sk-...' -e AGENT_MODEL='gpt-4o-mini' myagent:latest
# Docker with an env file:
# docker run --env-file .env myagent:latest
# GitHub Actions workflow (secrets stored in repo settings):
# env:
# OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
# SEARCH_API_KEY: ${{ secrets.SEARCH_API_KEY }}
# docker-compose.yml:
# services:
# agent:
# image: myagent:latest
# env_file:
# - .env
print('Never bake secrets into Docker images — always inject at runtime')密钥泄露后该怎么办
如果您不小心将 API 密钥提交到公共或共享仓库,请立即采取行动。密钥一旦离开您的控制,就应假定已经泄露——提交后几秒内,机器人就会扫描 GitHub 中的密钥。
# Immediate response if a key is exposed:
# 1. REVOKE the key immediately (provider dashboard)
# OpenAI: platform.openai.com/api-keys -> Delete key
# Anthropic: console.anthropic.com -> API Keys
# 2. Generate a new key
# 3. Update your .env file with the new key
# 4. Rotate in all environments (staging, prod)
# Remove from git history (does NOT guarantee removal from forks/clones):
# git filter-branch or git-filter-repo to rewrite history
# Force push to all branches
# Note: Rewriting git history cannot undo exposure
# if others have already cloned or forked the repo
print('Revoke immediately. Do not just remove from code — rotate the key.')知识检查:环境变量
测试您对代理机密信息管理中环境变量的理解。
回顾:代理的环境变量
现在,您已经了解代理进行机密信息管理的正确方法:
- 绝不要将 API 密钥硬编码,因为它们会永久留在 Git 历史记录中
- 必需变量使用
os.environ['KEY'],可选变量使用os.getenv('KEY', default) - 在启动时验证所有必需变量,并显示清晰的错误消息
- 在代码注释和
.env.example中记录必需变量 - 在日志中隐藏密钥,仅显示最后 4 个字符
- 在 Docker 运行时注入机密信息;在 CI 中使用 GitHub Secrets
- 如果密钥泄露:先撤销,再在所有位置轮换
常见问题解答
「代理的环境变量」课时是免费的吗?
是的 — 「代理的环境变量」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Agents 课程的其余内容,请升级到 CoddyKit PRO。 AI Agents 课程共包含 4 节课。
「代理的环境变量」这节课中我会学到什么?
os.environ、os.getenv(),以及为什么绝不能在源代码中硬编码密钥。 你通过在浏览器中直接运行的动手代码来练习 AI Agents,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 AI Agents 需要有经验吗?
无需任何先前经验。CoddyKit 上的 AI Agents 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「代理的环境变量」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 AI Agents 课中编写并运行代码吗?
能。每节 AI Agents 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。