02-随便玩玩-让openclaw给我整一个百度搜索插件

622 阅读8分钟

掘金账号想起来了,记录一下最近的情况。

找到新工作了,没涨薪,房租从以前的1k5变成了3k多,上海的房租还是贵啊。

先干着吧。

openclaw-权限更高的AI工具

最近看AI相关的玩具,浏览到了一个很火的工具。

openclaw

然后看了看视频,相关介绍,感觉可以一玩,下载来玩了玩,还是挺有趣的。

部署在本地,权限给的更多,相当于努比亚最近和豆包合作推出的那款AI手机。

给AI更多的权限,我可以偷更多的懒。

docs.openclaw.ai/zh-CN

image.png

上述是openclaw的官方文档,可以大致看看。

以及,如果想要一步到位的话,也可以看看下面这个官网。

openclaw.ai/

image.png

红框部分可以切换平台,都是一步到位版本,懒人福音。

我因为已经安装过了,就不多做赘述了。

minimax国内方案

国内可以用的AI模型,主要是千问和minimax,我看minimax有订阅,我就先用上了一个月29块的基础套餐。

千问肯定也是可以的,我不贴出来了。

(顺带吐槽一下,可视化视角下的配置参数太难了,动不动就是key就是api之类的配置,但实际上又不是对应的API KEY。此key非彼key。我配置都直接交给openclaw自己配置了。)

platform.minimaxi.com/docs/soluti…

image.png

正在玩的插件——飞书

最新的版本(26年2月2号)官方支持飞书了,挺不错的。

教程都有,不赘述了。

image.png

百度插件——openclaw自己写的

我当时希望openclaw自己能够在互联网上搜索信息,但是发现,搜索引擎对于AI有限制。

目前都是用的搜索API来实现AI搜索的。

不就是为了收钱嘛!

我一开始按照openclaw的推荐,看了看所谓的免费search API——Brave Search。

免费是免费,但是账号绑定要求你输入信用卡信息。

那我不乐意了,遂作罢。

image.png

然后,在后续的对话中,我了解到,国内有一家做搜索引擎的,虽然名声已经不大好了,但总归是搜索引擎。

image.png

是的,某度。

某度的AI搜索API

cloud.baidu.com/doc/qianfan…

主要是智能搜索生成这里。后面的x度搜索才是纯搜索。这里的智能搜索生成,其实AI还是有介入总结的。

image.png

一开始我是这么说的:

https://cloud.baidu.com/doc/qianfan/s/Omh4su4s0
https://cloud.baidu.com/doc/qianfan/s/2mh4su4uy
目前我希望你实现上述两种搜索方式。 第一种是AI介入的,搜索总结 第二种是无AI总结的,搜索结果直接展示。

后面发现,openclaw访问不了页面,我直接把调用案例复制粘贴发给他了。

我直接提供百度搜索(无AI总结)以及有AI总结的搜索的调用案例:

POST /v2/ai_search/web_search HTTP/1.1
HOST: qianfan.baidubce.com
Authorization: Bearer <API Key>
Content-Type: application/json
{
  "messages": [
    {
      "content": "北京有哪些旅游景区",
      "role": "user"
    }
  ],
  "search_source": "baidu_search_v2",
  "resource_type_filter": [{"type": "web","top_k": 20}],
  "search_filter": {
    "match": {
      "site": [
        "www.weather.com.cn"
      ]
    }
  },
  "search_recency_filter": "year"
}

POST /v2/ai_search/chat/completions HTTP/1.1
HOST: qianfan.baidubce.com
Authorization: Bearer <API Key>
Content-Type: application/json
{
    "messages": [
        {
            "content": "近日油价调整消息。",
            "role": "user"
        }
    ],
    "stream": false,
    "model": "ernie-3.5-8k",
    "instruction": "##",
    "enable_corner_markers": true,
    "enable_deep_search": true
}

经过他一阵折腾,似乎是整好了。

image.png

后续测试花了些时间,也算是把插件整好了。

image.png

百度插件部分

我让openclaw写了份md文档。放在最后吧,单独列一个大标题。

一些自己的探索——消息去重逻辑

openclaw的飞书插件,在引入SDK之前,没有消息去重功能。

我加了飞书插件后,时不时会发现,openclaw回复我8小时之前就发过的消息,整得我很懵。

后来搜索了,才知道,原来还有“消息去重”这种逻辑,也是学习到了。

大概思路就是,缓存消息ID,然后接收ID的时候,去对比,如果缓存过就不处理,不推送给openclaw。

如果没缓存,那么就推送openclaw,然后缓存之类的。

openclaw官方后续支持了飞书插件,最新的插件就写了SDK,目前用了几天发现没啥消息重复问题,估计是内部逻辑就解决了。

一些自己的探索——环境要区分

我一开始哼哧哼哧的,让openclaw做开发测试时候,就只开一个网关(环境),崩溃了就直接去openclaw doctor --fix,然后基本上就是插件问题,把插件目录下的对应插件删除,openclaw.json里面删除非法插件的配置信息,就重启成功了。

