Dexter 全面解读:从零到一的 AI 研究代理平台(含架构设计、工具生态与扩展开发)
posts posts 2026-03-26T16:15:00+08:00系统学习 Dexter 项目全部中文文档,涵盖:多模型路由、金融工具链、网页工具、技能系统、持久记忆、WhatsApp 网关、心跳与定时任务、Agent 循环机制、扩展开发与故障排查的完整技术指南。技术笔记AI Agent, 自动化Dexter 全面解读:从零到一的 AI 研究代理平台(含架构设计、工具生态与扩展开发)
预计阅读时间:60 分钟 | 难度:⭐⭐⭐⭐
目标读者:AI 开发者、金融科技研究者、想在本地搭建 Agent 系统的用户
概述:Dexter 解决什么问题
Dexter 是一个运行在终端的自主金融研究代理。它的定位和 Claude Code 相似:Claude Code 替程序员改代码、跑命令,Dexter 替研究者拆解问题、查数据、汇总结论,只是专业方向落在金融研究上。
为什么需要它,而不是直接问一个对话模型?模型给出的回答依赖训练数据,时效性有限,也难以验证来源。Dexter 不同——它把一次提问当成一次“研究”:先拆成执行步骤,再用实时行情、财报文件、网页搜索这些真实工具逐项执行,反复核对,直到给出有依据的结论。它留下的不是一段“看起来像答案”的文字,而是可以逐条回溯的执行记录。
一点溯源:Dexter 由开发者 virattt 发起。本文以社区 fork 仓库 A1pha3/dexter 为准——它在主线基础上同步能力,并附带了完整的中文文档集,后文内容均对应当前仓库代码与这份文档。
能力全景
Dexter 的能力可以拆成 8 个子系统,模型层先按下不表,单独在架构一节讲:
| # | 子系统 | 核心能力 | 代表工具 / 组件 |
|---|---|---|---|
| 1 | 多模型路由 | 8 家提供商统一接入 | OpenAI、Anthropic、Google、xAI、Moonshot、DeepSeek、OpenRouter、Ollama |
| 2 | 金融工具链 | 财报、价格、新闻、筛选 | get_financials、get_market_data、read_filings、stock_screener |
| 3 | 网页工具 | 搜索、抓取、渲染 | web_search、web_fetch、browser |
| 4 | 文件系统 | 本地文件读写编辑 | read_file、write_file、edit_file |
| 5 | 技能系统 | 可复用工作流 | skill(读取 SKILL.md) |
| 6 | 持久记忆 | 跨会话知识积累 | memory_search、memory_get、memory_update |
| 7 | WhatsApp 网关 | 消息通道接入 | 自聊模式、群聊模式 |
| 8 | 自动化引擎 | 心跳监控 + 定时任务 | heartbeat、cron |
记住这张表的目的是建立“什么问题该找哪个工具”的判断,而不是背工具名。后面各节会解释每个子系统为什么这样设计。
快速入门
动手之前,先确认一套可运行的环境。Dexter 用 Bun(v1.0 及以上)作为运行时,配套的 playwright 会随安装一并拉取。
前置条件
- 安装了 Bun 运行时
- 至少一个模型提供商 API Key(默认 OpenAI)
- (强烈建议)Financial Datasets 的 API Key,用于金融数据
- (强烈建议)一个搜索服务 Key:Exa(首选)、Perplexity 或 Tavily
安装与配置
# 1. 安装依赖(包含 playwright chromium)
bun install
# 2. 生成 .env 并填入必需项
cp env.example .env
# 至少填写:
# OPENAI_API_KEY=your-key
# FINANCIAL_DATASETS_API_KEY=your-key(强烈建议)
# EXASEARCH_API_KEY=your-key(强烈建议)# 3. 启动 CLI 交互模式
bun run start开发时可用 bun run dev 进入带热更新的 watch 模式。
验证能跑起来
启动后,用一条能命中金融工具的最小问题验证,例如:
Tesla 最近一季的营收是多少?观察作答过程中是否调用了 get_financials 或 get_market_data。如果只返回一个没有数据来源的普通回答,说明对应工具没有真正启用,先回到 §故障排查。
系统架构:六层协同设计
分层总览
┌─────────────────────────────────────────────────────────────┐
│ 入口层 │
│ src/index.tsx、src/gateway/index.ts │
├─────────────────────────────────────────────────────────────┤
│ 交互层 │
│ CLI 终端 UI、输入历史、状态显示 │
├─────────────────────────────────────────────────────────────┤
│ 代理层 │
│ 规划、迭代执行、上下文管理、工具协同 │
├─────────────────────────────────────────────────────────────┤
│ 模型层 │
│ 多提供商适配、调用路由、重试策略 │
├─────────────────────────────────────────────────────────────┤
│ 工具层 │
│ 金融工具、网页工具、文件工具、自动化工具、记忆工具 │
├─────────────────────────────────────────────────────────────┤
│ 扩展能力层 │
│ 技能系统、记忆系统、网关系统、调度系统 │
└─────────────────────────────────────────────────────────────┘下面自上而下拆开讲每一层,重点放在“为什么这样设计”。
模型层:前缀路由
模型层维护一份统一的提供商注册表(src/providers.ts)。关键设计是按模型名前缀判断提供商,而不是先让用户选提供商、再选模型:
| 提供商 | 模型名前缀 | 对应 API Key |
|---|---|---|
| OpenAI | 无前缀(如 gpt-5.4) | OPENAI_API_KEY |
| Anthropic | claude- | ANTHROPIC_API_KEY |
gemini- | GOOGLE_API_KEY | |
| xAI | grok- | XAI_API_KEY |
| Moonshot | kimi- | MOONSHOT_API_KEY |
| DeepSeek | deepseek- | DEEPSEEK_API_KEY |
| OpenRouter | openrouter: | OPENROUTER_API_KEY |
| Ollama | ollama: | 无需云端 Key |
两个值得注意的细节:
- 部分提供商定义了
fastModel,为摘要、快速分类这类低成本轻量场景预留了优化空间。 - 对 Anthropic,系统提示会被显式标记为
cache_control: ephemeral。原因是系统提示很长——包含工具描述、技能元数据、记忆信息和频道约束——缓存前缀能明显降低重复输入的云上成本。
工具层:工具装配原则
工具层有一个容易被忽略的设计约束:只把“当前真的能用”的工具暴露给模型。
原因在代理机制。Agent 的规划来自系统提示,如果系统提示列出它根本没法调用的工具,模型就会据此做出错误的计划——体验比“压根不展示这个工具”更差。这个原则直接决定了游戏规则:
- 对用户:先确认问题与工具职责是否匹配,再决定措辞。
- 对开发者:新增工具时,除了实现功能,还要写清楚 rich description。工具描述本身就是代理行为的一部分,不是附属注释。
代理层:Agent 循环与上下文
代理层是研究过程发生的核心,完整链路见下一节《Agent 循环机制》。
扩展能力层:四件事各司其职
技能、记忆、心跳、定时任务这 4 个概念容易被混为一谈,职责其实不同:
| 能力 | 作用 |
|---|---|
| 技能 | 提供专业工作流说明(如 DCF 估值) |
| 记忆 | 保存用户长期信息和历史上下文 |
| 心跳 | 按周期检查一份监控清单 |
| 定时任务 | 创建通用计划任务,触发时执行 Agent 询问 |
技能系统工作流
技能的存在是为了让复杂方法论可沉淀、可复用,而不是每次从零解释:
1. 发现 → 扫描包含 SKILL.md 的目录
2. 暴露 → 仅注入技能名称和描述到系统提示
3. 按需 → Agent 匹配后调用 skill 工具
4. 执行 → 返回技能正文,解析相对路径Agent 循环机制
用户输入 → CLI 接收 → Agent.create() 初始化
↓
构建系统提示(工具 + SOUL.md + 记忆 + 技能元数据)
↓
模型生成响应 → 判断是否有工具调用
↓
执行工具 → 结果写入 scratchpad
↓
上下文超限?→ 触发清理(先清最早工具结果)
↓
更高压力?→ 触发 memory flush
↓
收敛后生成最终答案 → 返回给用户这串流程描述的是迭代执行。肉眼可见的代价是:一次研究可能来回执行多轮工具调用,比“问一句答一句”慢。换取的是回答能引用真实数据、能自我核对。
金融研究工作流
Dexter 的差异点在于金融。好的研究提问,通常同时具备四个要素:对象、时间范围、判断维度、期望输出。
先看一个反例——它太单薄,工具很难据此拆出有价值的研究步骤:
Compare Apple and Microsoft on revenue growth, operating margin,
and free cash flow trend over the last 5 years.What is Tesla's latest revenue?再看一个更完整的研究提示词,它隐含了“拆步骤 + 给结论”的要求:
What does Tesla's latest revenue, gross margin, and operating income
suggest about demand quality and pricing power?对象 + 时间范围 + 比较维度 + 目标判断 + 期望输出格式区别在于:前者只要“查个数”,后者要“基于多个指标做判断”。研究价值来自后者。
金融工具如何分工
get_financials:财务、指标、估值、分析师预期类问题——营收利润现金流趋势、财务比率、估值指标。get_market_data:价格、新闻、市场动态、内幕交易等更偏“市场表层状态”的问题。read_filings:读 SEC 原始文件,适合对 10-K、10-Q、8-K 做文本层研究。有些结论不能只靠结构化指标得出,必须回到公司自己披露的文本。stock_screener:按条件筛选股票,而不是研究某个单一对象。
网页工具如何分工
web_search:通用网页搜索。只要 Exa、Perplexity、Tavily 中任一可用,就以同一个名字暴露,把供应商差异挡在规划层之外。web_fetch:抓取页面正文。当搜索结果标题已足够回答时,不必再抓全文。browser:处理依赖 JavaScript 渲染或交互的页面,比如需要点击、滚动、访问单页应用的场景。不要默认全用它——成本更高、更慢、失败面更多,系统提示也要求仅在必要时使用。
一个更普遍的判断:
get_financials管“公司基本面”,get_market_data管“市场和价格”,read_filings管“原始披露文本”。问之前先想清楚你的问题落在哪一层。
WhatsApp 网关
Dexter 可以通过 WhatsApp 接收消息并回传结果,把你从终端里解放出来。官方文档支持两种形态:自聊模式和群聊模式。
快速接入:
# 1. 扫码绑定你的 WhatsApp 账号
bun run gateway:login
# 2. 启动网关
bun run gateway自聊模式:打开 WhatsApp,在和自己聊天的会话里发问题,Dexter 处理完后就回发到同一个会话。
详细的配置项和排错步骤,见 WhatsApp 网关的独立 README。
心跳与定时任务
这两套机制让 Dexter 从“被动等待提问”变成“主动汇报”。
heartbeat:周期性检查
用一份监控清单驱动,按周期检查一次状态。适合“每天盯一眼这几个标的”这类固定监控。
cron:定时任务
三个 kind 也覆盖了三种最常见的定时需求:
// 一次性时间点
{ "kind": "at", "at": "2026-04-01T14:00:00Z" }
// 固定间隔
{ "kind": "every", "everyMs": 3600000 }
// Cron 表达式 + 时区
{ "kind": "cron", "expr": "0 9 * * 1-5", "tz": "America/New_York" }cron 触发时执行一次 Agent 询问,适合在固定时刻(如开盘前)生成一次研究结果。
调试:scratchpad
Dexter 把每次执行都记录成 scratchpad,方便复查数据来源——这也是它“可追溯”逻辑的来源。每条查询在 .dexter/scratchpad/ 下生成一个 JSONL 文件:
.dexter/scratchpad/
├── 2026-01-30-111400_9a8f10723f79.jsonl
├── 2026-01-30-143022_a1b2c3d4e5f6.jsonl
└── ...每条 JSONL 记录三类事件:
init:原始提问tool_result:工具调用、入参与原始返回thinking:Agent 的推理步骤
例如:
{"type":"tool_result","timestamp":"2026-01-30T11:14:05.123Z","toolName":"get_financials","args":{"query":"Compare Apple and Microsoft revenue growth over the last 5 years"},"result":{"data":{...},"sourceUrls":["https://financialdatasets.ai/..."]}}排查问题时,先看某次回答引用的 sourceUrls,再回看当时的 init 与 tool_result,就能判断是数据源问题、工具问题还是提问本身的问题。
故障排查
从高频到低频,按这个顺序排查:
1. 检查 .env 是否缺少关键 Key
2. 重新运行 bun install(确认依赖完整)
3. 重新启动 CLI 或网关
4. 用一条最小可验证问题重试
5. 必要时重建网关登录状态常见判断:
- 回答里只有模型自述、看不到数据来源 → 对应工具没有真正启用,检查该提供商的 API Key。
- 网页结果为空 → 检查搜索服务是否配了某一家的 Key;
web_search只要三家之一可用就会暴露。 - WhatsApp 收不到回复 → 先确认扫码登录状态,再检查自聊/群聊模式配置。
扩展开发
给 Dexter 加能力,核心是熟练使用两条接入路径:新增工具和新增技能。这不是把两个无关的方法并列——工具补“单一能力”,技能沉淀“整套工作流”。
开发前先回到《工具装配原则》:新增工具必须写清 rich description,因为它直接参与 Agent 的规划。技能则以提供专业工作流说明为主(如 DCF 估值),让复杂方法论能复用。
完整的接入方法、评估与发布边界,见官方文档的《开发与评估》《新增工具与技能》。
常见问题
Dexter 和直接问“GPT”有什么区别?
直接问对话模型,回答依赖训练知识且难溯源;Dexter 用真实工具逐项执行,结果可回溯、可核对。代价是更慢、更绕。
我该用哪个模型?
默认 OpenAI;任务重推理可切 Anthropic/DeepSeek,本地敏感场景可切 Ollama。选型参考“按模型名前缀路由”一节。
为什么不能强制 Dexter 用某个工具?
可以靠提问措辞引导,但最终由代理决定。更可靠的做法是把任务目标写清楚,而不是替它做所有规划。
技能、记忆、心跳、定时任务是一回事吗?
不是。看“四件事各司其职”表格,它们分别管工作流、信息记忆、周期检查、计划触发。
延伸阅读
- Dexter GitHub:A1pha3/dexter(fork 自 virattt/dexter,附中文文档集)
- 中文文档中心:docs/cn
- 系统架构详解:system-architecture.md
- Agent 循环机制:agent-loop-and-context.md
- 新增工具与技能:adding-tools-and-skills.md
参与讨论
使用 GitHub 登录。欢迎补充事实、异议与实践。
讨论暂时无法加载。