先看效果:
回答正确,说明4个文件都看过了,手动修改工具的答案后立刻问起,马上get到了,说明每次会话 都会加载,搞定

step1. ~/.openclaw/hooks/global-notes中添加handler.ts, HOOK.md
step2. ~/.openclaw/hookGlobals中添加 '__GNOTES.md', 'GAGENTS.md', 'GUSER.md', 'GTOOLS.md'
step3. workspace目录中的'GAGENTS.md', 'GUSER.md', 'GTOOLS.md' 文件内容清空(不是删除文件)
handler.ts
bash
import fs from 'fs/promises';
import path from 'path';
import { homedir } from 'os';
const GLOBALS_DIR = path.join(homedir(), '.openclaw', 'hookGlobals');
// 定义要注入的文件映射:目标文件名 -> 源文件列表(按顺序合并)
const fileMappings: Record<string, string[]> = {
'AGENTS.md': ['GAGENTS.md', 'GUSER.md', '__GNOTES.md'], // 合并为 AGENTS.md
'TOOLS.md': ['GTOOLS.md'], // 直接映射为 TOOLS.md
};
export default async function handler(event: any) {
// 仅在 agent:bootstrap 事件中处理
if (event.type !== 'agent' || event.action !== 'bootstrap') {
return;
}
// 确保 bootstrapFiles 数组存在
if (!event.context.bootstrapFiles) {
event.context.bootstrapFiles = [];
}
for (const [targetName, sourceFiles] of Object.entries(fileMappings)) {
try {
// 读取所有源文件内容
const contents: string[] = [];
for (const file of sourceFiles) {
const filePath = path.join(GLOBALS_DIR, file);
try {
const content = await fs.readFile(filePath, 'utf-8');
contents.push(content);
} catch (err: any) {
if (err.code !== 'ENOENT') {
console.error(`[global-notes] 读取文件 ${filePath} 失败:`, err);
}
// 文件不存在则忽略
}
}
// 如果有内容则合并注入
if (contents.length > 0) {
const combinedContent = contents.join('\n\n');
event.context.bootstrapFiles.push({
path: targetName, // 虚拟路径,仅用于标识
name: targetName,
content: combinedContent,
missing: false,
});
console.log(`[global-notes] 已注入 ${targetName},包含 ${contents.length} 个源文件`);
}
} catch (err) {
console.error(`[global-notes] 处理 ${targetName} 时出错:`, err);
}
}
}
HOOK.md
bash
---
name: global-notes
description: "为所有 agent 注入全局文件"
metadata:
openclaw:
events: ["agent:bootstrap"]
---
## 全局注意事项注入
在 agent 启动时,将 `~/.openclaw/hookGlobals/` 中的文件添加到引导文件列表中。