买方事件驱动投研雷达
> Pay Skill 范式:鉴权型(agent_local)
> 鉴权型:履约在本机执行(需本地取数/解析大文件),远端网关只做支付鉴权,支付通过后返回 fulfillment: "agent_local",Agent 再跑 scripts/ 下的脚本产出结果。
Overview
把 WorkBuddy 变成买方投研团队的事件驱动研究助手——不为使用者提供更多信息,而是在信息洪流里
准确回答两件事:哪些事件对当前仓位真正重要,以及市场是否已经预期到了。
核心差异点不在"抓取公告",而在预期差判断:
预期差 = 实际值 − 市场已 price in 的水平
↑ ↑
公告披露的事实 一致预期 + 前期股价已反映的部分
只回答"实际值"是资讯搬运,不是研究。三条要素缺一不可。
覆盖范围:A 股 / 港股 / 基金的公开公告与资讯;业绩预告、并购重组、股东增减持、
监管问询、经营合同、研报评级、资金异动、行业政策八大类事件。
边界(明确不做):
- 不访问任何非公开数据源、不使用内幕信息;
- 不给出具体买卖价格、目标价、买卖指令或择时建议;
- 不对未发生的事件做断言,不承诺收益;
- 不替代研究员的最终判断——提供判断依据,决策权归使用者。
When to Use(触发条件)
- 用户说「帮我梳理今天持仓股的重要公告 / 有没有预期差」时
- 用户说「XX 公司刚发的这个公告,市场预期到了吗 / 算超预期还是低于预期」时
- 用户说「扫一遍我的自选/持仓,看看哪些需要今天处理」时
- 用户说「这个行业最近有什么政策/价格数据异常,对我持仓影响多大」时
- 用户说「把这份事件解读整理成能进投决会留痕的简报」时
不触发:单纯问行情报价、问概念解释、要求给买卖点位——这些不在本 Skill 职责内,
应如实说明边界。
First-Use Configuration(首次使用配置)
首次对话时向用户收集以下参数;未提供时使用默认值,并在回复中提示可调整。
| 参数 | 默认值 | 说明 |
|---|---|---|
org_name |
空 | 机构名称,用于简报抬头与投决留痕 |
default_window_hours |
24 |
默认扫描窗口;72 可覆盖周末累积披露 |
default_weight |
一般持仓 |
用户未提供权重清单时的默认层级 |
heavy_position_pct |
5.0 |
单只占组合比例超过此值(%)即按重仓处理 |
filter_routine_buyback |
true |
是否过滤港交所翌日披露报表等程序性回购进度 |
rating_sync_threshold |
3 |
研报评级生效门槛:同步调整券商家数(低于则为噪音) |
output_format |
markdown |
输出格式:markdown / table / json |
tier_threshold_multiplier |
1.3 |
分档阈值上调系数(上线初期宁可漏不可扰,稳定后可调至 1.0) |
include_tier_c |
false |
简报是否包含 C 级噪音条目 |
配置文件:config.yaml。
Workflow(工作流)
> 鉴权型职责划分(重要):取数依赖使用者本机的聚源 MCP / 腾讯自选股 MCP 连接器,
> 远端网关没有这些数据源,因此——
> Agent 负责取数与判断,scripts/run_local.py 负责可计算、可复现的部分。
> 脚本不直接调用 MCP(Python 无法调用 WorkBuddy 的 MCP 工具),它消费 Agent 整理好的事件 JSON。
Step 1 · 明确标的与范围
确认涉及哪些标的(持仓 / 候选池 / 具体代码)、时间窗口、关心单一事件还是一组事件。
若用户给出持仓清单,按权重分层:重仓优先、同业参考从简。
标的或时间窗口不明确时先问清楚,不要默认全市场扫描。
Step 2 · 逐只取数(Agent 执行,调用本机 MCP)
按标的逐只、明确带上证券代码或简称发起查询——聚源是语义检索,泛查召回率无保障。
- 公告原文 → AnnouncementData(查公司事件的第一入口)
- 市场反应交叉验证 → NewsDataQuery
- 一致预期与评级 → FinancialResearchReport
- 精确数值(营收/估值/涨跌幅)→ FinQuery
- 产业时序数据 → MacroIndustryData
⚠️ 首次使用前须做数据源自检;聚源鉴权失败时立即转入 TOKEN 配置引导,
不得绕过、不得凭记忆编造数据。
Step 3 · 过滤与分类(scripts/run_local.py 执行)
Agent 把取回的公告整理成事件 JSON,交给脚本做确定性处理:
python3 scripts/run_local.py events.json --out scored.json
脚本完成:程序性内容过滤 → 八大类归档 → impact_score 打分 → S/A/B/C 分档。
规则细节见 references/rules.md。
Step 4 · 预期差判断与简报撰写(Agent 执行,核心增值环节)
Agent 基于脚本输出的分档结果 + 取回的原文,逐条判断:
1. 实际值是多少?(原文明确写出才采信)
2. 基准是什么?(一致预期 > 预告区间中值 > 同比 > 趋势外推;拿不到就标注"无基准")
3. 市场已反映多少?(事件前 5/20 日超额涨跌 + 估值分位)
框架与降级方案见 references/rules.md 第二节。简报格式见 references/output_templates.md。
Step 5 · 交付
输出结构化简报,每条事实附原文出处(公告标题 / 披露时间 / 聚源 source_address 链接)。
首次运行自检(建议):
python3 scripts/run_local.py demo
用内置合成数据跑通分类→过滤→打分→分档主链路,验证本机 Python 环境可用。
在向用户发起付费调用前先跑一次,避免用户付费后才发现环境跑不起来。
Output(输出规范)
每份简报必须包含五要素:发生了什么 / 预期差判断 / 对仓位的影响 / 建议动作 / 需要核实。
优先级分档(由 scripts/run_local.py 计算,Agent 可据判断微调并说明理由):
| 档位 | 分值 | 含义 | 处理 |
|---|---|---|---|
| S 级 | ≥ 70 | 重仓股重大超预期或重大利空 | 立即处理,置顶呈现 |
| A 级 | 40–69 | 需当日跟进 | 排在简报前部 |
| B 级 | 15–39 | 值得知晓 | 简报中部,简要陈述 |
| C 级 | < 15 | 噪音 | 仅归档,不占篇幅 |
事实标注纪律:
- 每个事实陈述附原文引用标记,能给出公告标题、披露时间、原文链接;
- 严格区分【已证实】与【推测】,推测必须以"推测:"开头;
- 原文中没有支撑片段时,明确写"原文未载明",不得填充;
- 一致预期拿不到时如实标注基准类型,不用行业常识代替数据。
结尾固定免责声明:
> 本内容基于公开信息整理,仅供内部研究参考,不构成投资建议。
建议动作枚举(五选一,不给价格与指令):
立即调研 | 列入投委会讨论 | 更新盈利预测 | 维持观察 | 仅归档
Notes / Constraints(约束)
合规红线(不可逾越):
1. 只用公开信息——不推测、不编造、不使用非公开来源,这是本 Skill 存在的合规基础;
2. 禁止编造原文引用——若原文无支撑片段,写"原文未载明";
3. 禁止给出买卖价格、目标价或明确买卖指令;
4. 付费不能成为编数据的理由——取不到的数据标注「未获取」,严禁因用户已付费而推测补造;
鉴权型三条纪律(见下方付费章节 Step 5):
支付未确认前不执行取数 / already_fulfilled: true 时复用上次结果 / 取不到就标注未获取。
噪音过滤铁律:程序性公告(说明会时间预告、制度修订、例行担保、权益分派实施等)
一律不进简报正文,仅在末尾汇总条数。单家券商评级调整默认降档处理,
需三家以上同步且盈利预测调整方向一致才升档。
宁可漏,不可扰:拿不准的不硬凑,明确说"证据不足"优于给出似是而非的判断。
上线初期分档阈值整体上调 30%,根据使用者反馈逐步下调。
不替代:本 Skill 输出的是研究依据与优先级排序,不替代研究员的独立判断、
不替代投决会流程、不构成投资决策本身。
Pay Skill 模式(鉴权型,按次付费,已接入 X402)
本 Skill 为付费技能(Pay Skill),按次收费,已通过腾讯 SkillHub +
微信支付 Agent Pay X402 协议接入。不存在免费运行模式——
未完成支付授权前,不得执行本地履约脚本、不得输出任何付费内容;
鉴权型只由服务端返回的 paid: true 解锁本机履约。
> 使用者须已安装并开通 weixinpay_pay 插件(微信 AI 支付 / AI 专属卡)。
> Step 0 检查不通过时不发起付费调用,直接引导开通后重试。
鉴权型:履约在本机执行(需调用本地取数脚本 / 解析本地或远程大文件),
远端网关只负责订单鉴权与支付状态确认,支付通过后返回 fulfillment: "agent_local",
不返回业务结果;Agent 收到 paid: true 后才在本地跑 scripts/ 下的脚本产出结果。
- 统一网关主接口:
POST https://pay.zerone-iteration.com/api/invoke
(请求体{"skill": "buy-side-event-radar", "skill_version": "1.0.0", "query": "...", "amount": 490}) - 兼容入口:
POST https://pay.zerone-iteration.com/api/resource(等价于默认 Skill) - 支付回调:
POST https://pay.zerone-iteration.com/api/pay/notify - 退款回调:
POST https://pay.zerone-iteration.com/api/refund/notify - 实现:透明网关(nginx + Java 17 / Spring Boot + WechatPay-Java,微信支付公钥模式);
skill/skill_version仅做格式校验后透传进 X402 预下单,不查 SkillHub(不查注册表、不反查是否真实存在/已发布/版本匹配);
无本地白名单,新增 Skill 免 Java 注册、免改 JAR、免重启,直接POST /api/invoke传正确 slug+版本即可 - 状态:未联调 —— 包内
pay/server.py为 Python 参考实现;生产由
pay.zerone-iteration.com透明网关承载(Java 17 / Spring Boot,微信支付公钥模式)。
首次上线须先在DEV_MODE=true下验证 402 响应结构(头 + body 双通道均含payment_code),
再切生产密钥实测 1 元真扣,通过后回填此处实测结论。未实测前不得对外宣称「已通」。
Agent 侧调用规范(含付费前置插件检查)
Step 0 付费前置插件检查(必须,缺失则不得发起付费调用)
- 检测当前环境中
weixinpay_pay插件(微信支付 Agent Pay / AI 专属卡)是否已安装并已开通; - 若不存在或未开通:不调用
/api/invoke,改为提示用户先安装/开通微信 AI 支付,完成后再继续; - 若可用:继续 Step 1。
Step 1 调用统一网关:POST /api/invoke,请求体:
{
"skill": "buy-side-event-radar",
"skill_version": "1.0.0",
"query": "用户原始需求(用于订单留痕,不作为履约输入)",
"amount": 490
}
skill:必填,固定为本 Skill 的 slugbuy-side-event-radar(与 SkillHub 已发布的一致;透明网关下传错 slug 时错误延后到 SkillHub/微信预下单环节才返回);skill_version:必填,当前版本号1.0.0(缺失返回400 MISSING_SKILL_VERSION);amount:必填,单位分,服务端校验为大于 0 的整数(小数/布尔/零/负数一律400 INVALID_AMOUNT,不静默截断);
区间不强制,价格由 SkillHub 产品定价约束。
Step 2 支付触发(X402 预下单 → 402):未支付时服务端依次执行——
- 生成订单号
out_trade_no(402 响应头X-Out-Trade-No与响应体out_trade_no均会返回,Agent 须记下); - 调用微信支付 Native 下单,获取
code_url; - 用 SkillHub 开发者私钥(SHA256withRSA)对 X402 AI 预下单请求签名;
- 调用
POST https://payapp.weixin.qq.com/palmpayminiapp/clawagentpay/preorder换取payment_code; - 返回 HTTP 402,响应头
WeixinPay-Required与 bodyWeixinPay块中
同时携带 X402 预下单返回的payment_code(必须是 X402 的payment_code,
不能直接把微信code_url当作payment_code返回),并回显本单amount与out_trade_no。
⚠️ body 的WeixinPay嵌套结构最易遗漏:缺失时 weixinpay 插件从 body 解析不到
payment_code,会报「当前支付订单已过期」,该报错常被误判为「返回了 code_url」。
Step 3 用户支付授权:Agent 将 WeixinPay-Required 头(或 body WeixinPay 块)中的
payment_code 作为 paymentCode 交给 weixinpay_pay 插件,向用户申请支付授权。
Step 4 二次调用鉴权:用户完成支付后,Agent 再次调用 POST /api/invoke
(请求体同 Step 1,带请求头 X-Out-Trade-No: <402 返回的订单号>);
服务端按订单号主动向微信查单验证支付成功(不依赖回调到达)后返回:
{"ok": true, "paid": true, "fulfillment": "agent_local",
"skill": "buy-side-event-radar", "out_trade_no": "...", "already_fulfilled": false}
Step 5 本地履约(本 Skill 的关键差异):Agent 收到 paid: true 且
fulfillment: "agent_local" 后,在本机执行 scripts/ 下的脚本产出结果
(见 scripts/README.md),再把结果交付给用户。
支付未确认前,不执行本地取数脚本、不输出任何付费内容
(未支付重试返回 402 {"code":"NOT_PAID"})。
> 幂等说明:already_fulfilled: true 表示同一订单此前已鉴权通过;
> 此时直接复用上次已产出的结果,不要重复跑取数脚本(避免重复消耗外部接口配额)。
异常处理说明(Agent 与服务端两侧)
| 异常场景 | 处理方式 |
|---|---|
weixinpay_pay 插件不可用 |
不发起付费调用,引导用户安装/开通微信 AI 支付后重试 |
| 用户拒绝支付 / 支付取消 | 如实告知用户支付未完成,不推进后续流程、不输出付费内容;可重新发起(服务端生成新订单) |
| 支付失败(余额不足/风控拦截) | 如实转达失败原因,引导稍后重试;失败订单作废,不据此履约 |
payment_code 过期(最长 15 分钟) |
提示订单已过期,Agent 重新调用获取新订单与新 payment_code,不得复用旧码 |
| 报错「当前支付订单已过期」 | 先查 402 响应体是否有 WeixinPay 嵌套结构,其次才是 code_url 方向 |
| 支付成功但二次调用仍 402(回调延迟) | 等待 3~5 秒后重试,最多 3 次(指数退避),携带 X-Out-Trade-No、订单号不变 |
| 网络异常 / 5xx | 指数退避重试(1s/2s/4s,上限 3 次);持续失败告知服务暂不可用 |
| 本地取数脚本失败(数据源不可用/文件缺失) | 如实告知用户并说明原因,不得因为已付费而编造数据;可引导稍后重试同一订单(already_fulfilled 为 false 时不会重复扣费) |
| 金额校验失败(400 INVALID_AMOUNT) | 修正 amount 为大于 0 的整数分后重试 |
| skill 传错 / 未发布(错误延后到 X402/微信预下单环节) | 核对 skill/skill_version 与 SkillHub 已发布条目一致后重试,不得随便换 slug |
| skill_version 缺失(400 MISSING_SKILL_VERSION) | 补上当前版本号 1.0.0 后重试 |
| 未支付即重试(402 NOT_PAID) | 等待用户完成支付授权后按 Step 4 重试,不得跳过支付环节 |
| 退款 | 服务端经 /api/refund/notify 接收回调;已退款订单的 payment_code 失效,再次调用将重新走支付流程 |
> 核心原则(SkillHub 官方教程 FAQ):支付失败/未确认时必须如实告知用户,绝不据此推进后续流程。
核心特征对照表(供审核查验)
| # | 核心特征 | 实现位置 |
|---|---|---|
| 1 | X402 AI 预下单换取 payment_code(开发者私钥 SHA256withRSA 签名,调官方 preorder 接口;WeixinPay-Required 返回 payment_code 而非微信 code_url) |
pay/server.py skillpay_x402_preorder();链路 Step 2.3~2.5 |
| 2 | 支付触发(未支付返回 402 + WeixinPay-Required 头/体双通道) |
pay/server.py _handle_invoke();链路 Step 2.5 |
| 3 | 订单号传递(out_trade_no 全链路关联:下单→预下单→回调置位→X-Out-Trade-No 重试→二次调用) |
pay/server.py generate_trade_no() / mark_paid / 402 响应 X-Out-Trade-No 头 |
| 4 | 重试机制(402 回调延迟重试带 X-Out-Trade-No、5xx 指数退避、订单过期重新下单) |
上表「异常处理说明」 |
| 5 | 付费前置插件检查(weixinpay_pay 可用性检测,缺失不发起付费调用) |
链路 Step 0 |
| 6 | 异常处理说明(支付失败/取消/过期/退款/本地脚本失败等全场景) | 上表「异常处理说明」 |
| 7 | 透明网关(skill/skill_version 仅做格式校验后透传,不查 SkillHub、不查注册表) |
pay/server.py resolve_skill()(无 SKILL_REGISTRY,免 Java 注册/重启) |
包内 pay/server.py 为 Python 参考实现(含 APIv3 签名、X402 预下单、回调验签解密、
主动查单、幂等鉴权、透明网关无需注册表),部署说明见 PAY_SKILL_UPGRADE.md 与 pay_skill.yaml。
注意:本 Skill 涉及两套独立密钥/证书——
- 微信支付 API 证书(
wechat_pay):用于微信 Native 下单与主动查单; - SkillHub 开发者密钥(
skillhub):用于 X402 预下单签名。
私钥均不得写入 Skill 包或仓库,须通过环境变量注入服务端。