fin-pulse — finance news radar for the OpenAkita Brain
Use this skill whenever the user asks about finance headlines, daily
briefs, hot-topic keyword alerts, or scheduled IM pushes from the
fin-pulse plugin. The plugin exposes seven agent tools that let you
create ingest / daily_brief / hot_radar tasks, inspect their status,
paginate tasks, cancel a running job, read / write the plugin config,
and search the article index by keyword / source / days window.
1. Triggers
Call fin-pulse tools when the user says (or implies):
- 「帮我看下今天美股 / 美联储 / 财经的大事」 →
fin_pulse_search_news
- 「生成今天的早报 / 午报 / 晚报」→
fin_pulse_create(mode="daily_brief", session=...)
- 「把早报 / 雷达告警推到飞书 / 企微」→
fin_pulse_create(mode="hot_radar", ...)
targets=[{"channel":"feishu","chat_id":"..."}]
- 「关键词 X 有什么新闻」→
fin_pulse_search_news(q="X")
- 「抓一下 fin-pulse 的 8 个源」→
fin_pulse_create(mode="ingest")
- 「查一下任务 Y 跑完了吗」→
fin_pulse_status(task_id="Y")
- 「fin-pulse 最近都跑了哪些」→
fin_pulse_list
- 「把 radar_rules 改成 +美联储 +降息」→
fin_pulse_settings_set
- 「fin-pulse 当前是怎么配的」→
fin_pulse_settings_get
Do not call these tools when the user only wants general finance
commentary; prefer web search for commentary and fin-pulse only for
their plugin state.
2. Tool reference
fin_pulse_create
Creates + runs a task synchronously (returns when done). mode is
required and must be one of ingest / daily_brief / hot_radar.
Pass extra params either nested under params or flat — both work.
Canonical shapes:
{"mode": "ingest", "since_hours": 24}
{"mode": "daily_brief", "session": "morning", "since_hours": 12, "top_k": 20, "lang": "zh"}
{"mode": "hot_radar", "rules_text": "+美联储\n+降息\n!传闻",
"targets": [{"channel": "feishu", "chat_id": "oc_xxx"}],
"since_hours": 24, "cooldown_s": 600}
since_hours: int in [1, 72] for ingest / daily_brief,
[1, 168] for hot_radar — out of range values clamp silently.
top_k: int in [1, 60], defaults to 20.
session: morning / noon / evening. Reject anything else
instead of guessing.
min_score: float in [0, 10]. Optional.
The returned envelope always has ok: bool and either a typed
payload (task_id, digest, result) or an error / hint.
Never retry on invalid_mode / missing_rules — surface to the user.
fin_pulse_status(task_id) / fin_pulse_cancel(task_id)
status returns the full task row (params + progress +
error_kind if failed).
cancel is idempotent and safe to call twice.
fin_pulse_list
limit clamps to [1, 200] default 50. Filter by mode / status
as needed. Use it to confirm state before suggesting a fresh
ingest.
fin_pulse_settings_get / fin_pulse_settings_set
get returns a redacted map — any key containing api_key,
token, webhook, secret, or password is masked as ***.
Never surface the *** value to the user as real data.
set takes {"updates": {k: v}} where values are stringified on
store. Don't write large JSON blobs through this tool.
fin_pulse_search_news
The daily-driver search tool:
{"q": "美联储", "days": 1, "min_score": 6, "limit": 20}
{"source_id": "wallstreetcn", "days": 7, "sort": "score"}
q supports plain LIKE matching today; the +must / !exclude
DSL is evaluated by hot_radar, not by this search — don't
promise that syntax here.
days clamps to [1, 90].
- Returns
items sorted by time (default) or AI score
(sort=score). Each item has title, url, summary,
source_id, ai_score, fetched_at, published_at.
3. Response etiquette
- When a tool returns
ok=false, quote the error kind plus any
hint — don't invent explanations.
- When the tool returns no items, say so explicitly and suggest
the user either run
fin_pulse_create(mode="ingest") first or
widen the days window.
- Daily briefs come back with
digest.stats (total_selected,
source_breakdown). Surface the count so the user knows whether
the digest is meaningful.
- Every task_id follows
fp-<uuid>; include it in your reply so
the user can reference it later.
4. Cross-tool recipes
Recipe A — "What's moving the Fed today?"
fin_pulse_search_news(q="美联储", days=1, min_score=5, limit=10).
- If
items.length < 3, follow up with
fin_pulse_create(mode="ingest", since_hours=6) and retry.
- Summarize the top 5 in bullet points with source_id tags.
Recipe B — "Generate + push the morning brief to Feishu"
fin_pulse_create(mode="daily_brief", session="morning", since_hours=12, top_k=20, lang="zh") → get task_id + digest.
- Quote the resulting
digest.title and article count so the user
can confirm.
- If they want it on IM, say: "你可以在插件 Digests Tab 点Resend
选飞书 / 企微,或把
channel + chat_id 告诉我我再帮你补
发 hot_radar 任务推一次。" (Do not try to call
dispatch/send from the tool surface — the REST surface is the
right entry point and requires an explicit chat_id.)
Recipe C — "Turn on a radar rule"
fin_pulse_settings_set({"updates": {"radar_rules": "+美联储\n+降息\n!传闻"}}).
- Remind the user that radar runs only via a scheduled task
(
POST /schedules) or an explicit
fin_pulse_create(mode="hot_radar", ...) with targets.
5. Safety rails
- Never send
dispatch/send or hot_radar/run without an explicit
chat_id from the user — IM pushes are user-visible and spamming
them is a support incident.
- If
fin_pulse_settings_get reveals newsnow.mode=off, don't
pretend NewsNow data is present.
- Respect the redaction — if a user asks "what's my Feishu webhook",
reply that it's redacted at the tool surface and point them to
the plugin Settings tab.
1---2name: fin-pulse3description: Track finance headlines, daily market radar, and source-backed financial news through Fin Pulse.4---5
6# fin-pulse — finance news radar for the OpenAkita Brain
7
8Use this skill whenever the user asks about **finance headlines, daily
9briefs, hot-topic keyword alerts, or scheduled IM pushes** from the
10fin-pulse plugin. The plugin exposes seven agent tools that let you
11create ingest / daily_brief / hot_radar tasks, inspect their status,
12paginate tasks, cancel a running job, read / write the plugin config,
13and search the article index by keyword / source / `days` window.
14
15---
16
17## 1. Triggers
18
19Call fin-pulse tools when the user says (or implies):
20
21- 「帮我看下今天美股 / 美联储 / 财经的大事」 → `fin_pulse_search_news`
22- 「生成今天的早报 / 午报 / 晚报」→ `fin_pulse_create(mode="daily_brief", session=...)`
23- 「把早报 / 雷达告警推到飞书 / 企微」→ `fin_pulse_create(mode="hot_radar", ...)`
24 + `targets=[{"channel":"feishu","chat_id":"..."}]`
25- 「关键词 X 有什么新闻」→ `fin_pulse_search_news(q="X")`
26- 「抓一下 fin-pulse 的 8 个源」→ `fin_pulse_create(mode="ingest")`
27- 「查一下任务 Y 跑完了吗」→ `fin_pulse_status(task_id="Y")`
28- 「fin-pulse 最近都跑了哪些」→ `fin_pulse_list`
29- 「把 radar_rules 改成 +美联储 +降息」→ `fin_pulse_settings_set`
30- 「fin-pulse 当前是怎么配的」→ `fin_pulse_settings_get`
31
32Do **not** call these tools when the user only wants general finance
33commentary; prefer web search for commentary and fin-pulse only for
34*their* plugin state.
35
36---
37
38## 2. Tool reference
39
40### `fin_pulse_create`
41
42Creates + runs a task synchronously (returns when done). `mode` is
43required and must be one of `ingest` / `daily_brief` / `hot_radar`.
44Pass extra params either nested under `params` or flat — both work.
45
46Canonical shapes:
47
48```json
49{"mode": "ingest", "since_hours": 24}
50{"mode": "daily_brief", "session": "morning", "since_hours": 12, "top_k": 20, "lang": "zh"}
51{"mode": "hot_radar", "rules_text": "+美联储\n+降息\n!传闻",
52 "targets": [{"channel": "feishu", "chat_id": "oc_xxx"}],
53 "since_hours": 24, "cooldown_s": 600}
54```
55
56- `since_hours`: int in `[1, 72]` for ingest / daily_brief,
57 `[1, 168]` for hot_radar — out of range values clamp silently.
58- `top_k`: int in `[1, 60]`, defaults to 20.
59- `session`: `morning` / `noon` / `evening`. Reject anything else
60 instead of guessing.
61- `min_score`: float in `[0, 10]`. Optional.
62
63The returned envelope always has `ok: bool` and either a typed
64payload (`task_id`, `digest`, `result`) or an `error` / `hint`.
65Never retry on `invalid_mode` / `missing_rules` — surface to the user.
66
67### `fin_pulse_status(task_id)` / `fin_pulse_cancel(task_id)`
68
69- `status` returns the full task row (params + progress +
70 `error_kind` if failed).
71- `cancel` is idempotent and safe to call twice.
72
73### `fin_pulse_list`
74
75`limit` clamps to `[1, 200]` default 50. Filter by `mode` / `status`
76as needed. Use it to *confirm* state before suggesting a fresh
77ingest.
78
79### `fin_pulse_settings_get` / `fin_pulse_settings_set`
80
81`get` returns a **redacted** map — any key containing `api_key`,
82`token`, `webhook`, `secret`, or `password` is masked as `***`.
83Never surface the `***` value to the user as real data.
84
85`set` takes `{"updates": {k: v}}` where values are stringified on
86store. Don't write large JSON blobs through this tool.
87
88### `fin_pulse_search_news`
89
90The daily-driver search tool:
91
92```json
93{"q": "美联储", "days": 1, "min_score": 6, "limit": 20}
94{"source_id": "wallstreetcn", "days": 7, "sort": "score"}
95```
96
97- `q` supports plain LIKE matching today; the `+must` / `!exclude`
98 DSL is **evaluated by hot_radar, not by this search** — don't
99 promise that syntax here.
100- `days` clamps to `[1, 90]`.
101- Returns `items` sorted by time (default) or AI score
102 (`sort=score`). Each item has `title`, `url`, `summary`,
103 `source_id`, `ai_score`, `fetched_at`, `published_at`.
104
105---
106
107## 3. Response etiquette
108
109- When a tool returns `ok=false`, quote the `error` kind plus any
110 `hint` — don't invent explanations.
111- When the tool returns no items, say so explicitly and suggest
112 the user either run `fin_pulse_create(mode="ingest")` first or
113 widen the `days` window.
114- Daily briefs come back with `digest.stats` (`total_selected`,
115 `source_breakdown`). Surface the count so the user knows whether
116 the digest is meaningful.
117- Every task_id follows `fp-<uuid>`; include it in your reply so
118 the user can reference it later.
119
120---
121
122## 4. Cross-tool recipes
123
124### Recipe A — "What's moving the Fed today?"
125
1261. `fin_pulse_search_news(q="美联储", days=1, min_score=5, limit=10)`.
1272. If `items.length < 3`, follow up with
128 `fin_pulse_create(mode="ingest", since_hours=6)` and retry.
1293. Summarize the top 5 in bullet points with source_id tags.
130
131### Recipe B — "Generate + push the morning brief to Feishu"
132
1331. `fin_pulse_create(mode="daily_brief", session="morning",
134 since_hours=12, top_k=20, lang="zh")` → get `task_id` + `digest`.
1352. Quote the resulting `digest.title` and article count so the user
136 can confirm.
1373. If they want it on IM, say: "你可以在插件 Digests Tab 点**Resend**
138 选飞书 / 企微,或把 `channel` + `chat_id` 告诉我我再帮你补
139 发 hot_radar 任务推一次。" (Do **not** try to call
140 `dispatch/send` from the tool surface — the REST surface is the
141 right entry point and requires an explicit `chat_id`.)
142
143### Recipe C — "Turn on a radar rule"
144
1451. `fin_pulse_settings_set({"updates": {"radar_rules":
146 "+美联储\n+降息\n!传闻"}})`.
1472. Remind the user that radar *runs* only via a scheduled task
148 (`POST /schedules`) or an explicit
149 `fin_pulse_create(mode="hot_radar", ...)` with targets.
150
151---
152
153## 5. Safety rails
154
155- Never send `dispatch/send` or `hot_radar/run` without an explicit
156 `chat_id` from the user — IM pushes are user-visible and spamming
157 them is a support incident.
158- If `fin_pulse_settings_get` reveals `newsnow.mode=off`, don't
159 pretend NewsNow data is present.
160- Respect the redaction — if a user asks "what's my Feishu webhook",
161 reply that it's redacted at the tool surface and point them to
162 the plugin Settings tab.