问题:
现象:发布任务给agent(明确指定使用2个skill技能),看着给出的结果,黑盒,越看越可疑
模型:minimax2.5CN
plantext
找到sessions/e68b18a5-2223-4b65-9738-d601c2a62145.jsonl会话文件,让长上下文的minimax检索看看到底发生了什么
1.⚠️ web_search (英文) - 失败 - missing_brave_api_key
2.⚠️ web_search (中文) - 失败 - missing_brave_api_key
3.✅ web_fetch (clawhub.com) - 成功但返回空结果
4.✅ web_fetch (docs.openclaw.ai) - 开始获取文档
果然,根本没有调用skill技能,完全是在忽悠我
复制这个结论丢给openclaw,说是要brave search的api key
再看看交互信息,里面有搜索tavily-search路径的动作,看来自动加载skill的功能有待完善,先给它固定到Tools.md中去吧
再次测试,这次提示缺少TAVILY_API_KEY,我明明已在环境变量中配置,什么情况呢?
找到skill看SKILL.md,手工执行没问题,ssh也没问题,把我执行OK的信息丢给它让它想办法解决
终于它自己找到原因了:openclaw默认执行器是`exec` 不加载 `~/.bashrc`
添加环境变量到.env文件,流程跑通,但忽悠我的原因还没有弄清
我要deepwiki给一个用户级解决方案,基本定位在模型的指令遵循能力上
最终方案: 直接SOUL.md,Tools.md 搞定
bash
# SOUL.md - 你的信任边界,非常重要
- 使用简洁清晰的中文
- 必要时提供技术细节,但先给结论
- 代码解释时先给整体思路,再给细节
- 不确定时,想办法确定(比如启动验证流程直接验证,调用搜索工具去找答案,3轮后如果还搞不定,承认不确定并寻求帮助)
- 确定时直接给出方案并执行,不说废话
- 凡是搜索汇总类任务,所有搜索的结果都要清晰展示,同时给出你自己的总结
# TOOLS.md - 本地工具
- shell工具:openclaw exec
- skills目录:{`.openclaw/skills`,`.openclaw/workspace/skills`}
参考资料1: 为什么 exec 不加载 ~/.bashrc
根本原因:非交互式、非 login shell
exec 工具在执行命令时,调用的是 getShellConfig() 函数,该函数返回 shell 和参数:
- 非 Windows (非 fish):返回
{ shell: $SHELL, args: ["-c"] } - Windows :返回 PowerShell 加
-NoProfile -NonInteractive -Command
最终执行命令的 argv 是 [shell, "-c", command],即 bash -c "your_command"。
这是标准 bash 行为:bash -c 启动的是非交互式、非 login shell,不会加载:
~/.bashrc(仅在交互式 shell 中加载)~/.bash_profile/~/.profile(仅在 login shell 中加载)
因此,在 ~/.bashrc 中 export 的环境变量不会生效。
PATH 的特殊处理(仅 host=gateway)
对于 host=gateway,exec 会额外通过 getShellPathFromLoginShell() 函数,以 shell -l -c "env -0" 的方式启动 login shell 来单独提取 PATH 变量 并合并进执行环境,但这只提取 PATH,不提取其他环境变量:
host=sandbox 则不做此操作,sandbox 内使用的是默认 PATH。
exec 是默认执行器吗?可以修改吗?
默认 host 是 sandbox
exec 工具的默认 host 是 "sandbox"(Docker 容器执行):
在运行时完整的优先级链(从高到低)为:
- 工具调用参数
host=xxx - Session 覆盖(
/exec host=...指令) - Agent 级配置
agents.list[].tools.exec.host - 全局配置
tools.exec.host - 硬编码默认值
"sandbox"
可用的 host 值:sandbox | gateway | node。
如何修改默认执行器
方法一:全局配置(永久生效)
在 ~/.openclaw/openclaw.json 中设置:
方法二:per-agent 配置
方法三:Session 临时覆盖(当次会话生效)
发送 /exec 指令:
解决环境变量不生效的方案
方案一:~/.openclaw/.env 文件(推荐)
将需要的变量写入 ~/.openclaw/.env,Gateway 启动时会加载:
方案二:启用 login shell 导入(env.shellEnv.enabled)
这会让 OpenClaw 以 login shell 运行并导入缺失的变量到 Gateway 进程环境中,从而让 exec 继承这些变量:
方案三:在命令中显式 source
在 exec 命令里手动 source,例如:source ~/.bashrc && your_command(仅适合 host=gateway,sandbox 中效果有限)。
方案四:tools.exec.pathPrepend(仅解决 PATH 问题)
如果只是 PATH 缺少某些目录,可以用 pathPrepend:
方案五:exec 的 env 参数
在工具调用时通过 env 参数显式传入环境变量(host=gateway/node 时 PATH 和 LD_* 等危险变量会被拦截):
Notes
OPENCLAW_SHELL=exec会被注入到所有 exec 子进程的环境中,可以在 shell profile 脚本里用这个变量检测 exec-tool 上下文,从而有条件地加载特定配置:- sandbox 模式下(默认),沙箱内使用的是容器自己的 PATH,
tools.exec.pathPrepend在 sandbox 里也有效 ,但host=node时无效。 host=gateway时,env.PATH覆盖因安全原因被禁止(防止二进制劫持):
参考资料2: 忽悠你的原因分析
1. Skills 系统的工作机制是"软指令"
系统提示中的技能部分 (## Skills (mandatory)) 本质上只是一段对模型的文字指令 ,框架层面并不强制执行。它告诉模型:先扫描 <available_skills> 列表,如果有匹配的技能,再用 read 工具去读该技能的 SKILL.md,然后才能按技能说明执行。
这意味着:模型完全可以无视这段指令 ,自行决定用 web_search / web_fetch。这就是 minimax2.5CN 的实际行为------它没有先去 read SKILL.md,而是直接走了自己熟悉的搜索路径。
2. 从 session 日志看,模型在"查找技能用法"而非"使用技能"
session 日志中:
web_fetch(clawhub.com)→ 在找技能包web_fetch(docs.openclaw.ai)→ 在查 OpenClaw 文档
这说明 minimax2.5CN 根本不知道如何调用技能 (需要先 read SKILL.md),于是它去网络上查找教程。这是模型指令遵循能力不足导致的。
用户级解决方案(从最可靠到最辅助,按优先级排序)
✅ 方案一(最可靠):使用斜杠命令 /skill 强制绕过模型裁量
斜杠命令是唯一在框架层面强制执行 技能调用的机制。当你发送 /skill <技能名> <任务内容> 时,OpenClaw 会在将消息送给模型之前,把消息体改写为 Use the "<skillName>" skill for this request.,让模型无从忽视。
如果该技能的 SKILL.md 中设置了 command-dispatch: tool,则完全不经过模型,直接调用工具。
操作方式(二选一):
/skill <技能名> <你的任务描述>--- 通用形式/<技能的命令名> <你的任务描述>--- 如果该技能已注册为命令
✅ 方案二:配置 agents.list[].skills 过滤器,让系统提示只展示这2个技能
当系统提示里技能数量少且精准时,模型命中正确技能的概率大幅提升。在 openclaw.json 中对该 agent 设置 skills 白名单:
json5
{
agents: {
list: [
{
id: "your-agent-id",
skills: ["skill-a-name", "skill-b-name"] // 只显示这2个技能
}
]
}
}
这由 resolveAgentSkillsFilter() 读取,传入 filterSkillEntries() 执行过滤------undefined 表示不限制,[] 表示全部屏蔽,填写技能名列表则只保留这些。
✅ 方案三:用 tools.deny 封堵 web_search / web_fetch 降级路径
从根本上切断模型的逃逸路线------如果这个 agent 的任务本来就不该用 web 工具,直接在工具策略层屏蔽:
json5
{
agents: {
list: [
{
id: "your-agent-id",
tools: {
deny: ["group:web"] // 等价于 deny: ["web_search", "web_fetch"]
}
}
]
}
}
deny 在所有策略层中永远优先 ,模型无法调用被屏蔽的工具。可用工具组 group:web 包含 web_search 和 web_fetch。
✅ 方案四:任务措辞要精准到"文件路径级"
由于技能调用的第一步是模型调用 read 工具读取 SKILL.md,你可以在任务中直接告诉模型路径,跳过模型"查找"这一步:
"请先用
read工具读取~/.openclaw/skills/<技能A>/SKILL.md,按其说明执行;然后再读<技能B>/SKILL.md,按其说明执行。"
这模拟了系统提示的原意,但表达更直接,减少模型歧义空间。
⚠️ 方案五(辅助):对需要严格 skill 遵从的任务换用指令遵循更强的模型
MiniMax 模型在处理复杂多步指令(scan available_skills → read SKILL.md → follow instructions)时表现不稳定。技能是通过系统提示以自然语言 XML 格式注入的:
指令遵循能力弱的模型会跳过"read SKILL.md"这一步,直接用自己认为合适的工具。如果任务对技能合规性要求高,考虑切换到 Claude / Gemini 等执行更严格的模型来运行这类任务。
诊断命令
bash
# 查看当前 agent 加载了哪些技能(确认2个目标技能是否在列)
openclaw skills check
# 列出当前所有已注册的斜杠命令(确认技能是否可被 /skill 调用)
openclaw skills list
Notes
- 斜杠命令(方案一)是最强的用户级保证,因为它在框架层面修改了消息体,而不是依赖模型自愿遵守。
- 方案二+三可以组合使用:技能过滤使系统提示更聚焦,工具屏蔽消除逃逸路径,双重保险。
- 技能快照在 session 启动时生成,如果你刚修改了
skills白名单配置,需要重新开启一个新 session 才能生效(修改不影响已有 session)。 - MiniMax 模型本身有一个已知问题:有时会将工具调用泄漏为 XML 文本而非结构化调用,OpenClaw 内部有
stripMinimaxToolCallXml()补丁来处理这类情况,但这进一步说明该模型在工具交互层面存在特殊性。