后来崩溃好几次,我实在受不了了,就想要搭建两个场景。

一个是主环境,一个是开发者环境。(玛德,我为什么不一开始就这么做?!)

后续还担心,openclaw官方不支持同时开启两个环境,查阅了下官方文档,是支持的。

这个文档,中文版是没有的,还是建议访问英文原版的。

实在不行你加个翻译插件嘛(我推荐“沉浸式翻译”,免费的微软翻译就行,你大致看得懂就可以了)

docs.openclaw.ai/gateway/mul…

image.png

庆幸的是,这部分文档,是支持openclaw直接访问的,你把这URL直接甩给它,然后大胆提出你自己的需求,让它自己悟去吧。

(当老板真好,hhhh)

主环境保证运行不出问题。

开发者环境就可以上一些最新的插件,以及你自己开发的插件。

最后出问题了,你不想自己看,还能直接call 另一个环境的AI,让它给你看。

image.png

image.png

大概记得的就这些吧,后续有什么想分享的,再说。

自己的一些探索——上下文极限得主动探测

似乎一开始的openclaw设置里面,没有主动设置上下文检测压缩。

内存刷新(memory flush)也是在你新建session之后才会压缩的。我飞书对话基本上不会主动new session。

那么问题来了,如何压缩上下文呢?

我遇到过上下文极限,导致LLM报错的问题:

LLM request rejected: invalid params, tool result's tool id(call_function_qkzwh2u55cij_1) not found (2013)

image.png

虽然最后AI分析,是生命周期之类的问题(我忘了,我问问AI)。

AI也忘了可还行。我记得当时是说第一个。

image.png

后续就让AI给我一些建议,包括监听上下文token占比啥的,主动发探测包啥的。

我忘记当时建议了,直接让AI总结现有方案了。

image.png

image.png

单独列举——我要让AI给我写日报

我痛恨两种人,一种就是让我写日报的人,另外一种就是阻止我要求别人写日报的人。

image.png

既然如此,周报、月报你都一块儿写了吧。

image.png

百度搜索插件安装指南

适用于 OpenClaw v2026.2+ | 插件类型: Tool Plugin


📦 插件概述

百度搜索插件提供两个搜索工具:

  • baidu_search - 原始搜索结果
  • baidu_ai_search - AI智能搜索(百度千帆)

依赖: 需要百度千帆API Key


📁 文件结构

插件只需要2个文件:

extensions/baidu-search/
├── index.ts              # 主代码 (218行)
└── openclaw.plugin.json  # 插件配置 (13行)

🔧 安装步骤

步骤1:创建插件目录

mkdir -p ~/.openclaw-dev/extensions/baidu-search
cd ~/.openclaw-dev/extensions/baidu-search

步骤2:创建插件代码文件

文件1: index.ts (主逻辑)

import { Type } from "@sinclair/typebox";

export const baiduSearchConfigSchema = {
  parse(value: unknown): { apiKey: string } {
    if (!value || typeof value !== "object" || Array.isArray(value)) {
      throw new Error("baidu-search config required");
    }
    const cfg = value as Record<string, unknown>;
    
    if (typeof cfg.apiKey !== "string" || !cfg.apiKey) {
      throw new Error("apiKey is required in baidu-search config");
    }
    
    return { apiKey: cfg.apiKey };
  },
  uiHints: {
    apiKey: {
      label: "Baidu Qianfan API Key",
      sensitive: true,
      placeholder: "bce-v3/...",
      help: "API Key from Baidu Qianfan Console",
    },
  },
};

