Hermes 多角色实战:我做了一个智能投研系统
最近花了一段时间研究 Hermes Agent,给自己搭了一套期货智能投研系统。
整体效果出乎我的意料------一句"分析甲醇"指令,十来分钟后我收到一份带置信度评分、仓位建议、5 个观测阈值的机构级投研报告。不是一个 Agent 写的,是 6 个 AI 角色在隔离环境里各自挖完之后由"首席投资官"综合的,全程我没敲第二行命令。
这套系统还在持续进化。下一步我打算做两件事:① 把它从期货扩到股票智能投研 ,多角色分工的逻辑直接复用;② 接入主动推送------AI 自己定时跑、自己判断哪些品种值得提醒,结论直接推到我手机的 IM 上,不用我主动问。
这篇就是这趟搭建的复盘------讲清楚我用 Hermes 搭了个什么、用到了哪些 Hermes 特性、最后留下三份对照清单。Profile 和 Skill 的内部细节 (system prompt、脚本、知识库)本文不展开,后续找机会单独整理。
TL;DR :这是一份作品记录 ------我用 Hermes 搭了个智能投研系统,从一句"分析甲醇"指令到一份带置信度评分、仓位建议、5 个观测阈值的机构级报告,全程十来分钟 (其中纯 Agent 运行不到 10 分钟,剩下是我和它确认拆解方案的交互时间)。本文做三件事:① 介绍这个系统用到的 6 个 Hermes 特性 (Profile / Skills / Kanban / Dispatcher / Scratch Workspace / Heartbeat-Reclaim);② 用一次甲醇期货分析展示它怎么跑、产出长什么样;③ 给出三份对照清单 ------7 个 Profile、2 个 Skill、10 条命令。本文聚焦架构与清单 ,Profile / Skill 的内部细节 (system prompt、脚本、知识库)不展开------后续找机会单独整理成文。
先讲清楚 4 个概念(熟悉 Hermes 的读者可跳过)
后文会反复出现 Hermes、Profile、Kanban、Skill 这几个词。先用一段话把它们摊开,避免读到一半看不懂。
Hermes Agent :Nous Research 出的一个 AI Agent 框架,定位类似 Claude Code / Cursor 但有几个独到能力------持久记忆 (关机后不会忘记你)、技能系统 (领域知识沉淀成可复用包)、多 Profile 协作(一个工具能跑多个 AI 角色协同)。本文集中在最后一个能力上。
Profile :一份独立的 Agent 配置 ------通俗说就是"一个 AI 角色"。每个 Profile 有自己的模型选择、人设规则(system prompt)、记忆、技能集。7 个 Profile 启动后是 7 个独立进程,看不见彼此的中间产物。我这套系统里有 7 个 Profile:CIO、多头研究员、空头研究员、技术分析师、市场研究员、风控、记忆反思器,外加 default(我自己的对话入口)。
Kanban :SQLite 持久化的任务图 。所有任务、依赖、状态、事件流都存在 ~/.hermes/kanban/kanban.db 这一个本地数据库文件里。Hermes 内置了一个 dispatcher 调度器 ------每秒扫一次:哪些任务的依赖都满足了就升为 ready,哪些 Profile 有空闲槽就 spawn 一个 worker 过去 claim 任务。Profile 之间不直接对话,全部通过 Kanban 传递产物。
Skill :可复用的领域包 。不是一段 prompt------是一个完整目录,含 SKILL.md(描述能力)、scripts/(可执行脚本)、references/(知识库)。Agent 加载技能用渐进披露------先看目录,按需展开内容。本文用到 2 个 Skill:kanban-orchestrator(总调度技能)和 commodity-supply-chain-intelligence(商品供应链情报包)。
把这 4 个概念在脑子里挂住------后面所有内容都是它们的组合。
一句话判断
单 Agent 的瓶颈不是模型能力,是它一个人扛不下专业分工 。Hermes 把多 Agent 真正落地需要的几件事------角色隔离、任务图持久化、依赖调度、产物隔离、容错------都做成了原生特性,不需要额外造轮子。这篇就是把这几件事摊开来看。
出场:7 个档案,是团队不是会话
下面就以这次"分析甲醇"为例,把整个流程过一遍。
跑 hermes profile list,能看到我配置过的 7 个 Profile:
| 档案 | 状态 | 模型 |
|--------------------------|----------|-------------------|
| default | 运行中 | deepseek-v4-flash |
| bear_researcher | 停止 | deepseek-v4-flash |
| bull_researcher | 停止 | deepseek-v4-flash |
| chief_investment_officer | 停止 | deepseek-v4-flash |
| market_researcher | 停止 | deepseek-v4-flash |
| memory_reflector | 停止 | deepseek-v4-flash |
| risk_manager | 停止 | deepseek-v4-flash |
| technical_analyst | 停止 | deepseek-v4-flash |
前面说了 Profile 是"一份独立的 Agent 配置"------具体落到磁盘上,每个 Profile 是一个目录。下面只挑重点(缓存、临时文件略过):
~/.hermes/profiles/bull_researcher/
├── profile.yaml # Profile 元信息(名字、描述、属哪个集合)
├── config.yaml # 模型、温度、token 上限等运行参数
├── SOUL.md # 这个角色的"灵魂"------人设规则、判断框架、输出约束
├── memories/
│ └── MEMORY.md # 这个角色的持久记忆(关机不丢)
├── skills/ # 挂到这个角色的技能目录树,按分类组织
│ ├── data-science/
│ ├── devops/
│ ├── research/c
│ └── ... # 26 个技能分类
├── sessions/ # 历史会话存档(这个角色每次对话都留痕)
├── checkpoints/store/ # 改代码 / 关键操作前的回滚快照
├── cron/ # 这个角色专属的定时任务
├── hooks/ # 事件钩子(比如 worker 完成后触发)
├── workspace/ # 角色的工作目录
└── state.db # SQLite,存这个角色的运行时状态
最关键的是 SOUL.md ------它是这个角色的人设和判断规则。我的 bull_researcher 的 SOUL.md 写着:
markdown
# Bull Researcher Agent Persona
You are a biased long-only hedge fund analyst.
Mission:
Construct the strongest bullish case.
Rules:
- Focus only on upside catalysts
- Ignore bearish arguments unless refuting them
- Think in asymmetric upside scenarios
Output:
Bullish drivers, catalysts, acceleration conditions
bear_researcher 是镜像版本的 SOUL.md,只看空。risk_manager 的 SOUL.md 让它不站队、专做最大回撤情景。chief_investment_officer 的 SOUL.md 让它最后看完所有人的报告再下结论。7 个 Profile 的差异本质是 8 份 SOUL.md 的差异------其他都是 Hermes 给每个 Profile 标配的基础设施。
这种"角色化"在单 Agent 里其实也能做------你在 prompt 里写"现在你是多头分析师"。但有两个问题:
- 上下文污染。多头看完空头的论据,下意识就会被影响。我做过实验,同一个 Agent 先看空再看多,多头论据明显比先看多再看空时弱。
- 专业偏置丢失。技术分析需要的是图表敏感度,基本面需要的是数据宽度,风控需要的是悲观主义。一个 prompt 切来切去,每个角色都不像。
Profile 的隔离把这两个问题一次解决------每个角色在自己的进程里跑,看不见别人的中间产物,只看到 Kanban 任务图里被显式喂给它的 parent 输出。
Skill 上场:kanban-orchestrator
我没去手工分配任务,我先调了一个技能:
/kanban-orchestrator
这是 Hermes Skills System 里 devops 分类下的一个总调度技能。它干一件事------把一句模糊需求拆成 Kanban 任务图。技能加载完,它先问我两个问题:
- 你的目标是什么
- 你有哪些可用的 Profile
第二个它自己 hermes profile list 跑了一下就知道了。
我说"分析甲醇",它给我吐了张方案表:
| 任务 | 负责档案 | 内容 |
|---|---|---|
| T1 数据采集 | market_researcher |
跑 commodity_intel.py 获取 10 维数据 + 新浪搜索补充供应链 |
| T2 技术面 | technical_analyst |
MA 均线 / 支撑阻力 / 量价 / 形态 / MACD-RSI |
| T3 多头逻辑 | bull_researcher |
MTO 修复 / 伊朗风险 / 季节性 / 政策 / 估值 / 成本 |
| T4 空头逻辑 | bear_researcher |
产能过剩 / 需求疲软 / 煤炭塌陷 / 进口高位 / 宏观弱 |
| T5 风险评估 | risk_manager |
整合 T1+T3+T4,给最大回撤、风险事件、仓位建议 |
| T6 投资结论 | chief_investment_officer |
综合所有人,给方向 / 入场 / 止损 / 时间维度 |
依赖关系:
T1 (market_researcher) ──┐
T2 (technical_analyst) ──┤
T3 (bull_researcher) ──┤──▶ T5 (risk_manager) ──▶ T6 (CIO)
T4 (bear_researcher) ──┘ ▲
│
T5 的输出也流入 T6
这张图有几件事值得注意:
T1-T4 完全并行 。多头看不见空头,空头看不见多头,技术面看不见基本面。这不是低效,是故意的隔离------只有这样每个人才能挖到底。等他们都挖完,T5 才把数据揉到一起做风控。
T5 不依赖 T2。技术面不参与风控决策,只参与 CIO 的最终综合。这是金融逻辑:风控是"最坏情况下我亏多少",技术形态在极端行情里没有意义。
T6 依赖所有人。CIO 是综合者,他要看到所有原始观点,自己判断谁更可信。
这张图不是模板,是 kanban-orchestrator 这个技能根据"分析一支期货品种"的语义现场拆出来的。我换成"分析腾讯股票",它会给出不同的任务图------可能加一个 bond_analyst 看可转债套利,去掉 commodity-supply-chain-intelligence 技能依赖。
创建任务:依赖关系直接编码进命令
我说"合理,继续"。它开始批量创建 Kanban 任务,下面是 6 条命令的真实形态(删了部分 body 简化展示):
bash
# T1:数据采集(带技能注入)
hermes kanban create "data: 甲醇(MA)全维度数据采集" \
--body "运行 commodity_intel.py ... 参考 references/methanol-ma-fundamentals.md" \
--assignee market_researcher \
--skill commodity-supply-chain-intelligence \
--max-runtime 30m \
--priority 1
# T2-T4:技术面 / 多头 / 空头(无依赖)
hermes kanban create "tech: 甲醇(MA)技术面分析" \
--assignee technical_analyst --max-runtime 20m --priority 1
hermes kanban create "bull: 甲醇(MA)多头逻辑分析" \
--assignee bull_researcher --max-runtime 20m --priority 1
hermes kanban create "bear: 甲醇(MA)空头逻辑分析" \
--assignee bear_researcher --max-runtime 20m --priority 1
# T5:风控(依赖 T1/T3/T4)
hermes kanban create "risk: 甲醇(MA)风险评估" \
--assignee risk_manager \
--parent t_be63214a \
--parent t_e3fef572 \
--parent t_4d675132 \
--max-runtime 15m --priority 2
# T6:CIO(依赖全部)
hermes kanban create "cio: 甲醇(MA)投资结论与操作建议" \
--assignee chief_investment_officer \
--parent t_be63214a --parent t_f0afecfd \
--parent t_e3fef572 --parent t_4d675132 \
--parent t_671e0b13 \
--max-runtime 20m --priority 2
注意三件事:
--assignee 把任务绑到一个 Profile 。不是用谁的模型跑,是用这个 Profile 的整套配置------它的 SOUL.md(人设)、它的 memories/、它的 skills/ 目录树------去跑这个任务。bull_researcher 这条命令一旦被 dispatcher 拿走,启动的就是一个 bull_researcher 进程,跟我这个 default 会话完全无关。
--skill 显式注入技能 。T1 加了 commodity-supply-chain-intelligence,意思是 worker 启动时这个技能在 skills_list 的 Level 0 目录里直接出现,Agent 会主动 skill_view 进去看。其他几个任务没加技能------多头研究员不需要"商品供应链情报"这个总技能,它需要的是自己 Profile 配置里挂的那些。
--parent 编码依赖。T5 写了三个 parent,T6 写了五个。Kanban 内部就是个 DAG,dispatcher 每秒扫一遍:找 status=todo 但所有 parent 都 done 的任务,把它升为 ready,然后让对应 Profile 去 claim。
整张图编码完,本地有个 SQLite 文件 ~/.hermes/kanban/kanban.db 存着所有任务、依赖、状态、事件流。这是 Hermes 多 Agent 真正的核心------任务图是持久化的,跨进程跨平台跨 Profile 共享。 你 CLI 创建的任务,接入的 IM 客户端那边也能看到;market_researcher 的产出,一旦 commit 进 done,CIO 那边自动可见。
Dispatcher 跑起来:3 个 worker 同时干活
任务建完,我跑了一句 hermes kanban list:
● t_be63214a running market_researcher data: 甲醇(MA)全维度数据采集
● t_f0afecfd running technical_analyst tech: 甲醇(MA)技术面分析
● t_e3fef572 running bull_researcher bull: 甲醇(MA)多头逻辑分析
▶ t_4d675132 ready bear_researcher bear: 甲醇(MA)空头逻辑分析
◻ t_671e0b13 todo risk_manager risk: 甲醇(MA)风险评估
◻ t_369bddb9 todo chief_investment_officer cio: 甲醇(MA)投资结论与操作建议
三个 worker 同时在跑。bear 在 ready 队列里排队,因为我本机的并发 worker 上限是 3。T5/T6 在 todo------它们的 parent 还没全 done。
我点开一个看正在干什么:
bash
$ hermes kanban show t_be63214a
Task t_be63214a: data: 甲醇(MA)全维度数据采集
status: running
assignee: market_researcher
workspace: scratch @ /Users/hxy/.hermes/kanban/workspaces/t_be63214a
skills: commodity-supply-chain-intelligence
started: 2026-06-10 17:03
Events (8):
[17:03] created {assignee: market_researcher, status: ready, ...}
[17:03] [run 1] claimed {lock: bogon:977, expires: 1781083105, run_id: 1}
[17:03] tip_scratch_workspace {message: scratch workspaces are ephemeral}
[17:03] [run 1] spawned {pid: 7010}
[17:03] [run 1] heartbeat
[17:04] [run 1] heartbeat
[17:05] [run 1] heartbeat
[17:06] [run 1] heartbeat
每个 worker 在 ~/.hermes/kanban/workspaces/<task_id>/ 里有一个独立的临时工作目录 (scratch),互相看不见。如果想要持久化的产物,可以建任务时加 --workspace dir:/abs/path 或 --workspace worktree: 用 git worktree。
每分钟一次 heartbeat 是 worker 给 dispatcher 报"我还活着"的信号。如果连续几个心跳缺席,dispatcher 会认为这个 worker 挂了,自动 reclaim 锁,让任务重新进入 ready 队列等下一个 worker 接手。这套调度从设计上就预设了 worker 会挂------这是分布式系统该有的姿态,单 Agent 没有这个保险。
第一份产出:6 分钟,一份原始数据交上来
我 hermes kanban tail t_be63214a 监听事件流,等了 6 分钟。第一行 completed 出现:
[17:09] completed {
result_len: 0,
summary: '甲醇(MA)全维度数据采集完成。
通过 akshare 获取 6 个合约报价(BACKWARDATION 结构, MA2609 主力 2972)、
2776 行主力连续日线(2026 年内 +34.18%)、
15 日 OHLCV 详情、
技术指标(MA5/10/20 多头排列, MA60=2992 压力)、
仓单数据(仅 2920 手历史低位)。
通过新浪搜索获取关键新闻:
伊朗 7 套装置复产、
沿海库存 56.55 万吨(同比 -16.96%)、
MTO 开工率 80.1%(环比 -6.6%)。
所有原始数据汇总输出到 ma_comprehensive_data.txt。'
}
这一行 summary 信息密度极高。我拆一下:
| 维度 | 数据点 | 这意味着 |
|---|---|---|
| 期限结构 | BACKWARDATION(近月升水远月) | 现货紧张,多头友好 |
| 主力价格 | MA2609 = 2972 元/吨 | 当前位置 |
| 年内涨幅 | +34.18% | 已经在牛市中段 |
| 均线系统 | MA5/10/20 多头排列,MA60=2992 是压力 | 短期强势但接近重要均线 |
| 仓单 | 2920 手历史低位 | 仓单极少 = 现货不愿交割 = 现货坚挺 |
| 供应 | 伊朗 7 套装置复产 | 3-4 周后进口冲击 |
| 库存 | 沿海 56.55 万吨,同比 -16.96% | 显著去库 |
| 需求 | MTO 开工率 80.1%,环比 -6.6% | 主力下游在走弱 |
这是一个矛盾的画面:价格强、库存低、仓单低、伊朗要来、MTO 要走弱。多头有现货支撑,空头有进口预期 + 需求转弱。
但 market_researcher 不下结论 。它的角色定义就是只采集,不判断------多空判断要分别交给 bull_researcher 和 bear_researcher,它们看到的是同一份原始数据,但站在不同的位置上挖。
T1 done 之后,dispatcher 自动检查:
- T2 不依赖 T1,已经在自己跑
- T3/T4 不依赖 T1,已经在自己跑(它们用 default profile 的市场常识在写宏观逻辑,等数据交上来后会被 CIO 综合)
- T5 依赖 T1/T3/T4,等 T3/T4 也 done 才能 ready
- T6 依赖全部,最远的等待者
我又跑了一次 list:
● t_671e0b13 running risk_manager risk: 甲醇(MA)风险评估
◻ t_369bddb9 todo chief_investment_officer cio: 甲醇(MA)投资结论与操作建议
✓ t_be63214a done market_researcher data: 甲醇(MA)全维度数据采集
✓ t_f0afecfd done technical_analyst tech: 甲醇(MA)技术面分析
✓ t_e3fef572 done bull_researcher bull: 甲醇(MA)多头逻辑分析
✓ t_4d675132 done bear_researcher bear: 甲醇(MA)空头逻辑分析
T1-T4 全部 done,T5 自动升为 running。我什么都没干。
用到的 6 个 Hermes 特性
把上面这套智能投研拆开看,它依赖 Hermes 的 6 个原生特性。这 6 个不是我"发明"的设计模式,是 Hermes 文档里就有的内建能力------我只是把它们装在了一起。
特性 1:Profile --- 角色化 Agent 配置
它是什么 :每个 Profile 是一份独立的 Agent 配置------config.yaml 选模型和运行参数,SOUL.md 定行为边界(人设规则),memories/MEMORY.md 装这个角色的持久记忆,skills/ 挂专属技能。它跟 default 会话同等地位,启动后是个独立进程。
这个系统怎么用它:7 个角色(CIO / 多头 / 空头 / 技术 / 风控 / 数据 / 记忆反思 / default)每个都是独立 Profile。它们在各自进程里跑,看不见对方的中间产物。
为什么必要:单 Agent 切换"现在你是多头"这种 prompt 切换会有上下文污染------多头看完空头的论据,下意识就被影响。Profile 的进程级隔离把这个问题一次解决。生产环境可以给不同角色配不同模型------CIO 用更贵的推理模型,数据采集用便宜的快模型,目前我都用 deepseek-v4-flash 是为了控本机预算。
特性 2:Skills --- 渐进披露的领域包
它是什么 :Hermes 的 Skills 不是一段 prompt,是一个目录结构 ------SKILL.md 描述能力,scripts/ 放可执行脚本,references/ 放知识库。加载机制是渐进披露:
Level 0: skills_list() → [{name, desc}, ...] ~3k tokens(看目录)
Level 1: skill_view(name) → 完整 SKILL.md 按需展开
Level 2: skill_view(name, x) → 子文件 references/... 更深按需
50 个技能全量加载会爆系统提示,渐进披露让 token 不随技能数量线性增长。
这个系统怎么用它:用了两个 Skill------
kanban-orchestrator(devops 分类):总调度技能,把"分析甲醇"一句话拆成 6 个任务图。commodity-supply-chain-intelligence(data-science 分类):包含commodity_intel.py脚本和methanol-ma-fundamentals.md知识库,给 market_researcher 用。
为什么必要:没有 Skill 系统,"把模糊需求拆成任务图"和"按品种采集 10 维数据"这两件事都得每次让 Agent 现想------慢、不稳定、不可复现。Skill 把它们沉淀成可复用的领域包。
特性 3:Kanban --- SQLite 持久化任务图
它是什么 :~/.hermes/kanban/kanban.db 是一个 SQLite 文件,所有任务、依赖、状态、事件流、产物路径都在这里。任何 Profile 启动一个 worker,输入是 task body + parent 的 result,输出 commit 回 task 表的 result 字段。
SQLite 这个选择很关键:
- 单文件,备份/迁移/审计都简单
- 跨进程并发安全(WAL 模式)
- 不需要起服务,cli 直接 sqlite3 就能查
- worker 死了重启,状态不丢
这个系统怎么用它 :6 个任务、5 条依赖边都编码在 Kanban 里。--parent 字段直接把依赖写进任务定义,声明依赖、不声明顺序------这是分布式调度的基本功。
为什么必要 :多 Agent 真正的核心问题不是"开几个 Agent 互相对话",是一个 Agent 的产物怎么干净地交给下一个 Agent。Kanban 是这个问题的协议层。比 Redis Pub/Sub 那种消息队列方案强一档------事件流是 append-only 的永久可查,不是发完就没。
特性 4:Dispatcher --- gateway 内置调度
它是什么 :旧版本的 hermes kanban daemon 已经 deprecate,调度器跟 IM 接入网关(gateway)那个服务合并了:
daemon DEPRECATED --- dispatcher now runs in the gateway.
Use `hermes gateway start`.
每秒一次 dispatcher 扫描的逻辑:
1. 找 expired claim 的 running 任务 → reclaim
2. 找 status=todo && all_parents=done 的任务 → 升为 ready
3. 找 status=ready 且对应 Profile 有空闲 worker 槽 → spawn worker
4. 检查 running 任务的 heartbeat → 长时间无心跳的 reclaim
这个系统怎么用它 :我点完 6 个 hermes kanban create 之后没敲第二行命令------T1-T4 自动并行起来,T5 等 T1/T3/T4 done 自动升 ready,T6 等全部 done 自动升 ready。dispatcher 全程在背景里推。
为什么必要 :调度是数据库 + 几条 SQL 的事,不需要让一个 Agent 来"管理"其他 Agent。让 Agent 管 Agent 是把简单事情复杂化的开始。
特性 5:Scratch Workspace --- 临时隔离工作区
它是什么 :每个任务在 ~/.hermes/kanban/workspaces/<task_id>/ 有自己的临时目录。worker 在里面写文件、跑脚本、缓存中间数据,互不干扰。scratch 是 ephemeral 的------任务 done 后自动清理:
tip_scratch_workspace: scratch workspaces are ephemeral ---
they're deleted when the task completes.
Use --workspace worktree: (git worktree) or
--workspace dir:/abs/path (existing dir) to preserve worker output.
这个系统怎么用它 :6 个 worker 各自有独立 scratch,bull_researcher 看不到 bear_researcher 写的草稿。要持久化产物(比如 market_researcher 的 ma_comprehensive_data.txt),就显式选 --workspace dir:/abs/path。
为什么必要:
- 信息隔离:多空研究员若能看到对方草稿,逻辑会互相污染("哎对面这么想,那我换个角度")。隔离 workspace 强制信息流通过 Kanban 的 result 字段走,不允许走文件系统的暗道。
- 清理隔离:默认让你"借完就还",要保留得显式声明------这是一种好的违反路径设计:你不会因为忘了清理而把磁盘塞满。
特性 6:Heartbeat & Reclaim --- worker 容错
它是什么:每个 running worker 每分钟向 Kanban 发一条 heartbeat 事件。如果连续几个心跳缺席,dispatcher 认为这个 worker 挂了,自动 reclaim 锁,让任务重新进入 ready 队列等下一个 worker 接手。
[17:03] [run 1] claimed {lock: bogon:977, expires: 1781083105, run_id: 1}
[17:03] [run 1] spawned {pid: 7010}
[17:03] [run 1] heartbeat
[17:04] [run 1] heartbeat
[17:05] [run 1] heartbeat
...
[17:09] completed
每个任务还有 max-retries(默认 2)和 max-runtime(我建任务时设 15-30 分钟)。
这个系统怎么用它:本机环境我没遇到 worker 挂的情况,但建任务时都设了 max-runtime------如果某个 worker 卡死,最多浪费 30 分钟,不会无限挂着。
为什么必要 :这套调度从设计上就预设了 worker 会挂------这是分布式系统该有的姿态。单 Agent 没这个保险,挂了就全盘重来。
本文不展开的细节:Profile 和 Skill 内部
提前说清楚------这篇只讲到"架构 + 清单"这一层 ,下面这些细节本文不展开:
- 每个 Profile 的
SOUL.md全文 。多头 / 空头 / 风控 / CIO 的人设规则、判断框架、输出格式约束,每个都几百到上千字,展开会把文章撑爆。这部分还在持续迭代------等 SOUL 稳定后会单独写一篇,专门拆"怎么写一份能让 bull_researcher 挖到底的 SOUL.md"。 commodity_intel.py脚本和methanol-ma-fundamentals.md知识库 。脚本里有 akshare 接入、新浪搜索抓取、10 维数据汇总的逻辑;知识库是一份甲醇基本面笔记。两个加起来又是一篇文章的体量------会单独写一篇,专门拆"怎么把一个商品品种沉淀成 Skill"。- 多品种泛化验证。目前只在甲醇上跑通了端到端,PTA / 沥青 / 燃料油这些化工品适不适用还要再试。等多跑几个品种,会有第三篇------专门讲"多 Agent 投研系统的迁移成本和踩坑"。
为什么先发这一篇而不是直接写细节?因为架构和清单是稳定的------Hermes 的 6 个特性、7 个 Profile 角色定位、Kanban 的依赖编码方式,这套骨架我跑了几次就确信了。Profile 内部和 Skill 内部还在调,过早写细节就是早衰文。
读到这儿的你如果也在用 Hermes,照着 6 个特性 + 三份清单的样子,自己搭一个验证版完全够------剩下的内部填充交给你自己的领域知识就好。
几分钟后:CIO 把报告交了
倒了杯水回来,再跑一句 hermes kanban list:
✓ t_be63214a done market_researcher data
✓ t_f0afecfd done technical_analyst tech
✓ t_e3fef572 done bull_researcher bull
✓ t_4d675132 done bear_researcher bear
✓ t_671e0b13 done risk_manager risk
✓ t_369bddb9 done chief_investment_officer cio
全部 done。整个流水线从我点回车到 CIO 出报告,十来分钟------纯 Agent 跑的时间不到 10 分钟,加上我和它确认拆解方案、回看任务状态那几次交互,凑够 10 分钟出头。下面是这份报告的关键骨架------不是我自己写的,是 CIO Profile 看完前面 5 个 Profile 的全部产出之后综合的。
一、基础数据(market_researcher 给的桩)
| 指标 | 数据 |
|---|---|
| 主力合约 | MA2609 |
| 最新收盘 | 2,972 |
| 2026 年内涨幅 | +34.18% |
| 合约结构 | BACKWARDATION(近月升水,远月贴水 200+ 点) |
| 港口库存 | 华东 56.55 万吨(同比 -16.96%) |
| 注册仓单 | 仅 2,920 手(历史低位) |
| MTO 开工率 | 80.1%(环比 -6.6%) |
| 关键供应 | 伊朗 7 套装置复产 |
二、技术面(technical_analyst 给的桩)
短期信号 (1-2周): ⬆ 偏多
均线: MA5 > MA10 > MA20 (多头排列)
MACD: 金叉,红柱放量
持仓: 持续增加(多空分歧加大)
量价: 价涨量增
中期风险:
MA60 = 2,992 压力 ────┐
3,000 整数关口 ├── 双重阻力
OBV 量价背离 ┘
结论:短期看多但需突破 MA60-3000 阻力区,否则反弹即是做空机会。
三、多空对决(bull vs bear)
| 维度 | 🟢 多头 | 🔴 空头 |
|---|---|---|
| 方向 | 强烈看多 → 3,200-3,500-3,800 | 强烈看空 → 2,700-2,750(极端 2,450) |
| 核心逻辑 | 伊朗地缘(占进口 40%)+ 近月升水 16% + 成本支撑 1,800-2,200 | 产能 1.15 亿吨过剩 + 远月深贴 + MTO 检修叠甲醛淡季 |
| 辅助逻辑 | MTO 利润修复 + 金九银十 + 冬季限气 | 进口放量 + 煤炭塌陷 + 3,049 双顶 |
| 硬止损 | 2,750 | --- |
注意,这两个 Profile 看到的是同一份原始数据,但走出了完全相反的方向。这就是我前面讲的"故意隔离"------多头不知道空头在写什么,反之亦然。它们不是给"中庸答案"妥协,是各自把自己那一边挖到底。
四、风险评估(risk_manager 的打分)
| 维度 | 分数 |
|---|---|
| 多头评分 | 19 / 30 |
| 空头评分 | 23 / 30 ← 占优 |
| 整体风险等级 | ⚠️ 高危 |
风控的核心结论一句话:伊朗地缘是单一主导变量 ------若霍尔木兹海峡封锁,甲醇暴涨,空头逻辑瞬间作废;若局势正常,偏空格局不变。所以建议控制仓位:做多 ≤10%,做空 ≤5%,对冲 ≤20%。黑天鹅区间下限 1,950,上限 4,000。
五、CIO 最终裁决
裁决:偏空 | 置信度:60 / 100
操作策略:
| 参数 | 数值 |
|---|---|
| 方向 | 🐻 逢高做空 |
| 入场区间 | 2,980 -- 3,020(等反弹入场,不追空) |
| 第一目标 | 2,860 |
| 第二目标 | 2,790 -- 2,800 |
| 硬止损 | 3,100 |
| 仓位 | ≤5%(伊朗尾部风险限制) |
时间维度:
| 周期 | 判断 |
|---|---|
| 短期 1-2 周 | 震荡偏空,2,980-3,020 是反弹做空机会 |
| 中期 1-3 月 | MTO 检修 + 甲醛淡季 → 累库,目标 2,790-2,800 |
| 长期 6 月+ | 金九银十 + 秋检 + 伊朗冬季限气,可能反弹,需重评 |
关键观测清单(5 个杠杆变量):
- 🇮🇷 伊朗地缘 --- 霍尔木兹海峡 / 制裁新闻(最大单一变量)
- 🏭 MTO 开工率 --- 跌破 75% 确认需求塌陷,回升 85%+ 利空减弱
- 📦 港口库存 --- 华东突破 70 万吨则确认累库
- 📄 仓单 --- 从 2,920 低位回升 = 交割压力增大
- ⛏️ 煤炭 --- 跌破 700 元/吨则成本支撑进一步削弱
⚠️ 免责声明:以上分析基于多 Agent 协作产出,仅供参考,不构成投资建议。
这份报告的"含金量"在哪
我看完报告的第一反应是------这不是单 Agent 能写出来的东西。具体三个细节我必须拎出来说。
第一,置信度 60/100 这个数字很难写 。一个 Agent 自己写报告,要么自信满满("强烈看空"),要么和稀泥("建议保持观望")。但 CIO 看到的是空头 23/30 比多头 19/30 占优------优势存在但不悬殊------所以给出"60 分置信度",并明确写仓位 ≤5% 来匹配这个不确定性。置信度和仓位匹配,是机构投研的基本功,单 Agent 在自己一个 prompt 里很难自然写出这种克制。
第二,"反弹做空、不追空"这一笔很贵 。空头 23 分占优,技术面又显示短期偏多------这两条放在一起,结论就不是"立刻做空",是"等反弹到 2,980-3,020 再做空"。这个判断需要同时持有"中期偏空"和"短期偏多"两个看似矛盾的信号,并把它们综合成一个具体动作。多视角并存才能产出这种判断。
第三,关键观测清单是真正可执行的 。它不是"持续关注市场动态"这种废话,是 5 个有具体阈值的指标------MTO 跌破 75% 触发什么、库存破 70 万吨触发什么、煤炭破 700 元/吨触发什么。这是一份"能挂在墙上"的清单,每周扫一眼就知道判断要不要更新。
这三个细节合起来才是这份报告的真正价值------不是它告诉我"做空",是它告诉我"在什么条件下做空、做多少、什么时候改主意"。
三份清单
这套智能投研落到地上就是三份东西。下面把它们摊开。
清单 1:Profile 清单(7 个角色)
| Profile | 模型 | 职责定位 | 在本次流程中 |
|---|---|---|---|
default |
deepseek-v4-flash | 我自己的对话入口,负责接需求、调度、收报告 | 接"分析甲醇"、跑 kanban-orchestrator、查任务 |
chief_investment_officer |
deepseek-v4-flash | 综合所有专家产出,给方向 / 仓位 / 时间维度 / 观测清单 | T6(最终裁决) |
market_researcher |
deepseek-v4-flash | 只采集,不判断------10 维数据 + 新浪搜索补充 | T1(数据采集) |
technical_analyst |
deepseek-v4-flash | 技术面专精------均线 / 支撑阻力 / 形态 / 量价 / MACD-RSI | T2(技术分析) |
bull_researcher |
deepseek-v4-flash | 只看多------把多头逻辑挖到见底,不接受感觉 | T3(多头逻辑) |
bear_researcher |
deepseek-v4-flash | 只看空------镜像版本的 bull_researcher | T4(空头逻辑) |
risk_manager |
deepseek-v4-flash | 不站队------做最大回撤、风险事件、仓位建议 | T5(风险评估) |
memory_reflector |
deepseek-v4-flash | 跨次复盘 / 教训沉淀 | 本次未触发,留作后续跑批用 |
关键设计 :market_researcher 和 risk_manager 都是不站队角色 ,前者只给数据、后者只算风险。多头空头的活留给 bull_researcher / bear_researcher 在隔离环境下各挖各的。
清单 2:Skill 清单(2 个技能)
| Skill | 分类 | 给谁用 | 内容 |
|---|---|---|---|
kanban-orchestrator |
devops | default |
总调度技能。把"分析甲醇"这种模糊指令拆成 Kanban 任务图 + 依赖关系,自动 spawn 到对应 Profile |
commodity-supply-chain-intelligence |
data-science | market_researcher |
商品供应链情报包:含 commodity_intel.py(akshare + 新浪搜索数据采集脚本)+ references/methanol-ma-fundamentals.md(甲醇基本面知识库) |
关键设计 :Skill 在创建任务时通过 --skill <name> 显式注入,worker 启动时这个 Skill 出现在 skills_list 的 Level 0 目录里,Agent 会主动 skill_view 进去看。其他几个角色没注入 Skill------它们靠自己 Profile 的 SOUL.md 和 memories/MEMORY.md 工作就够了。
清单 3:命令清单(10 条)
| 用途 | 命令 |
|---|---|
| 列出所有 Profile 状态 | hermes profile list |
| 启动调度网关(dispatcher 跑这里) | hermes gateway start |
| 加载总调度技能 | /kanban-orchestrator(在 Hermes 会话内) |
| 创建任务 | hermes kanban create "标题" --assignee <profile> [--skill <skill>] [--parent <task_id>] --max-runtime 30m |
| 列出所有任务 | hermes kanban list |
| 查看任务详情 + 事件流 | hermes kanban show <task_id> |
| 实时跟踪事件流 | hermes kanban tail <task_id> |
| 查看 worker 日志 | hermes kanban log <task_id> |
| 看可用 Profile + 任务计数 | hermes kanban assignees |
| Worker 看自己的完整上下文 | hermes kanban context <task_id> |
整套流程跑下来,人工敲命令的次数 = 6 条 create + 几次 list/show 查状态。不到 10 个动作。
收尾:从 3 小时到 10 分钟
这份报告我自己一个人写,至少要花 3-4 小时。大部分时间不是花在"想"上,是花在切换视角 上------一会儿当多头挖论据,一会儿当空头挖论据,一会儿当风控数仓位,一会儿当 CIO 综合权衡。每次切换,前一个角色的偏置都会渗透到下一个角色,最后写出来的报告其实是"一个我在 4 个角色间妥协的产物",不是 4 个独立角色的真实分歧。
多 Agent 把视角切换的成本外部化了------每个角色由它自己的 Profile 扛着 ,互相看不见,最后只交一份各自挖到底的产物。CIO 拿到的不是一个"妥协后的我",是 5 份真实分歧。这一份甲醇报告我倒杯水的功夫就拿到了,纯 Agent 跑的时间不到 10 分钟 ,3-4 小时压成十几分钟,20+ 倍的杠杆。
回到一开始那句话:
单 Agent 的瓶颈不是模型能力,是它一个人扛不下专业分工。
这个判断我现在更确定了。开头说的两个下一步进化方向------
股票智能投研:7 个 Profile 的角色框架(CIO / 多空 / 技术 / 风控 / 数据 / 反思)几乎不用动,换掉数据采集 Skill(A 股要接 Tushare / 同花顺数据源),重写部分 SOUL.md(股票要看财报、估值、行业景气度),整套 pipeline 直接复用。预计两周能跑通。
主动推送 :用 Hermes 的 cron 特性定时跑------每天盘前给我推一份昨日异动品种的快报、每周末给我推一份持仓品种的全维度更新。AI 自己判断哪些值得提醒,结论直接推到我手机的 IM 上。从"我问 AI 投研"变成"AI 自己判断要不要找我"------这才是杠杆放大的极致形态。
这两件事单 Agent 也能做一部分,但每次都需要我手工切视角、手工对比、手工触发。多 Agent + 定时任务把这些手工动作全消掉。
这才是 AI 工具的真正杠杆------不是让你用得更快,是让你不用做你本来就不该做的事。
关注 coft,用技术人的视角理解 AI 工程化与复杂系统。