# InvesResearch Agent · 架构决策记录(Architecture Decisions)

> 二级市场投研工作台(`web/`)的架构决策记录与分层说明 · **版本 v1.0** · 状态:与产品 PRD v1.0 / 工程 PRD v2.0 同步
>
> 关联文档:[产品 PRD](./product-prd.md) · [工程 PRD](./engineering-prd.md) · [系统设计文档](./system-design.md) · [路线图](./roadmap.md) · [架构图说明](./architecture-notes.md) · [Harness 工程最佳实践](./harness-best-practices.md)
>
> 本文档的定位:产品 PRD 回答"做什么、为谁做",工程 PRD 回答"怎么造、契约是什么";这份决策记录回答的是**"为什么是这套架构,而不是别的"**——它是前两份文档反复引用的那个"为什么"。读它不需要先读完整的工程 PRD,它是一份可独立阅读的决策摘要。配套的 `architecture-notes.md` 是 4 张 SVG 架构图的逐图说明,适合视觉切入;两份文档互补使用。

---

## 1. 架构总览:为什么分五层

整个工作台被刻意拆成五个自上而下、依赖单向的层。这样拆的根本理由,是让"会频繁变的东西"和"应该长期稳定的东西"物理隔离开——模型每升级一次,围绕它搭的复杂度就要被重新定价;数据源每隔一阵就会失效一次;而用户的研究框架和领域知识则相对稳定。把它们放进不同的层,就能在不动其它层的前提下单独迭代任意一层。

| 层 | 名称 | 职责一句话 | 变化频率 |
|---|---|---|---|
| L1 | 数据层(Data) | 在一堆不稳定的免费源之上,提供对上透明、可用率 > 99% 的统一数据服务 | 高(源会失效) |
| L2 | 工具层(Tools) | DCF、因子库、NLP、报告引擎等确定性计算能力的实现 | 中 |
| L3 | 能力层(Capability) | Skills(知识与流程)+ MCP(数据与计算)双层封装 | Skills 低 / MCP 中 |
| L4 | 编排层(Orchestration) | LangGraph 多 Agent 状态机、多空辩论、HITL 断点、checkpointer | 中(随对投研理解加深而迭代) |
| L5 | 接口层(Interface) | 前端工作台 + SSE 实时流 + 通知送达 | 中 |

依赖方向是严格单向的:L5 依赖 L4,L4 依赖 L3,L3 依赖 L2 与 L1。任何一层都不应反向依赖上层。这条纪律保证了下层可以被独立测试和替换——比如某个数据源失效,问题被隔离在 L1 的适配器和路由里,不会污染 L4 的编排逻辑或 L3 的上下文管理。

---

## 2. 关键架构决策(ADR 摘要)

下面这张表把工作台最重要的几个"取舍点"摊开。每一行都是一个"我们本来可以选 A,但选了 B,因为……"的决策。完整的逐条 ADR 见工程 PRD 附录 A。

| 取舍点 | 选择 | 原因 | 可逆点 |
|---|---|---|---|
| Harness 与 Agent 是否解耦 | **显式三层解耦**(Harness / Agent Logic / Capability) | 模型升级时,为弥补旧模型短板而写的防护逻辑会变成纯成本;解耦后可对 harness 做加法也做减法 | 几乎不可逆,是地基 |
| 编排框架 | **LangGraph** | 生产可控性最强:显式状态机、内建 checkpointing、interrupt 支持人工介入、Send 原语并行;CrewAI 简单流 token 开销约 3 倍,AutoGen 群聊每任务 20+ 次 LLM 调用 | 退化为单 agent 可降级 OpenAI Agents SDK |
| 能力放 Skill 还是 MCP | **数据会变 → MCP;知识稳定能写下来 → Skill** | 这是 Anthropic 官方推荐范式,也是上下文治理的关键:Skill 渐进披露,MCP 工具子集化 | 边界可调 |
| 多 Agent 协作形态 | **多空辩论(Bull/Bear/Neutral)** | 纯自然语言的辩论带来相对传统量化的可解释性优势——用户能看到看多看空的理由如何碰撞 | 可增减角色 |
| 数据源策略 | **免费/开源源 + 路由 + 容灾** | MVP 阶段不自建付费源替代品;免费源的覆盖与准确性边界就是产品能力边界,对用户透明披露 | 商业化前须迁付费源 |
| 真相源数据库 | **PostgreSQL / TimescaleDB** | 时序自动分块 + 列式压缩,适合做系统真相与时序数据 | 可迁移 |
| 结构化输出 | **Pydantic + 模型原生 structured output** | 事实标准;在生成层强制 schema 最可靠,其次 tool calling,最后才退回 prompted JSON | 不可逆 |
| 人工介入 | **关键节点 HITL 断点**(估值核心假设、最终结论) | DCF 假设的合理性必须由人背书;系统不在用户确认前把 DCF 写进最终报告 | 强度可调 |

