OpenClaw 里 TAVILY_API_KEY 明明写在 ~/.bashrc,为什么还是失效?一次完整排查与修复

OpenClaw 里 TAVILY_API_KEY 明明写在 ~/.bashrc,为什么还是失效?一次完整排查与修复

这次踩了一个很典型、也很容易误判的坑:

明明 ~/.bashrc 里已经配置了 TAVILY_API_KEY,但在 OpenClaw 里使用 Tavily skill 时,依然报 Missing TAVILY_API_KEY 。与此同时,内置 web_search 还因为 Brave Search API 没配 key 直接报错。

看起来像是"配置丢了",但真正的问题并不在 ~/.bashrc 本身,而在 Gateway 进程的启动方式

这篇文章把完整的排查链路、根因分析和修复步骤整理出来,给遇到类似问题的同学一个可复用的参考。


问题现象

最开始暴露出来的是两个现象:

调用内置搜索时,直接拿到类似下面的错误:

text 复制代码
missing_brave_api_key

这说明当前 OpenClaw 的内置 web_search 走的是 Brave Search,而不是 Tavily。

2. Tavily skill 明明装了,但实际不可用

Tavily skill 的 SKILL.md 里已经写得很清楚:

markdown 复制代码
Needs TAVILY_API_KEY from https://tavily.com

我进一步检查运行环境,结果是:

text 复制代码
TAVILY_API_KEY_SET=no

这就奇怪了:终端里明明能看到 ~/.bashrc 中存在 export TAVILY_API_KEY=...,为什么 OpenClaw 运行时却拿不到?


第一层判断:不是 Tavily 没装,而是运行环境没拿到 key

先看 Tavily skill 本身。

它的搜索脚本逻辑非常直接:

javascript 复制代码
const apiKey = (process.env.TAVILY_API_KEY ?? '').trim();
if (!apiKey) {
  console.error('Missing TAVILY_API_KEY');
  process.exit(1);
}

这意味着只要当前进程环境里没有 TAVILY_API_KEY,它就一定失败。

所以问题就从"有没有写配置"转变成了:

到底是谁在启动 OpenClaw Gateway,它启动时有没有继承 shell 环境变量?


第二层判断:Gateway 不是从当前 shell 启动的

继续检查 OpenClaw Gateway 状态:

bash 复制代码
bash -i -lc 'openclaw gateway status'

输出里有一个关键点:

text 复制代码
Service: systemd (enabled)
Service file: ~/.config/systemd/user/openclaw-gateway.service

这一下就基本破案了。

OpenClaw Gateway 不是我当前 terminal session 里手工启动的长期进程,而是 systemd user service 托管的服务。

这意味着:

  • 你在当前 shell 里 source ~/.bashrc
  • 你在 terminal 里 echo $TAVILY_API_KEY 能看到值
  • 并不等于 systemd 管理的 Gateway 进程也能看到这个值

因为它们根本不是同一个环境来源。


根因:~/.bashrc 给了 interactive shell,但没给 systemd user service

这是这次问题的核心。

~/.bashrc 什么时候会生效?

通常是:

  • 交互式 shell
  • 手动打开的 terminal session
  • 某些明确 source 它的 bash 进程

systemd user service 启动的进程,并不会自动读取你的 ~/.bashrc

所以会出现一种非常迷惑的状态:

你看到的环境

bash 复制代码
echo $TAVILY_API_KEY
# 有值

Gateway 真实拿到的环境

text 复制代码
TAVILY_API_KEY = 空

这也是为什么很多人会说:

"我明明已经 export 了,为什么程序还说没有?"

因为 你 export 给的是当前 shell,不是 systemd service


既然目前主要想用的是 Tavily 和 LangSearch,而 Brave Search API 不是免费方案,那一个实际的处理方式就是:

先把内置 web_search 关掉 ,避免以后继续因为 BRAVE_API_KEY 报错。

配置修正后,搜索路径就会更清晰:

  1. LangSearch:查技术文档、代码、资料
  2. Tavily:做通用网页搜索
  3. web_fetch:已知 URL 直接抓页面

这个动作不是必须,但在多搜索源共存时很有价值:

先减少噪音,再修主问题。


正确修法:把环境变量导入 systemd user manager

既然 Gateway 是由 systemd user service 启动,那么最短修法就是:

  1. 在当前 shell 中确认变量存在
  2. 导入到 systemd user manager
  3. 重启 Gateway
  4. 验证新进程已经继承到变量

第一步:确认当前 shell 有值

bash 复制代码
bash -i -lc 'echo $TAVILY_API_KEY'

如果这里为空,说明你的 ~/.bashrc 本身就没配对,或者没被当前 shell 加载。

第二步:导入 systemd user 环境

bash 复制代码
systemctl --user import-environment TAVILY_API_KEY FIRECRAWL_API_KEY

这一步非常关键。它会把当前 shell 中的环境变量同步给 systemd user manager。

第三步:重启 OpenClaw Gateway

bash 复制代码
systemctl --user restart openclaw-gateway.service

这样新的 Gateway 进程就有机会拿到刚刚导入的变量。

第四步:检查 systemd 环境是否已经存在

bash 复制代码
systemctl --user show-environment | grep -E '^(TAVILY_API_KEY|FIRECRAWL_API_KEY)='