const baiduSearchPlugin = {
  id: "baidu-search",
  name: "Baidu Qianfan Search",
  description: "Search tools using Baidu Qianfan API",
  kind: "tool" as const,
  configSchema: baiduSearchConfigSchema,

  register(api: {
    registerTool: (tool: {
      name: string;
      description: string;
      parameters: unknown;
      execute: (_id: string, params: Record<string, unknown>) => Promise<{ content: { type: string; text: string }[] }>;
    }, opts?: { optional?: boolean }) => void;
    pluginConfig: unknown;
  }) {
    const cfg = baiduSearchConfigSchema.parse(api.pluginConfig);
    const BASE_URL = "https://qianfan.baidubce.com";

    async function callQianfanAPI(
      apiKey: string,
      endpoint: string,
      body: Record<string, unknown>
    ): Promise<unknown> {
      const response = await fetch(`${BASE_URL}${endpoint}`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Authorization": `Bearer ${apiKey}`,
        },
        body: JSON.stringify(body),
      });

      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(`API调用失败: ${response.status} ${response.statusText} - ${errorText}`);
      }

      return response.json();
    }

    // AI智能搜索工具
    api.registerTool({
      name: "baidu_ai_search",
      description: "使用百度千帆AI进行智能搜索,返回AI总结后的结果",
      parameters: Type.Object({
        query: Type.String({ description: "搜索问题或关键词" }),
        model: Type.Optional(Type.String({ description: "使用的模型", default: "ernie-3.5-8k" })),
        enableDeepSearch: Type.Optional(Type.Boolean({ description: "是否启用深度搜索", default: true })),
      }),
      async execute(_id, params) {
        const { query, model = "ernie-3.5-8k", enableDeepSearch = true } = params as any;

        try {
          const response = await callQianfanAPI(cfg.apiKey, "/v2/ai_search/chat/completions", {
            messages: [{ content: query, role: "user" }],
            stream: false,
            model,
            instruction: "##",
            enable_corner_markers: true,
            enable_deep_search: enableDeepSearch,
          });

          return { content: [{ type: "text", text: JSON.stringify({ success: true, query, mode: "AI智能搜索", response }, null, 2) }] };
        } catch (error) {
          return { content: [{ type: "text", text: `搜索失败:${error instanceof Error ? error.message : "未知错误"}` }] };
        }
      },
    });

    // 原始搜索工具
    api.registerTool({
      name: "baidu_search",
      description: "使用百度搜索获取原始结果,直接展示搜索结果(无AI总结)",
      parameters: Type.Object({
        query: Type.String({ description: "搜索关键词" }),
        maxResults: Type.Optional(Type.Number({ description: "返回结果数量", default: 10 })),
        searchRecency: Type.Optional(Type.String({ enum: ["day", "week", "month", "year"], default: "year" })),
      }),
      async execute(_id, params) {
        const { query, maxResults = 10, searchRecency = "year" } = params as any;

        try {
          const response = await callQianfanAPI(cfg.apiKey, "/v2/ai_search/web_search", {
            messages: [{ content: query, role: "user" }],
            search_source: "baidu_search_v2",
            resource_type_filter: [{ type: "web", top_k: maxResults }],
            search_filter: { match: { site: [] } },
            search_recency_filter: searchRecency,
          });

          return { content: [{ type: "text", text: JSON.stringify({ success: true, query, mode: "百度搜索(原始结果)", count: maxResults, response }, null, 2) }] };
        } catch (error) {
          return { content: [{ type: "text", text: `搜索失败:${error instanceof Error ? error.message : "未知错误"}` }] };
        }
      },
    });
  },
};

export default baiduSearchPlugin;

文件2: openclaw.plugin.json (插件元数据)

{
  "id": "baidu-search",
  "configSchema": {
    "type": "object",
    "additionalProperties": false,
    "properties": {
      "apiKey": { "type": "string" }
    }
  },
  "uiHints": {
    "apiKey": { "label": "API Key", "sensitive": true, "placeholder": "请输入百度搜索API Key" }
  }
}

步骤3:配置 OpenClaw

修改 ~/.openclaw-dev/openclaw.json,添加:

3.1 注册插件路径
{
  "plugins": {
    "load": {
      "paths": [
        "/home/user/.openclaw-dev/extensions/baidu-search"
      ]
    }
  }
}
3.2 启用插件并配置API Key
{
  "plugins": {
    "entries": {
      "baidu-search": {
        "enabled": true,
        "config": {
          "apiKey": "你的百度千帆API Key"
        }
      }
    }
  }
}
3.3 添加工具白名单
{
  "tools": {
    "allow": [
      "baidu_search",
      "baidu_ai_search"
    ],
    "baiduSearch": {
      "apiKey": "你的百度千帆API Key"
    }
  }
}

步骤4:重启 Gateway

openclaw --profile dev gateway restart

🔑 获取API Key

  1. 访问 百度千帆控制台
  2. 登录账号
  3. 进入「API Key管理」
  4. 创建或复制现有API Key
  5. 确保已开通「AI Search」相关服务

✅ 验证安装

openclaw --profile dev plugins list | grep baidu

输出应该显示:

baidu-search  │  loaded  │  ~/.openclaw-dev/extensions/baidu-search/index.ts

⚠️ 注意事项

  1. API Key 敏感信息: 分享给他人时,抹去 apiKey 的实际值
  2. 插件路径: 确保 paths 中的路径正确指向 index.ts 所在目录
  3. 工具白名单: 必须将 baidu_searchbaidu_ai_search 加入 tools.allow
  4. 双重配置: API Key 需要在 plugins.entries.baidu-search.configtools.baiduSearch 两处配置

📝 完整配置示例

{
  "plugins": {
    "load": {
      "paths": [
        "/home/user/.openclaw-dev/extensions/baidu-search"
      ]
    },
    "entries": {
      "baidu-search": {
        "enabled": true,
        "config": {
          "apiKey": "bce-v3/ALTAK-xxxxx"
        }
      }
    }
  },
  "tools": {
    "allow": [
      "baidu_search",
      "baidu_ai_search"
    ],
    "baiduSearch": {
      "apiKey": "bce-v3/ALTAK-xxxxx"
    }
  }
}