OpenClaw
第零章 写在前面
官网: link
第一章 Hello OpenClaw
第一节 下载OpenClaw
下载
node --version
npm install -g openclaw
echo 'export PATH="$(npm config get prefix)/bin:$PATH"' >> ~/.zshrc
exec zsh
openclaw --version
第二节 运行OpenClaw
1.2.1 什么是GateWay(网关)
- 作用: OpenClaw是通过GateWay运行的, 你网页18789看到的是gateway dashboard可视化界面;
- ①言外之意就是想要用OpenClaw, 得先把gateway跑起来
- ②修改任何内容(plugin, skill)也得重启gateway
1.2.2 GateWay常用命令
| 作用 | 指令 | 示例 |
|---|---|---|
| 查看gateway的状态 | openclaw gateway status |
openclaw gateway status |
| 开启gateway | openclaw gateway start |
openclaw gateway start |
| 关闭gateway | openclaw gateway stop |
openclaw gateway stop |
| 重启gateway | openclaw gateway restart |
openclaw gateway restart |
第三节 CLI对话
| ① 作用 | ② 格式 | ③ 示例 |
|---|---|---|
| 开启新对话 | openclaw chat --session <新名称> |
openclaw chat --session work |
| 恢复上一次对话 | openclaw chat(默认 session=main) |
openclaw chat |
| 查看历史对话列表 | openclaw sessions |
openclaw sessions --limit 25 |
| 跳转指定历史对话 | openclaw chat --session <key> |
openclaw chat --session work |
| 删除指定历史对话 | 无内置命令,需手动删文件 | 默认在 ~/.openclaw/sessions/ 下找对应 session 目录删除 |
- session key 不写默认
main,所以openclaw chat永远是同一场对话 - 想开新对话换一个 key 就行:
openclaw chat --session test-001 chat是别名,tui/terminal也一样
第二章 Plugin
第一节 常用命令
| 作用 | 指令 | 示例 (voice-cal这个插件为例子) |
|---|---|---|
| 列出已安装的插件 | openclaw plugins list |
openclaw plugins list |
| 查看插件详细信息 | openclaw plugins info <id> |
openclaw plugins info voice-call |
| 启用插件 | openclaw plugins enable <id> |
openclaw plugins enable voice-call |
| 禁用插件 | openclaw plugins disable <id> |
openclaw plugins disable voice-call |
| 卸载插件 | openclaw plugins uninstall <id> |
openclaw plugins uninstall voice-call |
| 更新指定插件 | openclaw plugins update <id> |
openclaw plugins update voice-call |
| 更新所有插件 | openclaw plugins update --all |
openclaw plugins update --all |
| 第二节 Hello Plugin | ||
| 脚手架 | openclaw plugins init "<文件名称>" --name "<插件名称>" |
openclaw plugins init "test-01" --name "Test 01" |
| 检查插件加载情况 | openclaw plugins inspect <id> --runtime --json |
openclaw plugins inspect my-plugin --runtime --json |
第二节 Hello Plugin
STEP1: 利用脚手架
- 位置:
~/.openclaw/extentions(没有自己建) - 文件结构:
test-01/
├── tsconfig.json # tsc 编译配置:告诉 tsc 把 src/*.ts → dist/*.js
├── package.json # npm 包元数据:名称/版本/脚本/依赖/入口路径
├── openclaw.plugin.json # 插件 manifest:id/名称/配置/工具列表(Dashboard 发现)
├── README.md # 说明文档,可删
└── src/
├── index.ts # 插件入口源码:定义工具 + 执行逻辑
└── index.test.ts # vitest 单元测试,可删
openclaw plugins init "test-01" --name "Test 01"
STEP2: 删除不必要的内容
有用的文件就三个 ①
package.json②openclaw.plugin.json③index.ts其中②③最重要
- 最终文件结构
test-01/
├── tsconfig.json # tsc 编译配置:告诉 tsc 把 src/*.ts → dist/*.js
├── package.json # npm 包元数据:①删掉了 plugin:build/plugin:validate/test 脚本;②删掉了 vitest 开发依赖(没 test 就不需要)
├── openclaw.plugin.json # 插件 manifest:id/名称/配置/工具列表(Dashboard 发现)
└── src/
└── index.ts # 插件入口源码:definePluginEntry 注册 tool/cli/command/service/hook
- 只用修改package.json: 共计两处修改
{
"name": "openclaw-plugin-test-01",
"version": "0.1.0",
"type": "module",
"private": true,
"scripts": {
"build": "tsc -p tsconfig.json"
//(1/2) 这里删除了plugin:build; plugin:vaild; test脚本
},
"files": [
"dist",
"openclaw.plugin.json",
"README.md"
],
"peerDependencies": {
"openclaw": ">=2026.5.17"
},
"dependencies": {
"typebox": "^1.1.38"
},
"devDependencies": {
"openclaw": "latest",
"typescript": "^5.9.0"
//(2/2) 这里删除了vitest依赖
},
"openclaw": {
"extensions": [
"./dist/index.js"
]
}
}
STEP3: build并重启gateway
注意⚠️: openclaw 读的不是你这个文件下的
index.ts; 而是 build 产生的 dist文件夹目录下的index.ts
插件修改了没有更新?: 你修改后 build 了吗?
npm install
npm run build
openclaw gateway restart
第三节 我们的脚手架
- 方便读取:
"resolveJsonModule": true
{
"compilerOptions": {
"resolveJsonModule": true,
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"declaration": true,
"outDir": "dist",
"skipLibCheck": true
},
"include": [
"src/**/*.ts"
]
}
- 需要修改: ①name
{
"name": "openclaw-plugin-web-11",
"version": "0.1.0",
"type": "module",
"private": true,
"scripts": {
"build": "tsc -p tsconfig.json"
},
"files": [
"dist",
"openclaw.plugin.json"
],
"peerDependencies": {
"openclaw": ">=2026.5.17"
},
"dependencies": {
"typebox": "^1.1.38"
},
"devDependencies": {
"openclaw": "latest",
"typescript": "^5.9.0"
},
"openclaw": {
"extensions": [
"./dist/index.js"
]
}
}
- 需要修改: ①id ②name ③description ④configSchema ⑤uiHints
{
"id": "web-11",
"name": "web 11",
"description": "搜索网站插件",
"version": "0.1.0",
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"website" :{
"type":"string",
"description": "只能配一个网址"
}
}
},
"uiHints": {
"website" :{
"label": "网址",
"description": "只能配一个网址"
}
},
"activation": {
"onStartup": true
},
"contracts": {
}
}
- 说明: 这里演示的是注册一个command
import { Type } from "typebox";
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
import manifest from "../openclaw.plugin.json" with { type: "json" }; // 直接读 manifest
const plugin: any = definePluginEntry({
id: manifest.id,
name: manifest.name,
description: manifest.description,
configSchema: manifest.configSchema as any,
register(api) {
// 配置读取
const config = (api.pluginConfig ?? {}) as {
website?: string;
}
api.registerCommand({
name: "show-website",
description: "展示用户配置的网站",
handler: () => {
return { text: `你配置的是${config.website ?? "未配置"}` };
}
})
},
});
export default plugin;
第三章: 配置文件(openclaw.plugin.json)
openclaw.plugin.json是 openclaw 插件专属的配置文件 link 别名”plugin manifest”
总共有几个配置项? 表格总结
第一节 uiHints
3.1.1 最小配置示例 link
uiHints 是"给已有配置项加标签",不是"凭空创建配置项" 。Dashboard 只会为 configSchema.properties 里声明的字段渲染 uiHints 。
立即推===> uiHints和configSchema的properties字段都要配置
{
"id": "test-plugin",
"name": "Test Plugin",
"description": "Add Test Plugin tools to OpenClaw.",
"version": "0.1.0",
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"hhh": {"type": "string"} // 1/2
}
},
"uiHints": {
"hhh": { "label": "HHH", "help": "xixix" } // 2/2
},
}
3.1.2 更多配置示例
{
"id": "web-11",
"name": "web 11",
"description": "...",
"version": "0.1.0",
"uiHints": { // 1/2 uiHints全配置
"companyName": { "label": "公司名称", "help": "显示在报告标题中", "placeholder": "请输入公司名称" }, // ①string: placeholder=输入框灰色提示
"enableReport": { "label": "启用报告", "help": "开启后每日自动生成汇总报告"}, // ②boolean: 布尔不需要placeholder
"maxHistory": { "label": "最大天数", "help": "范围 1-365", "placeholder": "30"}, // ③ integer
"secretKey": { "label": "密钥", "help": "从后台获取的 API 密钥", "sensitive": true }, //④密码:sensitive=true → 前端打码
"targetEndpoints":{ "label": "目标接口", "help": "[{\"name\":\"名称\",\"url\":\"地址\"}]"}, // ⑤数组(对象数组): 数组不需要placeholder
"keywords": { "label": "搜索关键词", "help": "每行一个" }, // ⑥数组(字符串数组):
"reportType": { "label": "报告类型", "help": "选一种格式" } // ⑦下拉列表:枚举不需要placeholder
},
"configSchema": { // 2/2 configSchema的proerties字段
"type": "object",
"properties": {
"companyName": { "type": "string" }, // ① string
"enableReport": { "type": "boolean" }, // ② boolean
"maxHistory": { "type": "integer", "minimum": 1, "maximum": 365 }, // ③ integer
"secretKey": { "type": "string" }, // ④ 密码(配合sensitive:true)
"targetEndpoints":{ // ⑤ array<object>
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"url": { "type": "string" }
}
}
},
"keywords": { "type": "array", "items": { "type": "string" } }, // ⑥ string[]
"reportType": { "type": "string", "enum": ["summary", "detail", "analysis"]} // ⑦ 下拉枚举
}
},
"activation": { "onStartup": true }
}
需求: 注册一个命令(command), 打印所有的配置项;
主要学习: 学习如何api.configSchema获取所有的配置项(不同类型怎么接)
import { Type } from "typebox";
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
import manifest from "../openclaw.plugin.json" with { type: "json" }; // 直接读 manifest,避免写两份 configSchema
const plugin: any = definePluginEntry({
id: manifest.id,
name: manifest.name,
description: manifest.description,
configSchema: manifest.configSchema as any, // 复用 manifest 中的 configSchema
register(api) {
// 读取插件所有配置项,类型与 openclaw.plugin.json 中的 properties 完全对应
const config = (api.pluginConfig ?? {}) as {
companyName?: string; // ① 字符串
enableReport?: boolean; // ② 布尔
maxHistory?: number; // ③ 整数
secretKey?: string; // ④ 密码(sensitive: true 控制前端打码)
targetEndpoints?: Array<{ name: string; url: string }>; // ⑤ 对象数组
keywords?: string[]; // ⑥ 字符串数组
reportType?: "summary" | "detail" | "analysis"; // ⑦ 下拉枚举
};
// 注册命令:打印当前所有配置(密钥脱敏显示)
api.registerCommand({
name: "show-all-config",
description: "打印当前插件的全部配置项",
handler: () => {
const eps = (config.targetEndpoints ?? []).map((e) => `${e.name}: ${e.url}`).join(", "); // 对象数组 → 字符串
const keywords = (config.keywords ?? []).join(", "); // 字符串数组 → 字符串
const maskedKey = config.secretKey? config.secretKey.slice(0, 4) + "****" : "未配置";// 密钥只显示前 4 位
const lines = [
`公司名称: ${config.companyName ?? "未配置"}`, // ① 字符串
`启用报告: ${config.enableReport ?? false}`, // ② 布尔
`最大历史天数: ${config.maxHistory ?? 30}`, // ③ 整数
`密钥: ${maskedKey}`, // ④ 密码(脱敏)
`目标接口: ${eps || "未配置"}`, // ⑤ 对象数组
`搜索关键词: ${keywords || "未配置"}`, // ⑥ 字符串数组
`报告类型: ${config.reportType ?? "summary"}`, // ⑦ 下拉枚举
];
return { text: lines.join("\n") };
},
});
},
});
export default plugin;
| 类型 | uiHints | configSchema | TS 读取类型 |
|---|---|---|---|
| string | "label" "help" "placeholder" |
"type": "string" |
string |
| boolean | "label""help" |
"type": "boolean" |
boolean |
| integer | "label""help" "placeholder" |
"type": "integer", "minimum": 1, "maximum": 365 |
number |
| 密码 | "label" "help" "sensitive":true |
"type": "string" |
string |
| array<object> | "label" "help" |
"type": "array", "items": { "type": "object", "properties": { ... } } |
Array<{...}> |
| string[] | "label" "help" |
"type": "array", "items": { "type": "string" } |
string[] |
| 枚举 | "label" "help" |
"type": "string", "enum": ["a","b","c"] |
"a" | "b" | "c" |
第四章 Plugin(index.ts)
第一节 注册类型和方式
| 类别 | 用途 | Method | 有什么用 | 用哪个entry points? |
|---|---|---|---|---|
| Capability | LLM 文本推理 | api.registerProvider(...) |
接入自定义模型,如对接本地 Ollama | definePluginEntry |
| Capability | 实验性低级 Agent 执行器 | api.registerAgentHarness(...) |
自定义 agent 运行时 | definePluginEntry |
| Capability | 本地 CLI 推理后端 | api.registerCliBackend(...) |
用 llama.cpp 等本地引擎跑推理 |
definePluginEntry |
| Capability | 向量嵌入生成 | api.registerEmbeddingProvider(...) |
为 memory search 提供向量化能力 | definePluginEntry |
| Capability | TTS / STT 语音合成 | api.registerSpeechProvider(...) |
Whisper 语音转文字、ElevenLabs TTS | definePluginEntry |
| Capability | 流式实时转录 | api.registerRealtimeTranscriptionProvider(...) |
会议实时字幕 | definePluginEntry |
| Capability | 双工实时语音会话 | api.registerRealtimeVoiceProvider(...) |
实时语音对话机器人 | definePluginEntry |
| Capability | 图片/音频/视频分析 | api.registerMediaUnderstandingProvider(...) |
多模态理解,如 GPT-4V 图片识别 | definePluginEntry |
| Capability | 图片生成 | api.registerImageGenerationProvider(...) |
DALL·E / Stable Diffusion 画图 | definePluginEntry |
| Capability | 音乐生成 | api.registerMusicGenerationProvider(...) |
Suno / Udio 作曲 | definePluginEntry |
| Capability | 视频生成 | api.registerVideoGenerationProvider(...) |
Sora / Runway 生成视频 | definePluginEntry |
| Capability | 网页抓取/爬取 | api.registerWebFetchProvider(...) |
自定义网页内容提取器 | definePluginEntry |
| Capability | 网页搜索 | api.registerWebSearchProvider(...) |
接入 Bing / Brave Search API | definePluginEntry |
| Capability | 消息渠道 | api.registerChannel(...) |
接入 Telegram / Discord / Slack 等消息平台 | defineChannelPluginEntry |
| Tools | Agent 工具 | api.registerTool(tool, opts?) |
赋予 LLM 调用外部 API 的能力,如查股票、发邮件 | definePluginEntry(简单 defineToolPlugin) |
| Commands | 自定义命令(绕过 LLM) | api.registerCommand(def) |
注册 /stock 等用户直接调用的命令 |
definePluginEntry |
| Infrastructure | 事件钩子 | api.registerHook(events, handler, opts?) |
在 tool_call 前后、agent_turn 等节点插入逻辑 | definePluginEntry |
| Infrastructure | Gateway HTTP 端点 | api.registerHttpRoute(params) |
暴露 REST API 供外部调用 | definePluginEntry |
| Infrastructure | Gateway RPC 方法 | api.registerGatewayMethod(name, handler) |
注册插件专属 RPC,供 dashboard/web 调用 | definePluginEntry |
| Infrastructure | 局域网 Gateway 发现 | api.registerGatewayDiscoveryService(service) |
通过 mDNS/Bonjour 广播 Gateway 地址 | definePluginEntry |
| Infrastructure | CLI 子命令 | api.registerCli(registrar, opts?) |
注册 openclaw myplugin ... 命令行 |
definePluginEntry |
| Infrastructure | Node 特性 CLI | api.registerNodeCliFeature(registrar, opts?) |
openclaw nodes 下的子命令 |
definePluginEntry |
| Infrastructure | 后台服务 | api.registerService(service) |
启动定时任务、websocket 长连接等 | definePluginEntry |
| Infrastructure | 交互式处理器 | api.registerInteractiveHandler(registration) |
处理 CLI 交互式输入 | definePluginEntry |
| Infrastructure | 工具结果中间件 | api.registerAgentToolResultMiddleware(...) |
在 tool 结果返回给模型前做改写/裁剪(tokenjuice) | definePluginEntry |
| Infrastructure | Memory 附加 prompt 段落 | api.registerMemoryPromptSupplement(builder) |
在 memory 上下文中注入自定义提示 | definePluginEntry |
| Infrastructure | Memory 附加搜索/读取语料 | api.registerMemoryCorpusSupplement(adapter) |
扩展 memory search 的数据源 | definePluginEntry |
| workflow | Session 扩展状态 | api.session.state.registerSessionExtension(...) |
给 session 附加插件私有 JSON 状态,通过 Gateway 投射 | definePluginEntry |
| workflow | 下一轮注入上下文 | api.session.workflow.enqueueNextTurnInjection(...) |
审批流程中向下一个 agent turn 注入提示 | definePluginEntry |
| workflow | 可信工具策略 | api.registerTrustedToolPolicy(...) |
在 before_tool_call 前拦截/改写参数,如预算门控 |
definePluginEntry |
| workflow | 工具目录展示元数据 | api.registerToolMetadata(...) |
不改工具实现,仅修改工具在 UI 中的展示信息 | definePluginEntry |
| workflow | 控制 UI 描述符 | api.session.controls.registerControlUiDescriptor(...) |
给 session / tool / settings 面板注册 UI 控件 | definePluginEntry |
| workflow | 运行时生命周期回调 | api.lifecycle.registerRuntimeLifecycle(...) |
插件卸载/重置时清理资源(定时器、连接等) | definePluginEntry |
| workflow | Agent 事件订阅 | api.agent.events.registerAgentEventSubscription(...) |
监控 agent 运行状态,驱动工作流状态机 | definePluginEntry |
| workflow | 单次 run 临时状态 | api.runContext.setRunContext / getRunContext / clearRunContext(...) |
在一次 agent run 内跨 tool call 共享临时数据 | definePluginEntry |
| workflow | 调度任务清理元数据 | api.session.workflow.registerSessionSchedulerJob(...) |
注册插件拥有的 scheduler job 的清理钩子 | definePluginEntry |
| workflow | Session 附件投递 | api.session.workflow.sendSessionAttachment(...) |
向活跃 session 投递文件附件(bundled-only) | definePluginEntry |
| workflow | 定时 Session Turn | api.session.workflow.scheduleSessionTurn / unscheduleSessionTurnsByTag(...) |
Cron 驱动的定时触发 session turn(bundled-only) | definePluginEntry |
| workflow | Session 动作 | api.session.controls.registerSessionAction(...) |
注册客户端可通过 Gateway 调度的 session action | definePluginEntry |
| Channel 的轻量 setup 入口 | (无注册方法,仅导出 plugin 对象) | channel 禁用/未配置时仅加载最小 profile,不初始化 runtime | defineSetupPluginEntry |
| 四种 注册点 | Import |
|---|---|
| defineToolPlugin | openclaw/plugin-sdk/tool-plugin |
| definePluginEntry | openclaw/plugin-sdk/plugin-entry |
| defineChannelPluginEntry | openclaw/plugin-sdk/channel-core |
| defineSetupPluginEntry | openclaw/plugin-sdk/channel-core |
第四节: 能力注册 link
第五节: 工具和命令
2.4.1 注册Tool
2.4.2 注册 Command link
// 命令 A: /stock-endpoints — 列出所有接口
api.registerCommand({
name: "stock-endpoints", // 声明命令名称,用户输入 /stock-endpoints 触发。
description: "列出所有已配置的接口地址", // 声明命令说明。
agentPromptGuidance: ["用户询问有哪些接口时,建议使用 /stock-endpoints 命令查看。"], // ai何时提示用户这个命令
handler: () => {
const endpoints: Array<{name:string; url:string}> = api.pluginconfig?.apiEndpoints as any;
if (endpoints.length === 0) return { text: "当前没有配置任何接口地址。" }; // 数组为空时返回提示。
const lines = endpoints.map((e) => `- ${e.name}: ${e.url}`); // 每行一个接口:名称: 地址。
return { text: lines.join("\n") }; // 用换行符拼接返回。
},
});
- 注意⚠️: 一定要把
acceptsArgs: true打开否则接收不到第二个参数;handler:(ctx)=>{ctx.args}可以获取第二个参数
// 命令 B: /stock-endpoint <名称> — 按名称查接口
api.registerCommand({
name: "stock-endpoint", // 声明命令名称,用户输入 /stock-endpoint 股票行情 触发。
description: "按名称查看指定接口地址。用法: /stock-endpoint <接口名称>", // 声明命令说明。
acceptsArgs: true, // 允许接收参数(即 <接口名称> 这部分)。
agentPromptGuidance: ["用户想查看某个具体接口的地址时,建议使用 /stock-endpoint <名称> 命令。"],
handler: (ctx) => { // ctx.args 就是用户输入的接口名称。
const endpoints: Array<{name:string; url:string}> = api.pluginconfig?.apiEndpoints as any;
const keyword = (ctx.args ?? "").trim();
if (!keyword) return { text: "请输入接口名称,例如 /stock-endpoint 股票行情。可用的有: " + endpoints.map((e) => e.name).join(", ") }; // 没输入名称时提示可用的。
const found = endpoints.find((e) => e.name === keyword); // 在数组中查找 name 匹配的项。
if (!found) return { text: `未找到名为"${keyword}"的接口。可用的有: ` + endpoints.map((e) => e.name).join(", ") }; // 找不到时提示可用的。
return { text: `${found.name} 的接口地址: ${found.url}` }; // 找到了返回地址。
},
});
第六节: 基础设施 link
2.4.3 注册 Service
第七节: 工作流插件的主机 Hook link
第八节 其他封装
2.8.1 调用内置大模型封装
/**
* 创建临时内嵌 Agent 会话并执行 LLM 任务
* @param api OpenClaw 插件 API 实例
* @param tools 允许调用的工具名称数组,传空数组表示不限制工具
* @param content 传入的上下文内容
* @param prompt LLM 提示词
* @param isExpResJson 是否期望返回 JSON 格式内容,默认 false
* @returns LLM 返回的文本内容
* @description 每次调用创建独立临时 session,结束后自动删除 session 文件
* @example const res = await runTempEmbeddedAgent(api, ["web_fetch"], website, "你是一只猫娘,需要以猫娘的口吻来给用户描述这个网站");
*/
async function runTempEmbeddedAgent(api: any, tools: Array<string>, content: string, prompt: string, isExpResJson: boolean = false): Promise<string> {
const cfg = api.config; // 获取 OpenClaw 全局配置。
// STEP1: 解析 provider / model / authProfileId(对齐 llm-task 官方实现: index.js:L94-L104)
const defaultsModel = cfg?.agents?.defaults?.model; // 读取 agents.defaults.model。
const primaryModelRef = typeof defaultsModel === "string" ? defaultsModel.trim() : (defaultsModel?.primary ?? ""); // 兼容 string 和 { primary } 两种写法。
const slashIndex = primaryModelRef.indexOf("/"); // 查找 provider/model 分隔符。
const provider = slashIndex >= 0 ? primaryModelRef.slice(0, slashIndex).trim() : ""; // 取斜杠前半段作为 provider,如 "opencode"。
const model = slashIndex >= 0 ? primaryModelRef.slice(slashIndex + 1).trim() : primaryModelRef.trim(); // 取斜杠后半段作为 model,如 "deepseek-v4-flash-free"。
const authProfiles = cfg?.auth?.profiles ?? {}; // 读取全局认证配置。
const authProfileId = Object.keys(authProfiles).find((id) => authProfiles[id]?.provider === provider); // 匹配同 provider 的 profile。
if (!provider || !model) throw new Error("未解析到可用默认模型,请检查 ~/.openclaw/openclaw.json agents.defaults.model.primary"); // 没解析到则抛错。
// STEP2: 构建完整 prompt
const jsonPrefix = isExpResJson ? "Return ONLY a valid JSON value. Do not wrap in markdown fences. Do not include commentary.\n\n" : ""; // 是否期望 JSON 返回。
const fullPrompt = `${jsonPrefix}${prompt}\n\nCONTENT:\n${content}`; // 拼接完整提示词。
// STEP3: 调用临时LLM[runEmbeddedAgent] (全新会话)
const timestamp = Date.now(); // 时间戳,用于生成唯一 session/run ID 和最后的清理。
const sessionFile = path.join(os.tmpdir(), `session-temp-${timestamp}.json`); // 临时 session 文件路径,finally 中用于删除。
try {
const result = await api.runtime.agent.runEmbeddedAgent({ // 同步阻塞调用内嵌 LLM。
sessionId: `temp-${timestamp}-${Math.random().toString(36).slice(2, 8)}`, // 独立 session ID。
sessionFile,
workspaceDir: cfg?.agents?.defaults?.workspace ?? process.cwd(), // 工作目录。
config: cfg, // 全局配置。
runId: `temp-${timestamp}`, // 运行 ID。
prompt: fullPrompt, // 完整提示词。
timeoutMs: 30000, // 超时 30 秒。
provider, // 显式传入 provider。
model, // 显式传入 model。
authProfileId, // 显式传入 auth profile。
authProfileIdSource: authProfileId ? "user" : "auto", // 标记为 user 或 auto。
agentDir: path.join(os.homedir(), ".openclaw", "agents", "main", "agent"), // Agent 目录。
toolsAllow: tools.length > 0 ? tools : undefined, // 限制可用工具,空数组不限制。
}); // 结束调用。
const text = (result?.payloads ?? []).filter((p: any) => !p.isError && typeof p.text === "string").map((p: any) => p.text).join("\n").trim();
return text; // 返回提取的文本。
} finally { // 无论成功或失败都要清理临时 session 文件。
try {
if (fs.existsSync(sessionFile)) fs.unlinkSync(sessionFile); // 删除临时 session 文件。
} catch { /* 删除失败时忽略 */ }
}
}
2.8.2 拉起子Agent
第三章 接入LLM
- Title: OpenClaw
- Author: 明廷盛
- Created at : 2026-06-27 11:36:37
- Updated at : 2026-06-18 15:06:00
- Link: https://blog.20040424.xyz/2026/06/27/⏸️VibeCoding/OpenClaw/
- License: All Rights Reserved © 明廷盛