深度研究流水线
生成结构化市场报告的隔离式六步流水线
深度研究是一条专用流水线,与主 Agent 循环并行运行,但相互独立。主 Agent 循环以对话形式推进,并受权限管控;深度研究流水线则是一个六步状态机,最终产出一份结构化报告。实现位于
apps/agent/src/deep-research/pipeline.ts。
为何单独设计流水线,而不让 Agent 循环迭代? 多源研究需要并行采集数据(扇出后合并)、LLM-as-Judge 质量检查,以及重试逻辑。这些需求与对话式
plan → call → observe节奏不符。专用流水线还能保证研究输出的确定性与可溯源性,这是对话循环无法做到的。
查看实际效果:功能 → 深度研究 介绍了面向用户的一侧,包含报告输出示例。
适用场景
当目标是生成书面产物而非聊天回答时,使用此流水线:
- 针对特定资产或主题的长篇市场分析。
- 需要为每项论断注明来源的多源综合报告。
- 定时研究任务,希望获得可通过 id 查阅的产物。
对于快速对话问题("BTC 现价是多少"、"这里应该做多吗"),请使用 Agent 循环。深度研究流水线延迟更高、工具调用预算固定,且不保留当前对话的上下文。
六个步骤
除 collectData 外,每个步骤都是单次 LLM 调用。collectData 会针对每个目标,在工具注册表上运行一个子 Agent 循环。
与主 Agent 循环的隔离
流水线刻意保持隔离:
- 不读取聊天的对话历史。
- 不消耗技能系统的激活状态。
- 为数据采集自行构建一套精简工具子集,而不使用当前激活的技能。
- 不触发学习记录(
review-engine不会在流水线轮次中运行)。
隔离带来两项收益:确定性(每次研究任务从相同状态出发);成本管控(长会话的历史不会渗入研究成本)。
模式
interface ResearchRequest {
chatId: string;
userMessage: string;
mode?: "light" | "heavy";
language?: string;
}light(默认)。2 个并行采集目标,较小的最大迭代数,单遍报告生成。典型延迟:30–60 秒。heavy。4 个并行采集目标,更大的迭代预算,综合分析更深入。典型延迟:2–5 分钟。
定时/cron 研究任务选 light;用户明确要求深度报告时选 heavy。
场景
报告围绕场景组织,即预定义的分析角度,例如"多方观点"、"空方观点"、"基准情形"、"监管风险"、"宏观背景"。metaPlan 步骤根据研究主题,从
apps/agent/src/deep-research/scenarios.ts
的目录中选取 1–4 个场景。
场景选择对报告质量至关重要:缺少"宏观"场景的 BTC 研究报告往往遗漏最重要的背景信息;缺少"空方观点"则会产生确认偏差。目录刻意保持精简,以确保 LLM 场景选择器的可靠性。
输出产物
结果以 report 类型产物存储在 ArtifactStore 中:
interface ResearchResult {
report_id: string;
status: "completed" | "error" | "waiting_for_input";
title: string | null;
research_topic: string | null;
scenarios: string[];
summary: string | null;
key_findings: string[];
report_markdown: string | null;
error?: string;
tokens: { input: number; output: number };
}主 Agent 可通过 report://{id} URI 方案将已完成的报告引用给用户。这就是将研究与对话结合的方式:用户请求研究,获得 report_id,随后在聊天中提出引用该报告的后续问题。
报告正文为 Markdown 格式,包含场景标题、行内引用(通过 [text](url)),以及由 summarize 步骤生成的"关键发现"要点列表。
运行方式
在 REPL 中运行
主 Agent 激活 deep-research 领域技能,调用 deep_research_run 工具:
> write me a report on ETH staking yields this quarter
assistant: [activates deep-research skill]
assistant: [calls deep_research_run with mode=heavy]
assistant: ✓ report_id: r_abc123 — here's the summary…使用 CLI 子命令运行
完全绕过 REPL:
minara research "BTC ETF flows this quarter"
minara research "macro risks for Solana" --mode heavy完整参数列表见 子命令 → minara research。
通过 HTTP 请求运行
curl -X POST http://localhost:8080/research \
-H 'content-type: application/json' \
-d '{"topic": "BTC ETF flows", "mode": "light"}'请求与响应结构见 API → /research。
成本与可观测性
每个步骤都会在审计日志中以 source: "deep-research" 记录 {provider, model, tokens}。ResearchResult 上的 tokens 字段是用于快速核算成本的汇总估算值。如需精确的成本归因,可查询审计日志:
SELECT model, SUM(input_tokens), SUM(output_tokens), COUNT(*)
FROM audit
WHERE source = 'deep-research'
AND trace_id = ?
GROUP BY model;深度研究流水线是大多数 Minara 部署中单次 LLM 成本最高的环节。若账单异常偏高,通常先运行此查询排查。
扩展流水线
流水线刻意保持精简(pipeline.ts 约 700 行)。常见扩展方式:
- 新增场景:在
scenarios.ts中追加到目录。元计划提示词在运行时读取目录,无需修改提示词。 - 调整采集并发数:在
PipelineConfig中设置collectConcurrency。默认值为 4,与 v1 上限一致。 - 调整每个目标的最大迭代数:设置
collectMaxIterations。默认值为 8,即每个数据采集子 Agent 的 LLM 轮次预算。 - 新增后处理步骤:在流水线类中追加一个方法,在
summarize与返回之间调用。不要将逻辑内联到已有步骤中;步骤边界是流水线可调试性的保障。
不要将流水线接入主 Agent 循环的历史记录。隔离是设计特性;一旦破坏,聊天成本将渗入研究成本。
不适合放入研究的内容
- 依赖实时价格的决策。 流水线耗时数分钟,价格随时变动。任何依赖当前执行条件的操作,请使用 Agent 循环。
- 涉及资金的工具调用。 数据采集使用的精简工具子集排除了所有涉及资金的工具。若工具子集意外包含此类工具,流水线将拒绝运行。
- 用户私人上下文。 流水线不读取用户的钱包余额或历史记录,仅面向公开市场数据。若报告需要考虑用户的具体仓位,请在
bootstrap阶段将仓位信息放入用户消息;流水线会将其传递至后续步骤。