如果能看到输出,说明 systemd user manager 已经持有这些变量。

第五步:验证 Gateway 进程本身是否真的拿到了

可以直接检查进程环境,或者更简单,直接实测 Tavily:

bash 复制代码
bash -i -lc 'node skills/tavily-search/scripts/search.mjs "OpenClaw latest release" -n 3'

如果能正常返回答案和来源,说明修复已经生效。


实际验证结果

修复完成后,验证结果如下:

shell 环境

text 复制代码
SHELL_TAVILY=yes
SHELL_FIRECRAWL=yes

systemd user manager 环境

text 复制代码
TAVILY_API_KEY=<redacted>
FIRECRAWL_API_KEY=<redacted>

Gateway 进程环境

text 复制代码
PROC_TAVILY=yes
PROC_FIRECRAWL=yes

Tavily 实测

已经成功返回 OpenClaw 最新 release 的答案和来源。

这说明修复不是"看起来像好了",而是 从 shell → systemd → Gateway → skill 调用链路全部打通了


还有一个容易被忽略的问题:~/.bashrc 里重复定义了两次 TAVILY_API_KEY

排查过程中还发现一个隐患:

~/.bashrc 里曾经同时存在两个 export TAVILY_API_KEY=...

这类问题的风险不在于 bash 不能运行,而在于:

  • 你自己会误以为某个 key 在生效
  • 实际上后面的定义会覆盖前面的定义
  • 一旦前后 key 不同,排查时会非常混乱

因此后面又做了一步清理:

只保留一个 TAVILY_API_KEY,删掉旧的/重复的定义。

这一步不直接决定功能是否可用,但会显著降低后续维护成本。


为什么这个问题在 AI Agent / 自动化环境里特别常见?

因为这类系统经常同时存在多种"环境来源":

  • 当前终端 shell
  • systemd service
  • cron
  • Docker / container runtime
  • IDE 集成终端
  • 浏览器自动化子进程

如果你只在某一个地方 export KEY=...,很容易出现"这个地方能用,另一个地方不能用"的现象。

对 AI Agent 场景来说,这类问题尤其常见,因为工具调用往往发生在:

  • 后台守护进程
  • 独立 worker
  • system service
  • 子进程链路里

所以经验上更稳妥的原则是:

不要假设 ~/.bashrc = 全局真相。

要搞清楚:到底是谁在启动你的服务。


一份可复用的最短修复步骤

如果你也遇到类似问题,可以直接按下面这份清单来:

bash 复制代码
# 1) 确认当前 interactive shell 里有变量
bash -i -lc 'echo $TAVILY_API_KEY'

# 2) 导入到 systemd user manager
systemctl --user import-environment TAVILY_API_KEY FIRECRAWL_API_KEY

# 3) 重启 Gateway
systemctl --user restart openclaw-gateway.service

# 4) 检查 systemd 环境
systemctl --user show-environment | grep -E '^(TAVILY_API_KEY|FIRECRAWL_API_KEY)='

# 5) 检查 Gateway 状态
bash -i -lc 'openclaw gateway status'

# 6) 实测 Tavily
bash -i -lc 'node skills/tavily-search/scripts/search.mjs "OpenClaw latest release" -n 3'

如果第 6 步成功返回结果,基本就说明整条链路已经修好了。


最后的经验总结

这次问题最值得记录的,不是某一条命令,而是排查思路:

  1. 先看报错发生在哪一层:Brave 还是 Tavily
  2. 再看 skill 的真正依赖是什么:环境变量还是配置文件
  3. 再确认服务是谁启动的:interactive shell 还是 systemd
  4. 最后验证真实运行进程是否继承到变量

很多"明明写了环境变量却不生效"的问题,本质上都不是 key 配错,而是:

你把变量写进了 A 环境,但程序跑在 B 环境。

一旦把这层想清楚,定位和修复就会快很多。

如果你也在折腾 OpenClaw、Tavily、LangSearch 或其他 AI Agent 工具链,希望这篇记录能帮你少踩一个坑。

相关推荐
千寻girling2 小时前
Python 是用来做 AI 人工智能 的 , 不适合开发 Web 网站 | 《Web框架》
人工智能·后端·算法
stark张宇2 小时前
构建第一个AI聊天机器人:Flask+DeepSeek+Postgres实战
人工智能·postgresql·flask
yiyu07163 小时前
3分钟搞懂深度学习AI:自我进化的最简五步法
人工智能·深度学习
饼干哥哥5 小时前
用OpenClaw搭跨境电商团队:5个AI员工,跑通全平台矩阵!
aigc
浪浪山_大橙子5 小时前
OpenClaw 十分钟快速,安装与接入完全指南 - 推荐使用trae 官方 skills 安装
前端·人工智能
火山引擎开发者社区5 小时前
OpenClaw 快速上手:把云手机变成你的 7×24 小时 AI 手机助手
人工智能
Qlly5 小时前
DDD 架构为什么适合 MCP Server 开发?
人工智能·后端·架构
Lee川5 小时前
从零构建智能对话系统:AI Agent 实战指南
人工智能
冬奇Lab6 小时前
一天一个开源项目(第43篇):Star-Office-UI - 像素风格的 AI 办公室看板,让 AI 助手的工作状态可视化
人工智能·开源·资讯