Maintain a dynamic A-share pool (≤30 names) with quantitative scoring, technical timing, and scheduled push alerts.
Coding
Privora · A股/港股/黄金/基金 多资产 量化分析 · 量化回测 · 模拟盘 · 实时告警 · 风险监控 · Python 策略 · AI Agent
Privora · AI Agent 投资工作流平台 — Bearer Token 即接入 /agent/skills/execute 通用 dispatcher,覆盖 A 股/港股/美股/黄金/基金/财报数据 + Python 回测(含 sandbox)+ 模拟交易 + 组合归因(α/β TWR)+ 云端告警 + 流程编排。Hermes / Claude / GPT / OpenClaw 全兼容。
What it does
Privora · AI Agent 投资工作流平台 — Bearer Token 即接入 /agent/skills/execute 通用 dispatcher,覆盖 A 股/港股/美股/黄金/基金/财报数据 + Python 回测(含 sandbox)+ 模拟交易 + 组合归因(α/β TWR)+ 云端告警 + 流程编排。Hermes / Claude / GPT / OpenClaw 全兼容。
The skill document
Privora · AI Agent 投资工作流平台(Bearer Token 即接入 · A股/港股/美股/黄金/基金 数据 + 回测 + 模拟交易 + 告警 + 流程编排)
给你的 AI Agent 一个统一的投资研究工作流后端 —— 数据查询 + 策略回测 + 组合归因 + 云端告警 + 流程编排一个 Token 全覆盖。
Hermes / Claude / GPT / OpenClaw 任何 Agent,通过一个 Bearer Token 即可访问:
- 📊 多资产数据(按市场段分别发布,均 🟢 生产可用):日线 A 股 5500+ 股票(
stock_day,含沪深300 / 上证综指 / 中证A500 / 深证成指 4 主要指数)+ 港股(stock_day_hk,如00700.HK)+ 美股(stock_day_us,如AAPL);分钟 K 线 A 股(stock_kline)+ 港股(stock_kline_hk),1/5/15/30/60 分钟;持仓、黄金、基金、财报事件(业绩预告 / 快报)——一个 API 全覆盖,详见下方「数据资产可用性」表。 - 🔔 7×24 云端监控:Serverless 策略托管,飞书 / 微信毫秒级预警,零服务器运维
- 🧪 Python 策略回测:用同一份平台数据跑回测,输出 Sharpe / 最大回撤 / 交易明细
- 🔒 加密静态、认证边界返明文:持仓数据在数据库中以 per-account 独立密钥密文存储(防 DB 层泄露 + 平台 admin 跨账户读取);持有你 Bearer Token 的 Agent 通过 API 认证后,平台按调用者身份解密并返回明文 —— 这不是 E2E 加密,Token 授权即数据访问权。
- 🎯 1-click subscribe→alert:Agent 帮用户从"订阅 dashboard"到"配置 alert 上线"降到 1 step (2026-06-05 新增)
- 🧾 模拟交易 (Paper Trading):MARKET / LIMIT 委托类型 + 调度器驱动 + 真实涨跌停 / 停牌信号,账户 + 订单 DB-level 幂等。
让普通人也能拥有私募级别的工作流——不需要私募的预算,就能像私募研究员一样在同一条流水线里跑数据 + 分析 + Agent + 告警。
🆕 最新版本 v1.0.45(2026-07-16)· lg_agent_exec.sh 支持命名参数扁平调用(key=value / key:=jsonvalue),不用再手拼 envelope JSON;旧 envelope 形式 100% 继续可用。历史版本变更见文末 §最近更新。
🎯 最适合:想把整个投研工作流(数据查询 + 回测 + 模拟交易 + 告警 + 流程编排)交给 AI Agent 自动化的散户 / 小工作室;把 Hermes / Claude / GPT / OpenClaw 当量化助手用的开发者。注意:Bearer Token 是"工作流授权凭证",不只是"数据 API key" —— 授予前先按 §Scope 分类明白要给 Agent 哪些能力。
🌐 产品主页:https://privora.cn · 注册即拿 Token
演示
🌟 核心亮点
1. 🤖 兼容所有主流通用 AI Agent
打破生态壁垒,本技能不仅专供某一平台,而是完美兼容 Hermes、OpenClaw、Claude Code、GitHub Copilot 等所有支持外挂工具/技能的通用大模型 Agent。只需简单配置环境变量,您的通用 AI 助手瞬间化身专业量化分析师。
2. 🔒 加密静态 · 认证边界返明文(Encryption-at-rest, not E2E)
每个账户的持仓数据在数据库中以 per-account 独立密钥密文存储。这是防"库泄露 / 平台 admin 跨账户读取"的加密,不是 E2E 加密:
- 持有你 Bearer Token 的 Agent 通过 API 认证后,平台按调用者身份解密并返回明文 —— Token 是解密权的钥匙,保管好 Token 就是保管加密防线
- 每个账户的加密密钥独立,平台管理员账号无法跨账户读取持仓明细(DB 层保证)
- 订阅他人发布资产时,发布方看不到你的查询内容或账户信息(widget config 对订阅方 sanitize)
- 给不可信 Agent 的 Token = 给它明文数据。按 §Scope 授予最小 scope,不要 bundle 无关能力
3. ⚡ Serverless 极速预警与零部署
策略云端托管运行,无需您购买第三方行情 API,无需自建服务器维护 Cron 任务,无 Token 消耗税。策略触发后,毫秒级推送到您的飞书机器人或微信 Webhook。
🛠️ 能做什么
| 核心功能 | 详细说明 |
|---|---|
| 资产盈亏巡航 | 一键查询持仓明细、当日盈亏、历史收益率,数据由 privora.cn 闭环处理。 |
| 云端自动盯盘 | 设置预警条件(突破均线、涨跌幅、换手率等),触发即通知,7x24小时云端值守。 |
| 多终端实时推送 | 策略触发毫秒级推送到飞书、微信 Webhook,不错过任何交易信号。 |
| 行情数据 | 日线按市场段分别发布,均 🟢 生产可用:A 股(stock_day,沪深京 5500+ 股票 + 4 指数)、港股(stock_day_hk,如 00700.HK)、美股(stock_day_us,如 AAPL);分钟 K 线:A 股(stock_kline)+ 港股(stock_kline_hk),1/5/15/30/60 分钟;基金日 NAV(fund_day);SGE 黄金日线(metal_day);财报事件(stock_forecast 业绩预告 + stock_express 业绩快报,11 年历史已回填)。详见下方「数据资产可用性」表。 |
| Python 策略回测 ✨ | 用平台日线数据跑单股 / 多股组合回测,输出 Sharpe / 最大回撤 / 交易明细 / equity curve;结果持久化到 process_backtest_result,可通过 investment.stock.backtest.list 检索历史审计记录(平台已积累 44+ 次持久化回测)。 |
| 模拟交易 (Paper Trading) ✨ | MARKET / LIMIT 两种委托类型,调度器驱动,模拟完整委托 → 成交 → 盈亏核算链路;账户按 user_name 唯一(DB-level UNIQUE),订单按 (user_name, client_order_id) 幂等,Agent 重复调用不重建。适合策略 6 阶段验证的最终纸面交易关卡。 |
| 用户声音收集 | 支持 Agent 代客户提交 Bug 和需求,无缝对接后台反馈系统。 |
数据资产可用性(2026-07-17 platform check)
发布模型说明:底层物理表按市场是合表存储的(同一张表可能物理上含多市场行),但对外发布是按市场段分别发布为独立 DataAsset 的。
stock_day段族现已全市场覆盖并各自独立上线:A 股段 =stock_day,港股段 =stock_day_hk,美股段 =stock_day_us;分钟 K 线段族同理:A 股段 =stock_kline,港股段 =stock_kline_hk。三段各自独立发布、独立 asset id,调用时请用下表的 assetName,不要假设同一 asset 覆盖多市场。
| DataAsset | 状态 | 覆盖 | 频率 | 备注 |
|---|---|---|---|---|
stock_day | 🟢 生产可用 | A 股(沪深京)5500+ 股票日线 + 4 主要指数(沪深300 1B0300 / 上证综指 1A0001 / 中证A500 1B0510 / 深证成指 399001) | 日 | id=1;000001 等 A 股 ticker 自动路由(segmentValues SH/SZ/BJ);399001 自 2026-03-17 起停更,请求会返回 meta.benchmarkWarning |
stock_day_hk | 🟢 生产可用 | 港股日线(如 00700.HK) | 日 | id=204;数据新鲜(2026-07-16 校验通过) |
stock_day_us | 🟢 生产可用 | 美股日线(如 AAPL) | 日 | id=206;由 stock_day_us_backfill_to_mc 任务从 PG 同步至 MC |
stock_kline | 🟢 生产可用 | A 股 1/5/15/30/60 分钟 K 线(interval_type 区分周期) | 分钟 | id=202;日线 + 日内同步,由 stock_kline_daily_sync 等调度维护 |
stock_kline_hk | 🟢 生产可用 | 港股 1/5/15/30/60 分钟 K 线 | 分钟 | id=207;与 stock_kline 同结构,段独立 |
stock_minutes | ⚪ 已弃用 | (旧) 分钟 K 线,已被 stock_kline / stock_kline_hk 取代 | — | id=154;仅历史兼容保留,新集成请改用 stock_kline/stock_kline_hk |
fund_day | 🟢 生产可用 | 公募基金日 NAV | 日 (T+1) | 数据延迟约 1 个工作日 |
metal_day | 🟢 生产可用 | SGE 黄金 / 白银日线 | 日 | 上海黄金交易所 |
stock_forecast | 🟢 生产可用 (NEW 2026-06-22) | A 股上市公司业绩预告;11 年历史 82,457 行已回填 | 日 | 财报季 (1/4/7/10 月底前后) 集中发布 |
stock_express | 🟢 生产可用 (NEW 2026-06-22) | A 股上市公司业绩快报;11 年历史 19,945 行已回填 | 日 | 比业绩预告更精确但发布更稀疏 |
stock_dividend | 🟢 生产可用 (NEW v1.0.32) | A 股上市公司现金分红事件;进入 portfolio.attribution 归因 | 事件驱动 | 除权除息日发布 |
对 Agent 的指导:调用 dataasset.list 看完整列表;标 🔴 / ⚫ / ⚪ 的资产请避免在策略里硬编码依赖(⚪ = 已弃用,改用其后继 asset)。dataasset.metadata.get (2026-06-22 新上) 可查每张表的 lastUpdated / expectedUpdateCadence / cronExpression 来判断当前状态。
📌 本节是 2026-07-17 的一次平台盘点快照,随时间推移可能与实际覆盖漂移。各已发布资产的完整覆盖范围、分市场明细、更新频率与数据起始日期,见持续维护的公开清单页:privora.cn/features/realtime-minute-data-coverage(按六类分组,含 A股/港股/美股/北交所分市场明细)。
🛡️ Scope 与操作者责任
本 skill 是通过 Bearer Token 对接 Privora 平台的能力。操作类别的副作用不同,操作者负责按类别 scope token 并为需要的类别加入确认门槛:
- 只读(Read-only)—— 数据 API、回测结果查询、流程/调度/数据源/仪表盘/市场的 list/get。平台状态零副作用。
- 幂等写(Idempotent write)—— 模拟交易下单(DB 层 UNIQUE on
user_name+client_order_id,同 key 重试返回同一记录)、marketplace subscribe(ON CONFLICT 返回已有订阅)、告警配置更新。同输入多次调用只产生一次逻辑效果,可安全重试。 - 流程状态转移(Workflow state transition)——
process.ingestion.execute触发已授权 python_script 运行并写入process_backtest_result表;scheduler-instance 的redo / hold / resume / reset-priority转移 trigger row 状态。每次调用创建或修改持久化记录。 - 外发 webhook(Outbound webhook)——
schedule.job.plugin.webhook.trigger与告警评估路径向操作者配置的外部端点(飞书 / 微信 / 通用 webhook)发送通知。副作用在 Privora 之外,平台不可撤销。
本 skill 不暴露(需要人在 platform UI 手动完成):
- 持久化记录的删除 / 撤销 / reset 操作
- 调度器 online / offline 状态转移
- Webhook 插件生命周期变更(删除 / 禁用)
- 管理员级账户操作
本 skill 不预先声明任何操作是"agent-safe" —— 这个分类取决于操作者的风险偏好、agent 的可靠性、以及具体用例。推荐姿势:只读 + 幂等写允许 agent 自主调用,流程状态转移和外发 webhook 必须先经过用户确认门槛。
📋 场景 → scope 速查表
新建 token 的默认 scope 就能取数(2026-08-03 起)。点"创建"不改任何选项,你会得到
read-data 这一组:
dataasset.list dataasset.get dataasset.schema.get
dataasset.data.get dataasset.data.getRealtime marketplace.item.list
需要别的能力时,按场景挑一组(token 创建页有同名的场景按钮,点一下即可全选):
| 场景 | preset id | scopes |
|---|---|---|
| 取行情 / 资产数据(默认) | read-data | dataasset.list dataasset.get dataasset.schema.get dataasset.data.get dataasset.data.getRealtime marketplace.item.list |
| 读仪表板 | read-dashboard | read-data 全部 + dashboard.list dashboard.get dashboard.data.get |
| 触发并追踪流程 | run-process | process.ingestion.list process.ingestion.get process.component.list process.ingestion.execute process.ingestion.execute.log.get |
| 配置指标告警 | manage-alerts | metric.alert.list metric.alert.get metric.alert.create metric.alert.update metric.alert.toggle metric.alert.test |
| 读写持仓与交易 | portfolio | investment.{stock,fund,gold}.portfolio.* + .trading.*(含写权限) |
三个查询入口(三处读的是同一份定义,不会互相打架):
| 你是谁 | 去哪查 |
|---|---|
| 人 | privora.cn/profile/tokens 创建 token 时的场景按钮 |
| Agent | GET /agent/scope-presets —— 返回 {presets[], defaultScopes[], grantedScopes[]},每个 preset 带 scopes[]、skillIds[] 和 satisfied(当前 token 是否已满足) |
| Agent | GET /agent/skills —— 全量技能目录。每条带 granted(你现在能不能跑)、scope(需要哪个 scope)、params schema、exampleInvocation。跑不了的条目额外带 presetsGrantingScope |
GET /agent/skills过去只返回你已有 scope 的技能,所以 scope 不足时你根本看不到目标技能存在, 只能靠猜 skillId。现在默认返回全量并用granted标注;要恢复旧行为传?granted=true。
scope 不足时不用猜:403 响应体直接给出 requiredScope、你当前的 grantedScopes、
哪个 preset 含它(presetsGrantingScope)以及去哪改(remediationUrl)。
skillId 写错时 400 响应体给 didYouMean[] 候选。
Token 使用建议:
- 在 privora.cn/profile/tokens 创建专用 Bearer Token
- 最小 scope 原则 —— 只授予当前 use case 需要的 scope。只读分析用默认的
read-data就够; 要跑流程再加run-process;agent 真的要下模拟单才加paper.*(该命名空间由平台内部签发, 见下方"模拟交易"章节)。不要为"以防万一"打包无关 scope。 - 明确设置
LG_AGENT_BASE_URL=https://privora.cn - Token 泄露立即 rotate —— Token Management 页面列出所有活跃 token 及最后使用时间戳和 revoke 按钮
🛑 绝对不要让你的 agent 代替你 mint token。Token 创建是 operator 动作,不是 agent 动作。Agent 应该消费 operator 签发的 Bearer Token,不应该自己调
POST /api/subscription/tokens。
📑 输出仅供分析参考,不构成投资建议
本 skill 的输出(行情数据 / 组合分析 / 回测报告 / 模拟交易 / 告警评估)是供操作者审查的分析结果,不是投资建议、不是交易指令、也不能替代持牌财务咨询。
- 把结果作为你自己决策过程的输入 —— 使用前请自行验证数据新鲜度、假设、边界情况
- 实盘交易和不可逆的财务决策不应放在 agent 自动执行链路里 —— 模拟交易只是模拟;真钱交易必须走由操作者控制的券商链路并显式确认
- 回测反映的是历史条件 —— 过去表现不预测未来结果。使用前请确认数据窗口、策略逻辑、以及生存偏差 / look-ahead 假设
- 无监管咨询声明 —— 本平台是数据基础设施;下游任何投资决策由操作者本人(你)负责
🚀 快速接入 (Quick Start)
0) ⚡ 30 秒试一下(不需要注册 / 不需要 Token)
装完 skill 想立刻看看能干什么?打开 privora.cn/marketplace:
- 无需登录,直接浏览公开挂牌的 A 股 / 港股 / 美股 / 黄金 / 基金 / 财报事件等数据资产
- 想一眼看完全部已发布资产的覆盖范围 / 更新频率 / 数据起始日期,不用一个个点开?看公开清单页 privora.cn/features/realtime-minute-data-coverage
- 每个资产可以点进去看 25 行样本数据 + 20 字段元信息(
lastUpdated/ 数据源 / cron 表达式等) - 看到有价值的资产?记下 numeric asset id → 回到终端跑下面的 §4 First Call Recipe(3 步 / 约 2 分钟)立刻验证 Bearer Token 对同一资产能跑通 —— 无需额外配置,安装 skill 时的环境变量对同一资产完全生效
- 觉得样本还不够?往下走 §1 - §4 注册生成 Bearer Token 拿完整访问权(分页 / 过滤 / 更高 rate limit / 写操作 / Agent 集成)
为什么先看再注册:Privora 是投研工作流平台,"你的数据是否值得订阅"应该 30 秒能判断 —— 不需要注册墙。marketplace UI 是发现工具,Bearer Token 是同一批数据的程序化访问入口,两者对应关系明确。
1) 获取您的专属 Token
- 注册并登录 privora.cn
- 在侧边栏点击你的用户名 → API Token Management,或直接访问
https://privora.cn/profile/tokens - 创建一个仅包含所需 scopes 的专用 Token(建议先用只读或低权限 Token)
- 复制您的专属
LG_AGENT_TOKEN
2) 为您的 Agent 配置环境变量
在您使用的 Agent 终端(如 Hermes、Claude Code、GitHub Copilot 或 OpenClaw)中注入以下环境变量:
export LG_AGENT_BASE_URL="https://privora.cn"
export LG_AGENT_TOKEN="***"
公开版主要走以上 Bearer Token 方式;如果 Agent 只是浏览 marketplace / 预览已发布看板 & 资产,也可以走匿名模式(不需要 token,见下方 §🌐 匿名预览)。session cookie / CSRF 兼容调用不支持。
3) 唤醒 Agent,开始对话
现在,您可以直接用自然语言向您的 Agent 下达指令了!
4) ⚠️ 做出你的第一次成功 API 调用(3 步走 / 避免最常见的 500)
最容易踩的坑:URL 里的 {id} 必须是数字型 asset ID(如 42),不是 asset 名字(如 fund_day / stock_day)。传成名字后端 Spring 转 Long 失败会返回 500——错误信息不会明确告诉你原因。
正确的 3 步 recipe:
# Step 1: 先 list 拿数字 id ← 别跳过这步
curl -H "Authorization: Bearer $LG_AGENT_TOKEN" \
https://privora.cn/api/data-assets | jq '.data[] | {id, assetName}'
# 输出示例:
# {"id": 42, "assetName": "fund_day"}
# {"id": 8, "assetName": "stock_day"}
# {"id": 15, "assetName": "stock_dividend"}
# Step 2: 用数字 id (不是 assetName!) 查元数据
curl -H "Authorization: Bearer $LG_AGENT_TOKEN" \
https://privora.cn/api/data-assets/42/metadata
# Step 3: 用数字 id 查实际数据
curl -H "Authorization: Bearer $LG_AGENT_TOKEN" \
"https://privora.cn/api/data-assets/42/data?page=1&size=10"
Agent 侧用 lg_agent_exec.sh 调用同理(v1.0.45 起支持命名参数扁平写法,不用手拼 JSON):
scripts/lg_agent_exec.sh dataasset.list
scripts/lg_agent_exec.sh dataasset.metadata.get id=42
scripts/lg_agent_exec.sh dataasset.data.get id=42 filter_column=stock_num filter_value=600519
id 必须是数字(先 dataasset.list 拿到再传,不是资产名字如 fund_day)。想看某个 skill 接受哪些 key,先 scripts/lg_agent_list.sh describe dataasset.data.get 看 schema + 示例,再照着填。
如果你已经踩到 500:不用改代码逻辑,只需把 {name} 换成对应的数字 id 即可。数据资产的可用列表见下方「数据资产可用性」表 —— 那里的名字对应 dataasset.list 返回的 assetName 字段,需要先 list 拿到本 team 里对应的数字 id。
🌐 匿名预览(无 token)
如果 Agent 只是想浏览 marketplace 或预览已发布的看板/数据资产/流程——比如帮用户看看 Privora 有什么数据源、有哪些现成看板可订阅、某个流程做什么用——不需要 Bearer Token 也能直接跑。这条通路和 privora.cn/marketplace 页面上未登录访客看到的内容是同一套数据,只是把它变成 machine-readable 的 skill 调用。
什么时候用
- 用户还没注册,Agent 想先展示"这平台上有啥"
- 用户已注册但当前 session 没配 token,你想让 Agent 先给个 marketplace 摘要
- Agent 在做 discovery / recommendation,不需要写权限、也不涉及用户私有数据
怎么用
留空 LG_AGENT_TOKEN 或直接不传 Authorization header 即可:
# 无 token 调用 —— 直接返回 mode:"anonymous" + 10 个可用 skill
curl https://privora.cn/agent/skills
# 无 token 拿 marketplace 列表
curl -X POST https://privora.cn/agent/skills/execute \
-H "Content-Type: application/json" \
-d '{"skillId":"marketplace.item.list"}'
# 无 token 拿某个已发布看板的 widget 数据
curl -X POST https://privora.cn/agent/skills/execute \
-H "Content-Type: application/json" \
-d '{"skillId":"dashboard.data.get","params":{"pathParams":{"id":""}}}'
响应体的 mode 字段会明确标 "anonymous",grantedScopes 列出下方 10 个允许的 skill。
匿名模式可用的 skill(全部只读)
| skillId | 用途 |
|---|---|
marketplace.item.list | 列出所有可订阅的 marketplace 条目(看板 / 资产 / 流程)—— discovery 入口 |
dashboard.get | 按 id 拿某个已发布看板的元数据 + widget 定义 |
dashboard.data.get | 一次拿某个已发布看板所有 widget 的数据 |
dataasset.get | 拿某个 allowSubscription=true 资产的详情 |
dataasset.schema.get | 拿该资产的列 schema |
dataasset.metadata.get | 拿该资产的富元数据(lastUpdated / expectedUpdateCadence / cron / 数据源描述等 20 字段) |
dataasset.data.get | 拿该资产的历史数据(预览有效范围内) |
dataasset.data.getRealtime | 拿该资产的实时镜像数据(若配置了 realtime mirror) |
process.ingestion.get | 拿某个 allowSubscription=true 流程的结构(不含 stepCfg 源码) |
process.component.list | 列平台可用的步骤组件类型(rendering diagram preview 用) |
硬性约束
-
只读白名单:仅上表 10 个 skill 可调,其余 skill(包括其它只读 GET,如
investment.stock.portfolio.list/dashboard.list/dataasset.list)无论是否存在都返回 403missing-scope。任何写操作(subscribe / create / update / delete)同样 403;哪怕手工构造匿名 PUT/POST 到底层/api/**,Node 代理层也会先 401 拦截,不会到 Spring。 -
每 IP 限流(三桶,任一超限即 429):
桶 范围 限额 429 响应体 通用桶 所有匿名 skill 60 / IP / 分钟 {"success":false, "message":"Too many anonymous agent requests, ..."}(无bucket字段)数据爆发桶 dataasset.data.get+dataasset.data.getRealtime10 / IP / 分钟 {"success":false, "traceId":"...", "message":"Anonymous data-fetch burst-limit exhausted (10/min per IP). ...", "bucket":"burst"}数据日总桶 同上 100 / IP / 天 {"success":false, "traceId":"...", "message":"Anonymous data-fetch daily budget exhausted (100/day per IP). ...", "bucket":"daily"}收到 429 时读
response.body.bucket判断:"burst"等 60 秒重试;"daily"今日不再放行该 skill,建议引导用户注册 Bearer Token;无bucket字段则是通用 60/min 桶命中。Rate-limit 存储: v1.0.37 起三桶都存 Redis sorted sets (
anonratelimit:{burst,daily,general}:),通过 Lua 原子脚本实现 sliding window。fleet 内所有 Node worker + 所有 host 共享一份 counter,反爬承诺真的成立。Redis 不可用时 fail-open:静默放行 + ERROR 日志event:"rate-limit-redis-fail",反爬承诺仅在 Redis 健康时有效(运维监控 fail-open 日志识别异常)。 -
preview token 服务端自动签:不用你手工去
/preview-token拿;Node 按 skill 类型选:dashboard 类(dashboard.get/dashboard.data.get)要求调用方在params.pathParams.id里传目标看板 id,Node 会用该 id 签 dashboardId-bound token;未传 id 或其它 skill 一律降级为standalonesentinel(等同 dataasset 类行为)。 -
无效 Bearer 不降级:如果传了
Authorization: Bearer,返回 401 而不会悄悄退回匿名模式给你部分数据。要匿名就别传 header。 -
无跨租户 leak:所有资产读都走
canReadAssetgate;只有allowSubscription=true的资产/看板/流程会被返回,其它一律 404。跟浏览器/marketplace未登录访客看到的是同一套子集。 -
Dashboard-scoped token 不能跨团枚举:dashboard-A(发布者 = team-A)签的 preview token 无法通过
dataasset.metadata.get读到 team-B 的资产元信息,哪怕 team-B 资产allowSubscription=true。仅standalonesentinel token 可读所有公开挂牌资产。
匿名模式下的能力受限(订阅后才解锁)
数据获取类 skill(dataasset.data.get / dataasset.data.getRealtime / dataasset.get / dataasset.metadata.get / process.ingestion.get)在匿名模式下服务端会自动应用以下约束,参数会被静默改写或剥离——不是 400,你的 curl 依然能正常拿到响应,但拿到的不是你请求的形状:
- 分页强制固定
page=1, size=25:传任何其他值都被服务端硬覆盖。响应pageSize=25, currentPage=1。想拿更多请订阅后用 Bearer Token 调。 - 过滤 / 排序参数被静默清空:
filterColumn / filterValue / filterOp / orderBy / orderDirection一律置null再进服务层。想按条件过滤请订阅后再来。 - 发布者身份字段被剥离(
dataasset.get):dataSource / realtimeDataSource / businessOwner / technicalOwner / teamName / jobCode / createdBy / createdDate / updatedBy / updatedDate一律返回null。Metadata map 中teamName / dataSource / jobCode / createdBy / createdDate / sourceDescription也被剥离。 process.ingestion.get的stepCfg被剥离:匿名调用者拿不到 process step 的源码 / SQL / Python 内容。totalElements是哨兵值0,不是真实总数:匿名调用不消耗后端COUNT(*)查询(防止 JDBC 池 DoS)。分页导航请以data.length为准。
配合分页固定 + rate limit,匿名调用者理论上每 IP 每天最多拿到 2,500 行数据(100 次 × 25 行)——真的想跑分析请注册。
匿名模式下常见的误用
- ❌ 不要基于匿名 preview 数据做投资决策 —— 25 行不是完整数据集,这只是"试读",不是"取样"。
- ❌ 不要用多 IP 池绕 rate limit —— 我们记录并封 IP 池行为,正确路径是注册 Bearer Token。
- ❌ 不要期望
totalElements反映真实行数 —— 匿名调用永远返回 0,这是设计意图,不是 bug。 - ❌ 不要在匿名模式下尝试
filterColumn=...—— 参数会被静默丢弃,返回的是无过滤的前 25 行,不是过滤后的结果。
技术契约锚点(review 用):匿名 skill 白名单 = Node
app.js的ANONYMOUS_SKILL_SCOPES常量;匿名 rate limit =canAnonymousAgentCall(60/min) +canAnonymousDataFetchCall(10/min burst + 100/day daily);preview + HMAC 验证 =docs/auth-flow-invariants.md§1 + §2.6 + §2.6.1;能力锁定实现与残留 test 缺口 =docs/plans/2026-07-07-anon-preview-dataasset-lockdown.md。
从匿名 → 注册的漏斗
匿名浏览完,如果用户想真正订阅一个看板 / 用私有数据 / 跑回测,需要注册并领 token:
- 引导用户去
https://privora.cn/register(marketplace.item.subscribe是 🟡 写操作,不在匿名 scope 里) - 或直接调
auth.user.registerskill(也在匿名 scope 之外 —— 需要一层 signup 意图确认,见 §用户注册 & 反馈)
💬 典型应用场景
场景 1:查询账户今日盈亏(个人数据,仅自己可见)
您: “帮我查下今天的账户盈亏情况。”
Agent(调用
dataasset.data.get): “为您同步 privora.cn 的最新分析结果: 💰 当日盈亏: +319 元 | 累计浮动: -19,135 元 📊 持仓明细:
- 中国核电:+2.06%
- 永和股份:-32.45%
- 中国联通:-16.25%”
场景 2:设定云端智能监控
您: “帮我监控贵州茅台,只要突破MA20均线就通知我。”
Agent(调用监控接口): “✅ 已在云端成功创建监控任务:
- 标的:贵州茅台 (SH600519)
- 条件:价格突破 MA20
- 通知:飞书/微信推送 任务将在 Serverless 云端静默运行,触发时您将立刻收到推送。”
场景 3:测试流程并抓取执行日志
# 触发执行(异步),记下返回的 executionId
# 自定义 CLI 参数直接当 flat key 传(key 以 - / -- 开头,与 process.ingestion.execute
# 的 Map body 逐字对应)。后端会自动注入 `-f ` —— 不用自己传 -f。
RESP=$(scripts/lg_agent_exec.sh process.ingestion.execute id=123 \
-start_date=20260419 -end_date=20260420 --env=dev)
EXEC_ID=$(echo "$RESP" | jq -r '.executionId')
# 轮询日志,直到 completed=true
OFFSET=0
while :; do
LOG=$(scripts/lg_agent_exec.sh process.ingestion.execute.log.get \
id=123 executionId="$EXEC_ID" offset="$OFFSET")
echo "$LOG" | jq -r '.logLines[]'
[ "$(echo "$LOG" | jq -r '.completed')" = "true" ] && break
OFFSET=$(echo "$LOG" | jq -r '.nextOffset')
sleep 1
done
echo "exitCode=$(echo "$LOG" | jq -r '.exitCode')"
返回:status 由 running 过渡到 completed 或 failed,exitCode 为脚本退出码,logLines 为增量日志行。
场景 4:策略回测(双均线跑茅台)
您: “用双均线(5日/20日)对茅台 SH600519 过去三年跑个回测”
在平台新建一个 python_script 流程节点,脚本如下(lg_utils 已预装):
💡
stock_day回测用现成的run_stock_day_backtest就好——它已经把列名大小写(STOCK_NUM/OPEN_PRICE/CLOSE_PRICE)和日期格式(day_id的YYYYMMDD)配好了,别再手动传price_columns={“open”:”open_price”,...}或 ISO 日期,那些是 2026-04-21 踩过的坑。
from lg_utils import get_variable
from lg_utils.backtest_examples.dual_ma import DualMA
from lg_utils.backtest_examples.stock_day import run_stock_day_backtest
result = run_stock_day_backtest(
strategy=DualMA(fast=5, slow=20),
stock_num=”600519”,
start=”20220101”,
end=”20241231”,
initial_cash=1_000_000,
commission_bps=3, slippage_bps=1,
benchmark_asset=”stock_day”, # 可选:跟某只指数/股票对比
benchmark_filter_column=”STOCK_NUM”,
benchmark_filter_value=”000001”,
)
print(result.summary())
result.export_to_context(“maotai_ma520”) # stdout 日志快照
result.persist(name=”maotai_ma520”) # 持久化到 process_backtest_result 表
组合回测(共享现金池、多标的同时跑):
from lg_utils.backtest_examples.stock_day import run_stock_day_portfolio_backtest
from lg_utils.backtest_examples.dual_ma import DualMA
result = run_stock_day_portfolio_backtest(
strategies={“600519”: DualMA(5, 20), “000001”: DualMA(10, 30)},
stock_nums=[“600519”, “000001”], # 决定 size='all' 结算先后
start=”20240101”, end=”20241231”,
initial_cash=1_000_000,
)
# result.metrics[“per_asset”] 给出每只股票的贡献度/回撤/交易数
任务日志里会出现:
=== Backtest Summary ===
asset : stock_day
period : 20220101 ~ 20241231 (bars=725)
total_return : 23.1500%
sharpe : 0.8412
max_drawdown : 18.2300%
num_trades : 14
win_rate : 57.1429%
__LG_BACKTEST_RESULT__:maotai_ma520:{"metrics":...,"trades":...}
完整 JSON(含 trades / equity_curve)会被下游节点或监控面板消费。
场景 5:一键 subscribe→alert deeplink (NEW v1.0.13)
您: "帮我配个告警,招商银行股价跌破 30 通知我。"
Agent 调用流程(之前 6 步深埋,2026-06-05 起 1 步):
# 1) Agent 帮用户订阅相关 dashboard
RESP=$(scripts/lg_agent_exec.sh marketplace.item.subscribe itemId=dashboard-china-merchants-bank-watch)
# 2) 从 response 拿到本租户的 cloned dashboard ID
DASH_ID=$(echo "$RESP" | jq -r '.clonedDashboardId')
# 3) 构造 1-click deeplink — Agent 把这个 URL 给用户
DEEPLINK="https://privora.cn/dashboards?selectId=${DASH_ID}&openAlerts=true"
echo "请打开此链接配置告警:${DEEPLINK}"
用户点链接进去,metric alert modal 自动打开——已经对准刚订阅的 dashboard,剩下用户填阈值 + 选 webhook 渠道 finalize 就完。user-in-the-loop 边界保留(敏感操作仍需用户在 web 上确认),但 5 步导航 + 选 dashboard + 翻 toolbar 找 "Alerts" button 这些都省了。
这是平台活跃用户反馈最集中的需求——以前的路径是:订阅 → 跳到 dashboard 列表 → 找到目标 dashboard → 打开 toolbar → 找 "Alerts" button → (第一次还要去 /datasources 配 webhook,回来再继续)→ 配置 → 保存。这次更新把这条路径压到 1 步。
场景 6:模拟交易(paper trading)—— 暂不可自助,走 Process Python 节点(#787)
您: "用模拟账户跑一笔 600519 的市价买单 100 股,看看现在能不能成交。"
这条路径目前不能靠通用 Agent + 本包 Bearer Token 一次调用走完。 本节曾给出一段示例,调用 paper.account.create / paper.order.place / paper.order.get 三个 id —— 均不存在于 catalog,跑起来只会拿到 400 Skill not found(#787)。而且光改 id 也走不通:paper.* 是保留 scope 命名空间——自己去 个人设置 → Token 管理 创建一个带 paper.account.read / paper.orders.write 的 PAT,后端会直接拒绝 400 RESERVED_SCOPE,不存在"自助签发"这条路。
真实能力叫 investment.paper.*(见下方「investment.paper.* — 模拟盘交易」小节,含真实 skillId investment.paper.account.get / investment.paper.orders.submit / investment.paper.orders.list / investment.paper.positions.list),但入口不是 scripts/lg_agent_exec.sh,而是一个 Process 里的 python_script 节点,节点里用 lg.paper.* SDK(lg.paper.get_account() / lg.paper.submit_order(...) / lg.paper.get_orders(...))发起调用。Process 起跑时,后端会给这个节点自动注入一个 scope 限定的短期 Bearer(paper.orders.write paper.account.read dataasset.read)——Agent 不需要、也不能自己去申请这个 token。
该怎么做:
- 市场已有现成模板
starter_paper_trade_strategy——marketplace.item.subscribe一键复制到你的 tenant,改写里面的lg.paper.submit_order(...)调用即可,不需要从零搭 Process。 - 若要从零建:用
process.create(kind: "run_python")建一个含模拟下单脚本的步骤,process.ingestion.execute跑起来——节点内的lg.paper.*调用由平台自动授权,不经过本包的 Bearer。 - 若确实需要在 Process 之外、从外部 Agent 直接调
investment.paper.*:只能由平台管理员按"策略绑定模拟账户"流程走 UI 手动铸一个 process-execution token 再转交给你的 Agent——这不是本包能自助完成的操作,不要承诺用户"改个 id 就行"。
支持涨跌停 / 停牌 / suspended-stocks 信号、scheduler-driven 撮合。适合的 use case:策略上真实交易前 12 个月 paper trade 验证(per 6 阶段量化研究流水线最终关卡)——但入口是 Process 编排,不是本包 Bearer 的直接调用。
技能列表
REST 技能(scripts/lg_agent_exec.sh 调用)
公开版 skill 覆盖 4 类操作,见 §🛡️ Scope & Operator Responsibility 完整的 read / idempotent-write / workflow-transition / outbound-webhook 分类。删除、撤销、系统级审批等破坏性/管理类操作不在本 skill 范围内,需通过 platform UI 或 admin 工具完成。 风险标记:🟢 low / 🟡 medium / 🔴 high。所有
GET技能默认对会话用户开放;写操作需显式授予 scope。
📦 Request shape (v1.0.45+): 命名参数扁平写法 —— 直接用
key=value传参,不用手拼 JSON:scripts/lg_agent_exec.sh dataasset.data.get id=42 filter_column=code filter_value=000135等价于旧 envelope 形式
{"skillId":"dataasset.data.get","params":{"pathParams":{"id":42},"query":{"filter_column":"code","filter_value":"000135"}}}——网关会按每个 skill 的 path 模板自动把 flat key 分类到pathParams/query/body。key=value一律当字符串(保留stock_num=000135这类前导零);数字/布尔/数组用key:=value(如qty:=100)。旧 envelope 形式 100% 继续可用,两种写法可以在同一次调用里混用(例:数组 body 用--json,path 参数用 flat key)。想看某个 skill 接受哪些 key,跑scripts/lg_agent_list.sh describe。完整规则 + 历史踩坑 + envelope 手工写法见文末 §高级 / 兼容性附录。
流程 (Process / Ingestion)
| skillId | method | 功能 | 风险 |
|---|---|---|---|
process.ingestion.list | GET | 列出所有流程 | 🟢 |
process.ingestion.get | GET | 根据 id 获取流程详情 | 🟢 |
process.ingestion.execute | POST | 异步触发流程执行(返回 executionId)。body 接收自定义 CLI 参数,如 {"-start_date":"20260419","--env":"dev"}。后端自动注入 -f ,不要自己传 -f。 | 🟡 |
process.ingestion.execute.log.get | GET | 按 executionId 拉取日志+状态,支持 offset 增量轮询。记录持久化在 process_execution 表 + 磁盘文件,重启不丢。 | 🟢 |
process.component.list | GET | 列出当前团队可用的步骤组件(含 Markdown 使用说明) | 🟢 |
process.pipeline.build | POST | 一次性创建完整 pipeline(节点+组件+边)。python_script 节点的 stepCfg 必须使用执行器字段名 "script"(不是 "pythonScript"),例:{"script":"import sys\nprint(sys.version)","requirements":"pandas"}。process.component.list 返回的 form-schema 中的显示名 pythonScript 是 UI 表单专用名,不等于执行器运行时 JSON key——混用会导致执行时报 "Python script is empty or NULL"(2026-07-10 incident,已在后端加翻译层向前兼容,但规范写法仍推荐用 script)。 | 🟡 |
process.create | POST | 业务字段封装层(POST /api/ingestions/create-simple),比 process.pipeline.build 更简单:不需要知道 node id / stepSeq / aftId/sStep/nStep/fStep 拓扑字段 / 画布坐标 / 执行器 stepCfg 信封——只填 {name, description?, steps:[{kind, label?, ...}]},后端自动组装成 process.pipeline.build 同款请求并复用同一条持久化路径。kind 是封闭枚举,只支持单链路顺序执行(不支持分支/for 循环/if 节点,那些场景仍用 process.pipeline.build)。详见下方 process.create 详情。 | 🟡 |
process.pipeline.update | PUT | 全量更新已有 pipeline(PUT /api/ingestions/{id},同形 BuildPipelineRequest)。nodes 省略=仅改名/描述,保留现有步骤;nodes=[] 显式清空;nodes=[...] 全量替换。每次 PUT 自动写一条 dacp_meta_proc_version,可 /versions/{n}/restore 回滚。legacy team_name IS NULL 的流程会直接 403,需先 backfill。想只改一个步骤的 label/conf/remark 而保留 DAG?用 process.pipeline.update_node PATCH,避免 aftId 等拓扑字段被默认值 "-1" 误清空。想只改流程名称/描述?用 process.pipeline.patch_meta。 | 🟡 |
process.pipeline.update_node | PATCH | 部分更新单个步骤(PATCH /api/processes/{procId}/steps/{stepId})。字段掩码语义:仅 stepLabel / stepConf / remark 三个安全字段可被更新;缺失字段、显式 null、以及空字符串 "" 都视为"跳过"(不清空)。严格拒绝:aftId / sStep / nStep / fStep(DAG 拓扑)出现在 body 即返回 HTTP 200 success:false, code:"TOPOLOGY_FIELD_REJECTED" —— 要改变 DAG 拓扑请用 PUT process.pipeline.update 全量替换所有节点。stepName / stepSeq / parentId 静默丢弃。要清空 stepLabel/stepConf/remark 字段也必须走 PUT 全量替换 —— PATCH 设计为"只增改、不清空"。此 skill 需要 process.pipeline.update_node scope(独立于 process.pipeline.update),现有 token 须重新签发方可使用。 | 🟢 |
process.pipeline.patch_meta | PATCH | 部分更新流程级别元数据(PATCH /api/ingestions/{id}/meta)。字段掩码语义:仅 procLabel / procDescr 两个安全字段可被更新;缺失字段、显式 null、以及空字符串 "" 都视为"跳过"(不清空)。严格拒绝:nodes(拓扑变更)/ procName(标识符)/ creater(归属)/ teamName 出现在 body 即返回 HTTP 200 success:false, code:"FIELD_NOT_PATCHABLE" —— 要改名称/DAG 结构请用 PUT process.pipeline.update。此 skill 需要 process.pipeline.patch_meta scope(独立于 process.pipeline.update),现有 token 须重新签发方可使用。 | 🟢 |
process.create 详情
路径:POST /api/ingestions/create-simple,scope process.create(独立于 process.pipeline.build,现有 token 须重新签发方可使用)。
为什么需要它:process.pipeline.build 要求调用方懂平台内部的 DAG 拓扑(node id、stepSeq、aftId/sStep/nStep/fStep 边字段、画布 x/y/width/height)和执行器 stepCfg JSON 信封格式。process.create 只暴露业务字段——一个有序、有类型的步骤列表;封装层在服务端补平台管道,不生成任何业务代码(SQL/Python/消息文本仍由调用方自己写)。
请求体:
{
"name": "fund_dividend_wrapper_test",
"description": "可选描述",
"steps": [
{ "kind": "run_sql", "label": "create tables", "sql": "CREATE TABLE IF NOT EXISTS ...", "dataSourceName": "pg_main" },
{ "kind": "run_python", "label": "fetch akshare", "script": "import akshare as ak\nprint(ak.fund_fh_em())", "pipRequirements": ["akshare"] },
{ "kind": "run_python", "label": "tushare enrich", "script": "import tushare as ts\n# ...", "pipRequirements": ["tushare"] },
{ "kind": "print_summary", "label": "done", "message": "fund_dividend ingest complete" }
]
}
kind 封闭枚举,映射到真实平台组件(已核实执行器 *StepMeta 字段名,不是猜的):
kind | 平台组件 | 必填业务字段 | 可选字段 | 组装出的 stepCfg 信封 |
|---|---|---|---|---|
run_sql | sql | sql、dataSourceName | — | {"sql":..,"dsName":..,"needSplit":"true"} |
run_python | python_script | script | pipRequirements(字符串数组,pip 包名) | {"script":..,"requirements":".."}(requirements 由 pipRequirements 换行 join;未提供则省略该 key)。注意 key 是 script 不是 pythonScript —— 同 process.pipeline.build 那条 2026-07-10 坑,封装层已按执行器真实字段名组装,调用方不会踩到。 |
print_summary | print | message | — | {"message":..} |
body 里没有 teamName / userName 字段——不是被忽略,是这个 DTO 上根本没有这个属性。租户归属 100% 走鉴权上下文(同 process.pipeline.build),payload 传了也不会被采纳。
拓扑组装(调用方不需要关心,仅供理解结果):第 i 步(1-based)node id = "_step",stepSeq="",画布自动横向布局(120×60,间距 220)。相邻两步之间只支持单链路顺序执行——step[i] 的 sStep 与 aftId 都指向 step[i+1] 的 stepSeq,nStep/fStep 保持 "-1"。这是 fail-fast 语义:任一步骤失败即中止整个 pipeline,不会静默跳到下一步。不支持分支 / for 循环 / if 节点 / 并行——那些场景请用 process.pipeline.build 或先用 process.create 建好线性骨架、再用 process.pipeline.update 全量替换加拓扑。
返回:与 process.pipeline.build 相同的信封 {success, data:{id,name,description,created,teamName}, message}。name 冲突返回 HTTP 409 {success:false, code:"PROCESS_NAME_EXISTS"};steps 缺失某个 kind 必填字段返回 HTTP 400 {success:false, code:"VALIDATION_FAILED", message:"..."}。
示例调用:
scripts/lg_agent_exec.sh process.create name=fund_dividend_wrapper_test --json '{"body":{
"description":"fund dividend ingest",
"steps":[
{"kind":"run_sql","label":"create tables","sql":"CREATE TABLE IF NOT EXISTS fund_dividend (...)","dataSourceName":"pg_main"},
{"kind":"run_python","label":"fetch akshare","script":"import akshare as ak\nprint(ak.fund_fh_em())","pipRequirements":["akshare"]},
{"kind":"run_python","label":"tushare enrich","script":"import tushare as ts\n# ...","pipRequirements":["tushare"]},
{"kind":"print_summary","label":"done","message":"fund_dividend ingest complete"}
]
}}'
调度 (Schedule)
| skillId | method | 功能 | 风险 |
|---|---|---|---|
schedule.job.list | GET | 列出调度作业 | 🟢 |
schedule.job.get | GET | 获取调度作业详情 | 🟢 |
schedule.workgroup.list | GET | 发现 当前平台注册的 workgroup / namespace(从已注册 broker 聚合),是 schedule.job.create 两个必填字段的唯一合法来源 | 🟢 |
schedule.scripts.get | GET | 发现 平台配置的 jobScript 默认模板({dp, sh, py}),给 schedule.job.create 的 jobScript 字段用 | 🟢 |
schedule.job.create | POST | 创建调度作业(POST /api/schedule/jobs)。新建后 state="0",上线操作需通过平台 UI 执行。 | 🟡 |
schedule.job.update | PUT | 全量替换作业配置(PUT /api/schedule/job/{jobId})。全部字段都会被覆盖——缺失字段会被写成 null,可能清空 cronExp 等关键字段。推荐用 schedule.job.patch 做部分更新;PUT 只在需要显式清空某字段时使用。state 字段静默丢弃。 | 🟡 |
schedule.job.patch | PATCH | 部分更新作业配置(PATCH /api/schedule/job/{jobId})。字段掩码语义:只有非 null 字段会被覆盖到已存在的行,缺失字段和显式 null 都视为"跳过"。要清空字段请用 PUT schedule.job.update。state / teamName 同样静默丢弃(与 PUT 一致)。此 skill 需要 schedule.job.patch scope(独立于 schedule.job.update),现有 token 须重新签发方可使用。 | 🟢 |
schedule.job.depends.list | GET | 列出作业依赖(按 jobCode)。每行带 dependGroup——同组 OR、组间 AND | 🟢 |
schedule.job.depends.save | POST | 全量替换作业依赖列表(旧的先删再写)。支持按 dependGroup 分组做 OR/AND 组合 | 🟡 |
schedule.job.plugins.list | GET | 列出作业绑定的插件(按 jobCode) | 🟢 |
schedule.job.plugins.save | POST | 全量替换作业插件列表(旧的先删再写) | 🟡 |
schedule.instance.list | GET | 列出作业实例(一次运行=一条 trigger 行);ops 操作所需的 jobTriggerId 都从这里拿 | 🟢 |
schedule.instance.status.get | GET | 按 (jobCode, batchNo) 查单条最新状态,用于轮询 | 🟢 |
schedule.instance.log.get | GET | 按 jobTriggerId 拉取执行日志 | 🟢 |
schedule.instance.redo | POST | 重跑失败/已完成实例(保留依赖链语义) | 🟡 |
schedule.instance.hold | POST | 暂停运行中的实例(不杀进程,可恢复) | 🟡 |
schedule.instance.resume | POST | 恢复之前 hold 住的实例 | 🟡 |
schedule.instance.reset_priority | POST | 调等待队列里实例的优先级(priority 1-9,越小越先跑) | 🟡 |
schedule.job.lineage | GET | 作业的上下游依赖图(includeAssets=true 时附带每个节点的输出资产) | 🟢 |
schedule.job.by_process | GET | 用 process 名反查 jobCode(拿到后才能调 ops skill) | 🟢 |
schedule.broker.list | GET | 列当前注册的 broker(排"无人认领 workgroup"类问题时用) | 🟢 |
schedule.broker.latency | GET | Broker 队列长度 + 消费速率 + 推算的等待延迟(诊断"上线但跑得慢"类问题) | 🟢 |
schedule.job.plugin.webhook.trigger | POST | 手动触发作业绑定的 webhook 插件 | 🟡 |
调度作业字段契约
外部 agent 在调 schedule.job.create 之前,先走一遍"发现"(这几个字段没有硬编码枚举,值取决于当前部署):
schedule.workgroup.list→ 拿到{workgroups, namespaces},从中各选一个赋给workgroup/namespace。传一个没人认领的 workgroup 不会报错,但没 broker 会去跑——这是最典型的"创建完成但永远不执行"陷阱。schedule.scripts.get→ 拿到{dp, sh, py},按jobType选对应字段赋给jobScript(dp作业用dp,python作业用py,shell作业用sh;空字符串表示该类型没有在这套部署上配好)。- 如需参考现有同类 job:
schedule.job.list+schedule.job.get挑一个已上线的作业 clone 一份。
schedule.job.create / schedule.job.update 的 body(DataflowJob 形):
| 字段 | 必填 | 说明 |
|---|---|---|
jobCode | 后端强制 | 团队内唯一业务编码。已存在时 create 幂等返回旧 jobId。 |
jobLabel | UI 强制 | 展示名 |
jobType | UI 强制 | 枚举:dp / datastash / python / shell |
workgroup | UI 强制 | 集群组名。合法值来自 schedule.workgroup.list,不要自己编 |
namespace | UI 强制 | 命名空间。合法值来自 schedule.workgroup.list |
jobScript | UI 强制 | 执行命令行。默认模板来自 schedule.scripts.get(按 jobType 取对应字段) |
batchType | UI 强制 | 枚举:monthly / daily / hourly / minutely / once / daemon |
cronExp | 条件 | Quartz 6 段式(秒起头),如 0 5 15 * * ? |
jobParam | 条件 | JSON 字符串 数组:"[{\"paramName\":\"-f\",\"paramVal\":\"my_proc\"}, ...]";jobType=dp 时后端按 paramName="-f" 自动回写 procName |
procName | 可选 | dp 作业通常交给后端从 jobParam 反推;其他 type 可显式传 |
runConstraint | 可选 | "1"=顺序执行(默认),"2"=并发执行 |
batchNo / batchOffset / batchStep | 可选 | 批次计算相关 |
jobPriority | 可选 | 1–9,数字越小越高(默认 5) |
redoNum | 可选 | 失败重试次数 |
lastdtOffset | 可选 | 最晚启动偏移(秒),0 为不宽限 |
maxElapsed | 可选 | 最长运行时间(秒) |
jobExtCfg | 可选 | ≤1024 字符的扩展配置 JSON |
tag | 可选 | 自由标签 |
jobDescr | 可选 | 描述 |
state | — | update 时静默丢弃,上下线状态变更需通过平台 UI 操作 |
| 服务端自动填充 | — | jobId(UUID)、state="0"、version=1、teamName / memberName / createUser(取自会话) |
schedule.job.depends.save 的 body(JSON 数组,全量替换):
[
{ "dependCode": "upstream_a", "dependType": "10", "dependGroup": "g1" },
{ "dependCode": "upstream_b", "dependType": "10", "dependGroup": "g1" },
{ "dependCode": "20260424", "dependType": "20",
"batchCalExp": "${batchNo?calDate(-1,'d','yyyyMMdd')}" }
]
上面这份表示 (upstream_a OR upstream_b) AND 时间依赖。
dependType="10"— 任务依赖,dependCode是另一个 jobCode(同团队内可见)dependType="20"— 时间/批次依赖,dependCode是时间字符串,batchCalExp是批次偏移表达式(${batchNo?calDate(...)})dependGroup(可选)——分组键:同组 OR、组间 AND。同一个非空dependGroup的多行任一满足即算该组满足;不同组(包括每一行dependGroup为空/不传,各自独立成组)之间要求全部满足——即退化为原来的全 AND 语义。合法格式^[A-Za-z0-9_-]{1,32}$;空白会被规范化为null。任何一行格式不合法,整次保存都会失败({success:false, message}),且不会删除任何已有依赖行——可以放心重试。- 其他字段:
procName、output、isDefault("1"标默认)都可选 dependId每次保存都由服务端重新生成(UUID16),不用自己传,也不要依赖它在两次保存之间保持不变
schedule.job.plugins.save 的 body(JSON 数组,全量替换):
[
{
"pluginCode": "webhook",
"state": "1",
"pluginCfg": "{\"webhookDsName\":\"feishu_ds\",\"dataSourceName\":\"feishu_ds\",\"triggerStates\":[\"1\",\"-2\"]}",
"isBlock": "0",
"isDefault": "1"
}
]
pluginCode+pluginCfg(JSON 字符串)为必填state为要监听的任务状态:"1"成功 /"-2"失败 /"2"结束 /"0"启动 /"-1"中止(dacp_dataflow_job_trigger.state的子集)- webhook 插件:
pluginCfg里必须带webhookDsName,否则返回{"success":false, "message":"Webhook plugin requires pluginCfg.webhookDsName"} jobPluginId服务端生成
典型的"从零到调度可跑"流程(外部 agent 视角):
schedule.workgroup.list+schedule.scripts.get→ 发现合法的workgroup/namespace/jobScriptschedule.job.create→ 拿到jobIdschedule.job.depends.save(至少一条依赖,否则上线后不会产生 instance)- (可选)
schedule.job.plugins.save→ 绑 webhook 等插件- 通过平台 UI 上线作业(state: 0 → 1)→ 让 broker 把它纳入触发域
作业运维决策手册
Ops 流程几乎总是先 schedule.instance.list(或 schedule.job.by_process→schedule.instance.list)拿到目标 jobTriggerId,再按下面这张表选动作:
| 场景 | 推荐 skill | 备注 |
|---|---|---|
| 失败了想重跑一次 | schedule.instance.redo | 保留依赖链;默认 opType="3",带依赖重跑 |
| 运行中但想先停住等数据就绪 | schedule.instance.hold | 不杀进程,可 schedule.instance.resume 恢复 |
| 等待太久想插队 | schedule.instance.reset_priority | 只对"在队列等待"的实例有效 |
| 查上下游会被哪些 job 影响 | schedule.job.lineage | 在平台 UI 操作前先看一下上下游影响 |
| 已知 process 名找对应 jobCode | schedule.job.by_process | 常用于从 Process 页面反向调 ops |
| 排查"作业没有 instance" | schedule.broker.list → 看 workgroup 有没有 broker;schedule.job.lineage → 看 depend 是否还卡着 | 第二常见的"不跑"陷阱 |
| 排查"在跑但很慢 / 积压" | schedule.broker.latency | 看 stalled / 队列长度;若是 broker 瓶颈就不是 job 的问题 |
| 想看这次跑得怎么样 | schedule.instance.status.get(单点)或 schedule.instance.log.get(看日志) | 轮询建议用 status.get,日志用 log.get |
数据源 & 数据资产 (Datasource / Data Asset)
| skillId | method | 功能 | 风险 |
|---|---|---|---|
datasource.list | GET | 列出数据源 | 🟢 |
datasource.get | GET | 获取数据源详情 | 🟢 |
datasource.list.active | GET | 列出活跃数据源 | 🟢 |
datasource.connection.test | POST | 测试数据源连接 | 🟡 |
datasource.update | PUT | 全量替换数据源(含连接配置 dsConf)。想只改描述或显示标签?用 datasource.patch,避免 dsConf/dsAuth 被覆盖。 | 🟡 |
datasource.patch | PATCH | 部分更新数据源元数据(PATCH /api/datasources/{dsId})。字段掩码语义:仅 dsDescr(描述)/ dsLabel(显示标签)两个安全字段可被更新;缺失字段、显式 null、以及空字符串 "" 都视为"跳过"(不清空)。严格拒绝:dsConf(更改连接目标会破坏运行中的 ETL)/ dsType(标识符)/ dsAuth / dsId / dsName / teamName 出现在 body 即返回 HTTP 200 success:false, code:"FIELD_NOT_PATCHABLE"。此 skill 需要 datasource.patch scope(独立于 datasource.update),现有 token 须重新签发方可使用。 | 🟢 |
dataasset.list | GET | 列出数据资产 | 🟢 |
dataasset.get | GET | 获取资产详情 | 🟢 |
dataasset.schema.get | GET | 获取资产 schema(列名/类型);支持 ?refresh=true 绕过缓存实时重新采集 | 🟢 |
dataasset.metadata.get | GET | 获取资产富元数据:20 个字段,包含 lastUpdated(最近刷新时间)、expectedUpdateCadence(调度批次类型,来自关联 Job)、cronExpression(cron 表达式)、sourceDescription(数据源描述)。Bug #50 后续,用于程序化判断资产新鲜度。 | 🟢 |
dataasset.data.get | GET | 查询资产数据(盈亏、行情等,全量历史);支持 filter_op 过滤运算符(见下方详情)。MC 数据源资产速度较慢(2-5s)但包含完整历史 | 🟢 |
dataasset.data.getRealtime | GET | 查询资产的 实时镜像数据源(PG 热窗口,最近 365 天);低延迟,适合仪表盘 / 实时 P&L。资产未配置 realtimeDataSource 时返回 {success:false, message:"This asset has no realtime mirror"},不抛异常。路径:GET /api/data-assets/{id}/data-realtime | 🟢 |
dataasset.history.field-as-of | GET | 点状时间(PIT)股票状态字段查询:is_st(ST/暂停挂牌)、market_board(板块)、delisted(退市)、industry(申万行业分类)。返回指定股票在某日期上的历史状态快照。依赖 PR-B ETL 完成首次回填后方可返回实际数据;回填未完成前返回 data:null。详见下方「dataasset.history.field-as-of」节。 | 🟢 |
dataasset.update | PUT | 全量替换数据资产元数据(PUT /api/data-assets/{id})。想只改 description/tags/allowSubscription?用 dataasset.patch PATCH,避免误改 sensitivityLevel 等不可改字段。 | 🟢 |
dataasset.patch | PATCH | 部分更新数据资产元数据(PATCH /api/data-assets/{id})。字段掩码语义:仅 description / tags / allowSubscription 三个安全字段可被更新;缺失字段、显式 null、以及空字符串 "" 都视为"跳过"。严格拒绝:sensitivityLevel(含别名 sensitivity_level / securityLevel / level)— 敏感级是 MONOTONIC,调整必须走专用 sensitivity-change 路径;assetName / assetType / tableName / teamName 等标识符也拒绝。allowSubscription=true 在 INTERNAL 资产上要求 tags 包含 permission_field:,否则返回 code:"PERMISSION_FIELD_REQUIRED"(INLINE 复刻 PUT 路径的 publish-validation guard)。此 skill 需要 dataasset.patch scope(独立于 dataasset.update),现有 token 须重新签发方可使用。 | 🟢 |
数据资产 API 详情
dataasset.schema.get — ?refresh 参数
路径:GET /api/data-assets/{id}/schema
| 参数 | 必填 | 默认 | 说明 |
|---|---|---|---|
refresh | 否 | false | false:返回注册时缓存的 schemaInfo JSON(快速,无 I/O)。true:绕过缓存,对底层表做实时列采集,结果持久化回 schemaInfo 并写 last_schema_sync_at。 |
refresh=true 时响应的 meta 字段会包含 lastSchemaSyncAt(ISO-8601 UTC 时间戳
Related skills
Access Chinese financial market data — A-shares, HK stocks, funds, indices, macro — via 200+ interfaces.
Run long-only backtests on daily stock OHLCV CSVs and get standardized performance metrics plus a trade log.
Access crypto and Taiwan stock market data, plus nine exchange trading APIs with mandatory user confirmation before any write action.
Get A-share, Hong Kong, and US stock market data via unified HTTP GET calls to FTShare-market-data endpoints.
A股投研体系 v5.0 - 散户级 Bloomberg. 七大新工具:(1) DCF 内在价值 - 巴菲特/段永平/林奇思想 (2) 板块轮动识别 (3) 卖出信号体系 - 5维 (4) 北极星监控 - 公告自动 (5) 实时盘中警报 (6) 财报自动解析 (7) 历史回测引擎. 含 v2.1 选股模型(5维10...