OpenClaw

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.jsonopenclaw.plugin.jsonindex.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

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)

第一节 注册类型和方式

①能够注册哪些? link ②每种通过什么注册? link

类别 用途 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

第五节: 工具和命令

2.4.1 注册Tool

// 命令 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}` }; // 找到了返回地址。
},
});

2.4.3 注册 Service

第八节 其他封装

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 © 明廷盛