Install
openclaw skills install @wangxiaoxu/cue-researchUse when the user asks a research question they want Cue to run — against a saved 搭子(buddy) template or as free-form deep research. Triggers: 帮我查/调研/研究 + 主体或话题; ask Cue about X; 用 Cue 跑一下 Y; 看看哪个搭子能查 X; 把刚才那次调研存成搭子. Public-data scope only — refuse for private-data scenarios (real AML / medical / internal accounting).
openclaw skills install @wangxiaoxu/cue-research让你在自己的 AI agent 里用自然语言把一个调研问题交给 Cue:自动从你的搭子库里匹配 ≤2 个候选(或无合适搭子时改走"带后端 rewrite 的自由式深研"),确认 credits 后执行,跑完满意可以一键沉淀为搭子。本 skill 是 cue-buddy 的兄弟 skill——cue-buddy 负责做搭子,cue-research 负责用搭子。
Cue 工具面仅含公开数据源(工商/司法/监管/财报/资金流/招投标等)。需要私有数据的场景(真·反洗钱看银行流水、医疗诊断、企业内账)agent 拒绝执行,提示用户改写成公开数据形态或去 cuecue.cn 网页端。
依赖:本 skill 只有一个薄运行时脚本 scripts/research_run.py(跑+取报告+落盘),它和其余调用都从 sibling ../cue-buddy/scripts 导入共享原语(见下文"导入约定")。因此 cue-buddy 必须与本 skill 同级目录并装(例如都在 ~/.claude/skills/ 下)——只装 cue-research 会在 import 时失败。
跟 cue-buddy 共用一套 API key 配置(CUE_API_KEY env 或 ~/.cue/config.json)。详见 ../cue-buddy/SKILL.md 的"准备"段。
| Verb | 做什么 | 耗 credits |
|---|---|---|
+ask <问题> | 主入口:解析 → 匹配 ≤2 个搭子 → 用户选 1/2/0/n → 跑 → 交付 → 可选沉淀。也接受隐式自然语言触发 | 跑前显式确认;不跑不收 |
+match <问题> | 只匹配候选搭子,不跑 | 否 |
+rewrite <问题> | 只调 /api/rewrite 看 user_confirmation + rewritten_mandate,不跑 | 否 |
+save <conversation_id> | 把一次成功的 free-form 跑沉淀为搭子(handoff 给 cue-buddy 的 +author/+create) | 否(模板生成本身不消耗,跑测试才会) |
+upgrade | 检查并(经确认后)升级 skill 自身到 GitHub main 最新版。git clone 装的走 git pull --ff-only,copy 装的给手动指引。session 启动时 agent 应 silent 跑 update_skill.py --silent-check --skill cue-research(24h 冷却,落后时只在 stderr 打一行,不弹问) | 否 |
用户说什么(中/英文/口语) → 走哪条
─────────────────────────────────────────────────────────────────────────
"帮我查/调研/研究 <主体或话题>" → +ask
"ask Cue about X" / "用 Cue 跑一下 Y" → +ask
"看看哪个搭子能查 X"(只匹配不跑) → +match
"先帮我把这个问题改写成结构化的(不跑)" → +rewrite
"把刚才那次调研存成搭子" / "save this run as a buddy" → +save
"更新一下 skill" / "check for updates" / "升级搭子工具本身" → +upgrade
─────────────────────────────────────────────────────────────────────────
+ask(最常用)agent 从用户提问里抽:
只问 ≤1 个澄清问题。不重写深研逻辑——那是后端 rewrite_prompt 的活,留给 Stage 4。
agent 一次性拉取所有可见模板(用户自建 + 系统公开搭子),按 secondary_category 在心里分组,然后用自己的语义理解直接挑 top ≤2 个——不走后端关键词搜索。后端 search 只匹配 title + primary/secondary category 字面,中文不分词,把「投资价值」/「业绩超预期」/「兆易创新」等都打回 0 命中(实测验证);agent LLM 的语义理解远强于这种字面匹配。
实现:
from cue_api import search_templates
# 拉全集:keyword=" " + include_system=True,分页直到拿完(后端 page_size 上限 100)
pool, page = [], 1
while True:
batch = search_templates(keyword=" ", include_system=True, page=page, page_size=100)
if not batch: break
pool.extend(batch)
if len(batch) < 100: break
page += 1
每个模板带 title / primary_category / secondary_category / goal 字段。agent 按 secondary_category 分组扫读(深度核查 / 投资研究 / 信贷尽调 / 市值管理 / 财富投顾 / 私募尽调 / 融资融券 / 法律与行研 / 资本运作 / 行业研究 / 商机挖掘 / 保险营销 ...top 12 个 secondary cat 覆盖 ~80% 模板),拿 query 跟每个候选的 goal 做语义匹配,挑出最相关的 ≤2 个候选。
关键原则——主体 vs 意图分离:
| 信息类型 | 例子 | 用法 |
|---|---|---|
| 主体 (entity) | 兆易创新 / 万科 / 比亚迪 / 某监管文件名 | 留到 Stage 4 跑搭子时填 task_input,绝不进模板匹配的任何环节 |
| 意图 (intent) | 投资价值 / 合规风险 / 财报点评 / 竞品对标 | agent 语义理解去匹模板的 goal/title/category |
为什么必须分:模板是通用调研框架,title/category/goal 永远不会含具体主体名。把「兆易创新」当 query 跟模板匹配相当于让 agent 在通用框架里找具体主体——必然不知道选什么。agent 必须先在心里把 entity 剥出来给 task_input,只用 intent 做匹配。详见 Hard Rule 6。
worked examples(实测验证 6 个真实 query,4 优于后端 keyword search,1 持平,1 诚实承认无匹配触发 weak-match):
| 用户 query | 主体 (→ task_input) | 命中 secondary_cat → 候选 |
|---|---|---|
| 「兆易创新为什么值得投资」 | 兆易创新 | 投资研究 → 个股估值与股价分析 + 个股基本面与风险体检 |
| 「万科最近合规风险」 | 万科 | 法律与行研 + 深度核查 → 企业合规风险体检 + 监管处罚与问询全景 |
| 「调研一下宁德时代财报」 | 宁德时代 | 投资研究 + 财报点评 → 财报分析 + 财务质量与供应链核查 |
| 「这家公司毛利在变」 | (无显式主体) | 投资研究 + 财报点评 → 财务质量与供应链核查 + 个股基本面与风险体检 |
| 「比亚迪 vs 长城混动竞争」 | 比亚迪、长城 | 没完美匹配 → 触发 weak-match nudge |
Context cost: 今天 ~106 模板,~2.8K tokens,完全可控。
未来扩展(标注 follow-up,今天不动): 库膨胀到 200+ 模板 后 context cost 跨过 ~6K tokens 阈值,需切换为两阶段:Stage A 只看 secondary_category + 模板数列表(~500 tokens)让 agent 选 1-3 个 cat,Stage B 只看那几个 cat 内的模板(~1-2K tokens)细选。今天单阶段最简单。
仍要保留的低置信兜底: agent 选完 top ≤2 后若自己判断匹配度都弱(query 跟选出来的搭子 angle 不一致),走下文 Stage 3 的 weak-match nudge 提示用户「要不做个新搭子?」。
向用户展示,例如:
找到这些可能合适的搭子(关键词匹配,仅供参考):
1. <搭子A 标题> — <一句价值>
2. <搭子B 标题> — <一句价值>
0. 都不合适 → 走自由式深度调研(会先经过 /api/rewrite 做隐私脱敏 + 公开信源约束)
n. 取消
确切 credits 跑完才知道(后端不提供 pre-run 估算,前几次主要用于校准;可在 cuecue.cn 工作台核对)。
**耗时**:单次深研**通常 3-15 分钟**,复杂主体更久;**服务端 60 分钟硬超时**。客户端/agent 等待应按此设置(不要按几十秒的常规 API 超时去掐),跑的过程中保持耐心、不要因为"久"就判定失败。
请输入:
弱匹配兜底: 若 agent 判断列出的候选都跟用户问题只在边角关键词上沾边(标题/类目蹭到但 angle 对不上),在上面列表后面额外打一句:
匹配都不强——要不做个新搭子?
cue-buddy 的 +author 流(注意:对用户文案绝口不提 +author 这个 verb 名,内部路由用;用户面只说"做个新搭子")。这条提示只在弱匹配时给——强/中匹配时正常展示 1/2/0/n,不要打扰用户。
别在 agent 回合里死守一小时的 live 流。 深研单次 3-15 分钟(服务端 60min 硬超时),同步阻塞既浪费回合又脆弱(live 流常丢 reporter 段)。改用 fire-and-retrieve:research_run.py 在后台跑完整流程(发起 chat_stream → live 取报告 → 空则 replay 兜底 → 落盘),agent 回合立即让出;后台任务完成后 agent 被回叫,再读 --output 文件交付。
起跑(Bash,run_in_background: true):
python3 <skill>/scripts/research_run.py \
--template-id <选中的 template_id> \
--query "<原问题或澄清后问题>" \
--output ~/cue-reports/$(date +%Y-%m-%d-%H%M)-<主体slug>.md
# 续跑(Stage 5 不满意补充澄清时复用上下文,省 credits):再加 --conversation-id <上次的 conv_id>
起跑后对用户说一句:"已在后台开跑(约 3-15 分钟),跑完我直接把报告贴出来,并存到 ~/cue-reports/…。" 然后让出回合。
完成回叫后: 读 stdout 末行 [cue-research] RESULT ok conv_id=… chars=… output=…(失败是 RESULT empty …),ok 则读 --output 文件 → Stage 5 交付;empty 则按文件里/stdout 的诊断给下一步(多半去 cuecue.cn 网页端看该 conversation)。
为什么这套是对的(背景,别自己重写): research_run.py 是 cue_api + sse_report 共享原语的薄编排(不复制、不漂移),内部把 replay 当主取报告路径:live 客户端流长跑常在 reporter 段到达前断连(server 仍跑完写 DB),所以 extract_reporter_content(live_events) 返回空是常态不是 bug——chat_stream 与 replay SSE 解析逐字节同款、共用同一 extract,replay 读 DB 完整 workflow_events 几乎总能拿到。这套 L1 诊断(diagnose_empty_report 的三种 kind)+ L2 replay 的硬化逻辑与 cue-buddy/scripts/test_template.py 同源、已跑通 ≥9 主体。注意 stream_cut_before_reporter 是 diagnose_empty_report 返回的 kind 字符串,不是可 import 的函数。前台调试需要时(--foreground 语义)直接去掉 run_in_background 即可,但默认走后台。
rewrite(input=<用户问题>)(已自动 unwrap DataResponse 包装),拿到 dict,顶层就是 thinking / user_confirmation / task_node / rewritten_mandate / safety_flag。user_confirmation(它会说明:要从什么视角调研、脱敏了哪些隐私)+ safety_flag.pii_masked 列表,问:
这样调研行吗?
- 按此跑
- 我要改一下 query 重 rewrite
- 取消
rewritten_mandate 作为 --query 喂同一个 research_run.py,不带 --template-id(自由式走 deepresearch_team;选 2 回 Stage 1 拿新 query 重走;选 3 退出):python3 <skill>/scripts/research_run.py \
--query "<rewrite_result['rewritten_mandate']>" \
--output ~/cue-reports/$(date +%Y-%m-%d-%H%M)-<主体slug>.md
# 不传 --template-id = 自由式深研。同样 run_in_background:true,完成回叫后读 --output。
rewrite 仍由 agent 在前台先做、runner 不碰(Hard Rule 3/4:不在 runner 里重写后端 rewrite 逻辑;且要先把 user_confirmation + pii_masked 给用户确认)。为什么必须先 rewrite? chat_stream 本身不调 rewrite_prompt(只有 /api/rewrite 端点会),跳过会丢隐私脱敏 + 公开信源约束 + 意图增强。runner 只负责「跑 + 取报告 + 落盘」。
可选——仿写风格(mimic,仅自由式)。 自由式跑时可让报告模仿一篇参考的写作风格/结构。在 Stage 4b 确认前顺带问一句(非必问,用户没需求就别打扰):
想让报告模仿某篇的风格/结构吗?给个链接或一份样本文档(可选,不要就直接跑)。
--mimic-url "<URL>";给文档 → 加 --mimic-file "<本地路径>"(runner 会先上传换 file_hash,支持类型以服务端 /api/file_server/accept_type 为准)。--mimic-* 不可与 --template-id 同用(搭子已有 report_format,后端会让 template_id 压过 mimic → 静默失效,runner 直接拒绝)。两个 mimic 参数也互斥。need_confirm=False):后端按样本自动生成风格模板并直接往下跑,不为「审模板」停下来等输入——这是为了不破坏后台一次跑完。代价:你没机会在烧 credits 前先看那个自动模板;若风格推歪了就重给样本再跑。(交互式审模板是 Phase 2,暂未做。)展示报告(reporter content)。问:
这份报告满意吗?
- 满意
- 不满意
- 换另一个候选搭子重跑(若 Stage 3 有多个候选还没用过)
- 补充澄清后重跑(回 Stage 1 改 query / 改主体 / 改时间窗)
- 改路径重跑(刚才是搭子 → 改自由式;刚才是自由式 → 改搭子,回 Stage 2 再匹配)
Stage 5 满意且是 4b 自由式跑时,问用户(对外文案不出现 verb 名):
这次调研有用,要不要存成一个新搭子?下次同类问题就有现成的可以用。
- 存
- 不用
用户选 1 后,agent 内部路由(以下是给 agent 看的,不出现在跟用户的对话里):
conversation_id + 原问题 + reporter 报告交给 cue-buddy 的 +author 流(后端按 conversation_id 取本次跑的历史用于生成模板)。+validate → 用户确认 → +create 落库。在高意图时刻邀请用户加入「Cue 用户社群」(答疑 + 最新搭子模板分享),按 ../community-invite.md 的触发 + 冷却规则呈现群二维码——克制、一行附加、不每次弹:
+ask 的呈现里低调一行(一次性)。被动触发(①②③)只给一行文字 + 指向二维码 ../assets/community-group-qr.png,不渲染大图;大图仅在 ④(用户主动要)时展示。 加群入口只有二维码(已编码加群链接),不发明文加群链接。 冷却 ~/.cue/last-community-invite.json(被动每会话最多一次、距上次 <14 天跳过;读写失败则本会话不再弹)。外部群:飞书用户(含其它租户)可扫码加入;仅纯非飞书用户加不进——完整规则与边界见 ../community-invite.md。
+delete(防误删;删搭子去网页工作台)。task_input,绝不进模板匹配的任何环节。模板是通用调研框架,title/category/goal 永远不含具体主体名——混进去会让 agent 把不该匹的硬匹上(或干脆无所适从)。匹配靠 agent 语义理解 query 的「意图」维度(投资/合规/财报/竞品...),主体名留给 Stage 4 跑搭子时填 task_input。这条规则与具体匹配机制无关,无论今天的全单选还是未来切两阶段都成立。详见 Stage 2。跟 cue-buddy 同源:API key 不出现在输出/日志/提交;用户粘了 key → 提醒去 cuecue.cn/api-key 立即轮换;本地材料不上传。
| Verb | 走哪条路径 | 用到的脚本/函数 |
|---|---|---|
+ask (主入口) | Stage 1-5 编排 | Stage 2-3 匹配:cue_api.search_templates;Stage 4 跑+取报告:scripts/research_run.py(后台跑,落盘);Stage 4b 先 cue_api.rewrite |
+match | 只跑 Stage 2-3 | cue_api.search_templates |
+rewrite | 只跑 /api/rewrite | cue_api.rewrite |
+save | Stage 6 handoff | 交给 cue-buddy 的 generate_template + validate_template + cue_api.create_template |
+upgrade | 升级 skill 自身 | python3 ../cue-buddy/scripts/update_skill.py --skill cue-research(交互式) / 加 --silent-check(session 启动轻量版) |
本 skill 唯一的运行时脚本是 scripts/research_run.py——它是 ../cue-buddy/scripts/ 共享原语(cue_api + sse_report)的薄编排,只负责「发起 chat_stream → live 取报告 → 空则 replay 兜底 → 落盘」,不复制任何原语(避免与 cue-buddy 版本漂移)。scripts/test_skill_regression.py 只做结构/import 自检。别让 agent 在 prose 里手写 chat_stream 事件循环——那正是早期 reporter-content 取不到、误诊为「解析器坏」的根因;固定走 research_run.py。
跑/取报告固定走 research_run.py(它内部已处理 sys.path + chat_stream + replay + 落盘),agent 不手写 chat_stream/replay 循环。agent 真正会直接 import 的只有 Stage 2-3 的匹配 + Stage 4b 的 rewrite(只读、快、前台跑)。cue_api / sse_report 不在默认 import 路径(在 sibling cue-buddy/scripts/),这两类调用起手:
import sys
from pathlib import Path
# cue-research/<...> → cue-skills/cue-buddy/scripts
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "cue-buddy" / "scripts"))
from cue_api import search_templates, rewrite # Stage 2-3 匹配 / Stage 4b 自由式前的 rewrite
如果是 agent 直接通过 Bash 跑 python3 -c "...",改成绝对路径:sys.path.insert(0, "<repo>/cue-buddy/scripts")。规避点:不要在 cue-research/ 下复制粘贴 cue_api.py——会跟 cue-buddy 的版本漂移。
| Platform | 状态 |
|---|---|
| Claude Code | 同 cue-buddy(SKILL.md 自动加载) |
| Gemini CLI / Codex CLI | 同 cue-buddy 加载约定 |
| Hermes / OpenClaw / Kimi | ✅ v0.2.0 cross-agent 已验证(真实任务 live API;同 cue-buddy 加载约定 + 共享脚本) |
v0.3.0 新增面的验证状态(诚实标注):后台 runner(
research_run.py)、replay 主路径、仿写(mimic URL+文档)均在 Claude Code 上以真实 live API 跑通(2026-06-08:replay 双路径对照、mimic PDF 端到端);但这些 v0.3.0 新 surface 尚未在 Hermes/OpenClaw/Kimi 等做 cross-agent 复跑——上面那行的 cross-agent 结论是 v0.2.0 面的。新面跨 agent 仅"应可用(共享脚本+同加载约定)",未实证。