---

## 3. Harness 的八个子系统

L4 编排层背后是一套 harness(工程骨架)。它是"模型之外承载 agent 运行的一切",由八个职责单一、边界清晰的子系统组成。理解这八块,就理解了整个运行态。

第一是**会话层(Session)**,用 LangGraph 的 Postgres checkpointer 持久化状态,保证任何会话可中断、可恢复。第二是**控制平面**,负责编排循环本身——决定下一步执行哪个节点、如何恢复失败步骤。第三是**上下文构建器(Context Builder)**,负责接近窗口上限时的压缩、工具结果清理、子代理上下文隔离。第四是**工具路由器(Tool Router)**,把 agent 的动作意图分发到正确的 MCP 工具。第五是**沙箱(Sandbox)**,隔离执行不可信代码(也是未来浏览器自主抓取的落点)。第六是**凭证代理(Credential Proxy)**,守住凭证边界——agent 永远看不到数据库密码或数据源 API key,只有 MCP server 持有。第七是**追踪层(Trace)**,用 Langfuse 记录全过程。第八是**评估层(Eval)**,对结果做评判。

这套分层的价值在于每个子系统都能独立测试、独立替换。当某个数据源失效,问题被隔离在工具路由器和数据适配层,不会扩散。

---

## 4. 数据流:一次深度调研在五层之间如何流动

把抽象的分层落到一次真实调研上,数据是这样流动的。用户在 L5 输入标的并选择深度;请求连同上下文(watchlist、最近调研)发往 L4;Supervisor 解析意图,决定加载哪些 Skill(深度调研通常同时加载公司基本面、行业、估值三个主 Skill);各分析师 Agent 通过 Send 原语并行 fan-out,经 L3 的 MCP 工具触达 L2 计算与 L1 数据;估值师基于财务数据建模,在估值节点触发 HITL 断点等人工确认核心假设;多空双方就估值和前景辩论至少两轮;风控官评估尾部风险;PM 综合成稿;报告生成器产出可下载文档。整个过程中关键节点设 checkpoint(SQLite/Postgres 落盘),任何一步失败都不会让整体崩溃,已完成的工作不丢失。

---

## 5. 显式"不做"清单(范围边界)

架构里最容易被忽略、却最重要的一部分,是明确写下"我们现在不做什么",以防范围蔓延。下列能力在当前版本被**有意推迟**,不是遗漏:

不做个性化投资建议(定位是研究效率工具,所有产出带免责声明);不做实盘交易和下单执行,不与券商交易系统对接;MVP 阶段不追求毫秒级 tick 数据,分钟级足够;不自建付费数据源的替代品;Watchlist 定时调研与告警在路线图里属较后阶段(这一点与拍我分享会揭示的"常驻态"使用模式存在张力,见增强 PRD 的讨论,但当前版本仍按既定优先级推进)。

---

## 6. 与 agent/ 那条线的关系

本工作台与 `agent/`(卫星互联网产业决策辅助 Agent)是"同源异市"的两个项目:共享暗色金调的视觉系统(Fraunces + Inter Tight + JetBrains Mono),共享"判断+建议优于汇总"的产品哲学,但面向不同市场、有不同后端,**共享品牌而不共享代码**。两条线的架构文档可以互相参照:agent 那条线的 `agent/docs/architecture.md` 与本文档是平行关系。

---

> **免责声明** — 本文档及其所属系统的所有产出仅用于研究效率提升与教育目的,不构成任何投资建议。架构决策可能随团队规模、外部依赖、模型能力演进而调整,所引技术基准为 2025–2026 年快照,实施前请核对官方文档。
