- 人工智能
- AI Agent
- 即时通讯
- 后端
- 本地部署
- 语音
【免费下载链接】openclaw-cn
中文社区版OpenClaw,同原版保持定期更新,已内置钉钉、企业微信、飞书、QQ、微信以及国内网络环境优化。你的专属个人AI助手。支持所有操作系统和平台。🦞
环境变量是 OpenClaw 的"神经中枢",理解它的加载顺序是排查网关 API Key 缺失、配置部署异常的关键。本文基于docs/environment.md并结合 src/config/paths.ts、src/config/io.ts、src/infra/dotenv.ts、src/infra/shell-env.ts 等源码,系统梳理 OpenClaw(Clawdbot)加载环境变量的全部来源、优先级顺序、配置env块的两种写法、登录 shell 导入机制、配置内${VAR}替换语法,以及OPENCLAW_HOME、OPENCLAW_STATE_DIR、OPENCLAW_CONFIG_PATH三个路径类变量的覆盖规则。
环境变量从哪里来:五大来源与"绝不覆盖"原则
OpenClaw(Clawdbot)的配置加载器会从多个来源收集环境变量,核心规则只有一条:never override existing values(绝不覆盖已存在的值)。也就是说,环境变量一旦在更高级别的来源中被设定(非空),低优先级来源的同名变量将被忽略,这与传统的.env覆盖行为截然不同,可以避免部署环境中意外的"环境变量劫持"。
按优先级从高到低,环境变量来源如下:
| 优先级 | 来源 | 说明 |
|---|---|---|
| 1(最高) | 进程环境 | Gateway 进程从父 shell / 守护进程(daemon)继承的变量,任何情况下都不会被后续来源覆盖 |
| 2 | 当前工作目录的.env | 使用 dotenv 默认行为加载(dotenv.config({ quiet })),不覆盖已有值 |
| 3 | 全局.env | 位于~/.openclaw/.env(即$OPENCLAW_STATE_DIR/.env),不覆盖已有值 |
| 4 | 配置文件env块 | 位于~/.openclaw/openclaw.json中的env配置,仅在变量缺失时应用 |
| 5(最低) | 登录 shell 导入 | 由env.shellEnv.enabled或OPENCLAW_LOAD_SHELL_ENV=1触发,仅对缺失的"预期 Key"生效 |
从源码实现看,第 2、3 步由 src/infra/dotenv.ts 中的loadDotEnv()完成:先以dotenv.config({ quiet })加载当前工作目录(CWD)的.env,再尝试读取path.join(resolveConfigDir(process.env), ".env")作为全局回退文件,并使用override: false保证绝不覆盖已存在的值。
需要特别注意的是:如果配置文件完全不存在,第 4 步(configenv块)会被跳过,但第 5 步(shell 导入)只要启用就仍然执行。这一行为在 src/config/io.ts 的loadConfig()中可见——当configPath不存在且 shell 回退已启用且未延迟时,会直接调用loadShellEnvFallback()并返回空配置{}。
配置文件中的env块:两种等价的非覆盖式写法
在~/.openclaw/openclaw.json(JSON5 格式)中,你可以通过env块直接内联设置环境变量。它提供两种等效的写法,均为非覆盖式(即仅当变量缺失时才生效):
{ env: { OPENROUTER_API_KEY: "sk-or-...", vars: { GROQ_API_KEY: "gsk-..." } } }- 顶层直接书写
KEY: "value",如OPENROUTER_API_KEY; - 或将多个变量收纳进
vars子对象,如GROQ_API_KEY; - 两种方式完全等价,可以混用。
从源码层面看,src/config/env-vars.ts 中的collectConfigEnvVars()会先遍历envConfig.vars,再遍历envConfig顶层除shellEnv和vars之外的所有字符串键,最后统一交给 src/config/io.ts 的applyConfigEnv()应用——应用逻辑非常简单:if (env[key]?.trim()) continue;,即环境里已有非空值就跳过,否则才写入。
env块的 Schema 在 src/config/zod-schema.ts 中定义:shellEnv对象可选,包含enabled: boolean与timeoutMs: number(整数、非负);vars为Record<string, string>;顶层允许任意字符串键(.catchall(z.string())),这正是两种写法都能被接受的原因。
Shell 环境导入:把登录 shell 的密钥带进 Gateway
env.shellEnv机制会执行你的登录 shell,并只导入缺失的预期 Key——这是解决"明明在终端里 export 了 API Key,但 Gateway 作为守护进程/服务运行时却拿不到"这一经典问题的方案。
{ env: { shellEnv: { enabled: true, timeoutMs: 15000 } } }对应的环境变量等价写法:
OPENCLAW_LOAD_SHELL_ENV=1—— 等价于enabled: trueOPENCLAW_SHELL_ENV_TIMEOUT_MS=15000—— 等价于timeoutMs: 15000(默认 15000ms)
源码实现位于 src/infra/shell-env.ts 的loadShellEnvFallback()。其执行逻辑依次为:
- 若未启用,直接跳过;
- 若
expectedKeys中已有任意一个键存在于环境中(非空),则整个导入被跳过(skippedReason: "already-has-keys")——这是一个重要的短路优化:只要检测到任意一个预期 Key 已存在,就认为环境已就绪,不再执行登录 shell; - 否则通过
execFileSync(shell, ["-l", "-c", "env -0"], { timeout })执行$SHELL(缺省回退/bin/sh)的登录 shell,以 NUL 分隔输出环境变量(env -0),解析后用\0分割(parseShellEnv(),见 src/infra/shell-env.ts); - 仅对缺失的预期键逐一代入值,最终返回实际应用的 Key 列表。
所谓"预期 Key"(SHELL_ENV_EXPECTED_KEYS)在 src/config/io.ts 中定义,包含常见模型与渠道凭据:OPENAI_API_KEY、ANTHROPIC_API_KEY、ANTHROPIC_OAUTH_TOKEN、GEMINI_API_KEY、ZAI_API_KEY、OPENROUTER_API_KEY、AI_GATEWAY_API_KEY、MINIMAX_API_KEY、SYNTHETIC_API_KEY、ELEVENLABS_API_KEY、TELEGRAM_BOT_TOKEN、DISCORD_BOT_TOKEN、SLACK_BOT_TOKEN、SLACK_APP_TOKEN、OPENCLAW_GATEWAY_TOKEN、OPENCLAW_GATEWAY_PASSWORD。
加载时机上(src/config/io.ts),当shouldEnableShellEnvFallback(env)为真或配置中cfg.env?.shellEnv?.enabled === true,且未设置OPENCLAW_DEFER_SHELL_ENV_FALLBACK时,会在配置加载完成、applyConfigEnv之后触发 shell 导入;超时值优先取cfg.env?.shellEnv?.timeoutMs,否则回退到OPENCLAW_SHELL_ENV_TIMEOUT_MS或默认 15 秒。
配置内的${VAR}替换:把密钥写进配置但不落盘
你可以在配置文件的任意字符串值中使用${VAR_NAME}语法直接引用环境变量,加载时会被替换为实际值:
{ models: { providers: { "vercel-gateway": { apiKey: "${VERCEL_GATEWAY_API_KEY}" } } } }这一语法在 src/config/env-substitution.ts 的substituteString()中实现,规则要点:
- 仅匹配大写环境变量名,模式为
[A-Z_][A-Z0-9_]*; - 使用
$${}转义可输出字面量${}; - 若引用的变量缺失或为空,会抛出
MissingEnvVarError(携带变量名与配置路径上下文),加载因此失败——这保证了配置不会在静默中拿到空密钥; - 关键时序:在 src/config/io.ts 中,
applyConfigEnv先于resolveConfigEnvVars执行,因此${VAR}可以引用同配置env块中定义的变量; - 配置写入(
writeConfigFile)时,未变更路径上的${VAR}引用会被restoreEnvVarRefs/restoreEnvRefsFromMap还原,避免把解析后的明文密钥写回磁盘(见 src/config/io.ts)。
更完整的说明可参见 网关配置文档。
路径相关的环境变量:三个覆盖入口
OpenClaw 提供三个路径类环境变量,用于调整内部路径解析:
| 变量 | 用途 |
|---|---|
OPENCLAW_HOME | 覆盖所有内部路径解析所依赖的主目录(默认~/.openclaw/、agent 目录、会话、凭据),适合以专用服务用户运行 OpenClaw |
OPENCLAW_STATE_DIR | 覆盖状态目录(默认~/.openclaw) |
OPENCLAW_CONFIG_PATH | 覆盖配置文件路径(默认~/.openclaw/openclaw.json) |
OPENCLAW_HOME:为无头服务账户实现完整文件系统隔离
设置OPENCLAW_HOME后,它将替换系统主目录($HOME/os.homedir())用于全部内部路径解析,从而让无头(headless)服务账户获得完整的文件系统隔离。
其解析优先级为:
OPENCLAW_HOME > $HOME > USERPROFILE > os.homedir()源码实现在 src/infra/home-dir.ts 的resolveEffectiveHomeDir()中:若OPENCLAW_HOME非空则直接采用;否则依次回退$HOME、USERPROFILE、os.homedir()。OPENCLAW_HOME也支持波浪号路径(如~/svc),会在使用前基于$HOME展开——这正是expandHomePrefix()(src/infra/home-dir.ts)的职责,resolveRequiredHomeDir()则在所有来源都不可用时回退到process.cwd()。
macOS LaunchDaemon 示例:
<key>EnvironmentVariables</key> <dict> <key>OPENCLAW_HOME</key> <string>/Users/kira</string> </dict>由于 LaunchDaemon 以 root 运行且没有常规登录环境,显式注入OPENCLAW_HOME是让服务使用指定用户配置目录的标准做法。
路径解析的完整链路
从 src/config/paths.ts 可以看到三个变量的协同:
resolveStateDir()(src/config/paths.ts):优先读取OPENCLAW_STATE_DIR(兼容旧名CLAWDBOT_STATE_DIR)的覆盖;否则在~/.openclaw(新目录)与.clawdbot、.moltbot、.moldbot(历史遗留目录,见第 20 行的LEGACY_STATE_DIRNAMES)之间按存在性选择;resolveCanonicalConfigPath()(src/config/paths.ts):优先读取OPENCLAW_CONFIG_PATH(兼容CLAWDBOT_CONFIG_PATH),否则默认$OPENCLAW_STATE_DIR/openclaw.json;resolveConfigPath()/resolveConfigPathCandidate()还会在状态目录中按openclaw.json→clawdbot.json→moltbot.json→moldbot.json的顺序探测已存在的配置文件(src/config/paths.ts),保证老用户升级后配置仍能无缝找到。
此外,paths.ts还暴露了若干相关覆盖项可供部署参考:OPENCLAW_OAUTH_DIR(OAuth 凭据目录,默认$STATE_DIR/credentials,见 src/config/paths.ts)、OPENCLAW_GATEWAY_PORT(默认 18789,见 src/config/paths.ts)、OPENCLAW_NIX_MODE=1(Nix 部署模式,禁止自动安装流程,见 src/config/paths.ts)。
调试排查清单
当你在 Gateway 中遇到"API Key 缺失"类问题时,可按以下顺序自检:
- 进程环境:确认启动 Gateway 的父进程/shell 中变量确实存在且非空(
echo $OPENAI_API_KEY); .env文件:检查当前工作目录与~/.openclaw/.env(或$OPENCLAW_STATE_DIR/.env)中是否有同名变量——注意低优先级.env里的值不会覆盖进程环境中的值;- 配置文件
env块:确认openclaw.json的env块没有拼写错误,且 JSON5 语法合法; - shell 导入:确认
env.shellEnv.enabled或OPENCLAW_LOAD_SHELL_ENV=1已设置,且预期 Key(见上文SHELL_ENV_EXPECTED_KEYS列表)确实存在于你的登录 shell 中——可临时执行$SHELL -l -c 'env -0'验证; ${VAR}引用:检查配置中apiKey等字段是否为${SOME_KEY}形式且对应变量非空,否则会触发MissingEnvVarError并导致配置加载失败;- 路径类变量:若使用服务账户或容器部署,核对
OPENCLAW_HOME/OPENCLAW_STATE_DIR/OPENCLAW_CONFIG_PATH是否指向了正确的目录,避免读取到"另一份"配置。
相关文档
- 网关配置完整说明
- FAQ:环境变量与 .env 加载
- 模型提供商概览
- 人工智能
- AI Agent
- 即时通讯
- 后端
- 本地部署
- 语音
【免费下载链接】openclaw-cn
中文社区版OpenClaw,同原版保持定期更新,已内置钉钉、企业微信、飞书、QQ、微信以及国内网络环境优化。你的专属个人AI助手。支持所有操作系统和平台。🦞
相关推荐
aws-vault环境变量优先级:理解配置覆盖机制
aws vault环境变量优先级:理解配置覆盖机制 你是否曾在使用aws vault时遇到配置不生效的问题?明明在配置文件中设置了参数,却被某个环境变量意外覆盖
开发工具安全pixi 环境变量完全指南:配置项、注入变量与优先级机制
pixi 环境变量完全指南:配置项、注入变量与优先级机制 pixi 是一款基于 Conda 生态、使用 Rust 编写的跨平台包管理器与环境管理工具。本文聚焦
开发工具CLI包管理器任务调度OpenClaw 环境变量完全指南:加载来源、优先级与配置实践
OpenClaw 环境变量完全指南:加载来源、优先级与配置实践 OpenClaw 从多个来源汇集环境变量:进程环境、工作区 .env 、全局状态目录 .env
AI 应用AI Agent交互助手后端即时通讯网关
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考