首页
/ DeerFlow 前端工程开发指南:基于 `frontend/AGENTS.md` 的架构、命令体系与 AI Agent 协作规范

DeerFlow 前端工程开发指南:基于 `frontend/AGENTS.md` 的架构、命令体系与 AI Agent 协作规范

2026-09-07 09:24:41作者:滕妙奇

导读:DeerFlow 的前端是一个基于 Next.js 16 构建的 Agent 系统 Web 界面,通过 LangGraph SDK 与后端进行线程化对话、流式响应与制品(artifact)交互。本文以 frontend/AGENTS.md 为骨架,系统梳理其架构分层、源码目录约定、完整命令体系、Rstest/Playwright 双轨测试策略、环境变量与代理配置,以及为 AI 编码助手(Claude Code、Codex 等)设计的协作规范。读完你不仅能快速上手 pnpm dev,还能理解每个目录、每条命令、每个测试文件背后的设计意图,具备独立向该工程提交高质量改动、或为其他 Agent 工程撰写同类开发指引的能力。

一、AGENTS.md 是什么:AI 协作的唯一事实来源

在 DeerFlow 仓库中,frontend/AGENTS.md 并不仅是一份人类开发者阅读的 README。它的核心定位在文档首段即被点明:

它为 AI 编码 Agent(Claude Code、Codex 及其他)在操作 DeerFlow 前端时提供指引,是"唯一事实来源"(source of truth);同目录的 frontend/CLAUDE.md 仅通过 @AGENTS.md 将其导入。

这一设计解决了多 Agent 协作场景下的文档同步难题:指引只维护一份,Claude Code 用 CLAUDE.md 作为入口、Codex 与通用 Agent 直接读取 AGENTS.md,二者指向同一份内容,避免多份文档漂移失同步。若你以 AI Agent 身份在本工程内开发,第一件事就是完整通读该文件;若你是维护者,也应遵循其"贡献规范"一节的约定,在架构、命令或约定变化时同步更新它(详见后文)。

从仓库结构看,这一"分层指引"思路被延续到了更深一层:frontend/AGENTS.md 明确写到 src/ 下存在更细粒度的 frontend/src/AGENTS.md,将本文件中的前端各分区再行拆分,供聚焦某目录开发时按需查阅。

二、项目概览:一个"有状态对话"式 Agent Web 界面

2.1 它在整个系统中扮演的角色

DeerFlow 前端是一个面向 AI Agent 系统的 Web 界面,它并不自行驱动 Agent,而是通过 LangGraph SDK 与基于 LangGraph 的后端通信,对外提供:

  • 基于线程(thread)的 AI 对话:创建会话、发送消息、接收流式响应;
  • 线程级 /goal 完成条件:用户可为单个线程设定完成目标并跟踪其状态;
  • 制品(artifacts):后端 Agent 产出的文件/代码等,前端负责展示与管理;
  • 技能与工具(skills/tools)系统 的交互入口。

文档给出了一幅非常凝练的架构图:

Frontend (Next.js) ──▶ LangGraph SDK ──▶ LangGraph Backend (lead_agent)
                                              ├── Sub-Agents
                                              └── Tools & Skills

即前端是"瘦客户端":它只负责编排对话、渲染流式结果;真正的 Agent 编排、工具调用、技能执行都发生在后端的 lead_agent 及其子 Agent 中。这也解释了为什么前端核心代码(src/core/)里大量模块都与"如何调用后端 API、如何解析流式事件、如何恢复线程状态"相关。

2.2 技术栈与版本要求

文档明确列出了当前栈及运行前提,这些信息与 frontend/package.json 中的声明相互印证:

类别 版本 / 要求 说明
框架 Next.js 16(package.json 中为 next@^16.2.11 App Router 架构,含 i18n 与 rewrites
UI 框架 React 19react@^19.0.0 服务端组件与客户端组件混用
语言 TypeScript 5.8typescript@^5.8.2 tsc --noEmit 做类型检查
样式 Tailwind CSS 4tailwindcss@^4.0.15 v4 @import 语法 + CSS 变量主题
包管理 pnpm 10.26.2packageManager 字段锁定) workspace 内安装使用 pnpm
运行时 Node.js 22+、pnpm 10.26.2+ 低于该版本可能无法正常构建

2.3 核心依赖及其分工

frontend/AGENTS.md 强调的四组核心依赖,构成了应用的能力底座:

依赖 版本 职责
@langchain/langgraph-sdk ^1.5.3 Agent 编排与流式通信的唯一通道(连接后端)
@langchain/core ^1.1.15 LangChain/LangGraph 的基础类型与构建块
@tanstack/react-query ^5.90.17 服务端状态管理(请求缓存、失效、重试)
UI 体系 Shadcn UI、MagicUI、React Bits、Vercel AI SDK 组件全部由 registry 自动生成,禁止手改

结合 frontend/src/core/api/index.ts(重新导出 api-client)以及 frontend/src/core/api 目录下的 api-client.tsstream-mode.tsfetcher.ts 等文件可以看出,"LangGraph 客户端单例"是被 core/ 各业务域(threads、artifacts、memory…)共享的底层设施;core/api 之上才是一个个业务领域模块。

三、源码布局(src/):按领域组织而非按类型组织

这是整个工程最值得学习的部分。frontend/AGENTS.md 给出的目录约定打破了常见"全部放 components/ 下"的写法,改用领域化 + 少量共享层结构:

顶层目录 内容与职责
app/ Next.js App Router 页面与 API Route Handlers
components/ React 组件,其中 ui/(Shadcn)与 ai-elements/(Vercel AI SDK)自动生成、ESLint 忽略、禁止手改workspace/(聊天页组件)、landing/(落地页)、docs/(MDX 渲染组件)为手写
core/ 业务逻辑核心。文档列举了大量领域:threads/(创建/流式/状态)、api/(LangGraph 客户端单例)、agents/(自定义 Agent)、subagents/(运行时 worker 目录与管理变更)、auth/artifacts/channels/(IM 连接)、integrations/(Lark CLI 等托管三方集成)、i18n/(en-US、zh-CN)、memory/skills/messages/mcp/models/input-polish/(发送前草稿改写 API)、voice-input/(浏览器语音识别)、suggestions/tasks/todos/tools/workspace-changes/(run 级变更文件摘要与 diff 拉取)、config/notification/blog/ 等,另有 rehype/streamdown/ 渲染助手与 utils/
hooks/ 共享 React Hooks
lib/ 工具函数,如由 clsx + tailwind-merge 实现的 cn()
content/ MDX 内容(博客、文档),由应用渲染
styles/ 全局 CSS:Tailwind v4 @import + CSS 变量主题
typings/ 环境(ambient)TypeScript 声明

根级还有两个关键文件:frontend/src/env.js(环境变量校验,详见第六节)与 mdx-components.ts(MDX 组件映射)。

从实际目录看(如 frontend/src/core 下存在 threads/channels/memory/skills/mcp/scheduled-tasks/subagent-batches/ 等),文档所述与仓库实现一致。这种"核心代码与页面解耦"的布局,使单元测试可以纯粹针对 core/ 逻辑运行而无需渲染 DOM(对应下文 Rstest 的 node 环境设计)。

3.1 app/ 下的主要路由

文档详列了 App Router 中的关键路由,据此可快速定位页面代码:

  • / —— 落地页(landing);
  • /showcase/[thread_id] —— 白名单公开的只读演示页;
  • /workspace/chats/[thread_id] —— 需要认证的聊天工作台(实际路径见 frontend/src/app/workspace/chats);
  • /workspace/agents/[agent_name]/workspace/agents/new —— 自定义 Agent 的查看与新建;
  • /artifacts/view —— 无浏览器镶边(chrome-free)的窗口,用面板自带渲染器渲染单个 Markdown 制品;
  • /blog/…/[lang]/docs/… —— 博客与多语言文档站;
  • (auth)/{login,setup,auth/callback} —— 登录、初始化与 OAuth 回调流;
  • /api/… Route Handlers(例如 /api/memory)。

四、命令体系:从开发到发布的完整脚本

frontend/AGENTS.md 的 Commands 表与 frontend/package.json 的 scripts 一一对应,是前端开发最常用的操作入口:

命令 作用 备注
pnpm dev 启动开发服务器 默认使用 Webpack 打包
pnpm build 生产构建(next build 文档额外指出可用 NEXT_CONFIG_BUILD_OUTPUT=standalone 产出 standalone 产物
pnpm check Lint + 类型检查eslint . && tsc --noEmit 提交前必跑
pnpm lint 仅 ESLint
pnpm lint:fix ESLint 自动修复
pnpm format Prettier 检查 实际应用用 pnpm format:write
pnpm test Rstest 单元测试
pnpm test:e2e Playwright E2E(Chromium)
pnpm typecheck tsc --noEmit
pnpm start 启动生产服务器

两个值得注意的工程化细节:

  1. 开发期默认用 Webpack。当需要诊断本地 Next.js 打包器问题时,可通过环境变量 DEER_FLOW_DEV_BUNDLER=turbo 搭配 pnpm dev 临时切到 Turbopack。这避免了"默认开启 Turbopack 导致难以复现 Webpack 场景问题"的调试困境——把非默认打包器当作诊断手段而非默认值。
  2. pnpm check 是提交闸门。它把 ESLint 与全量类型检查串成一条命令,配合贡献规范中"提交前运行"的要求,保证任何 Agent 改动在进入仓库前先过静态检查。

五、双轨测试策略:Rstest 单元测试 + Playwright E2E

DeerFlow 前端的测试体系设计得很克制:能用纯逻辑测试就不渲染 DOM,能 mock 后端就不起真服务。理解这一原则,才能正确地把测试写进正确的轨道。

5.1 Rstest:按环境拆分两个 project

单元测试位于 tests/unit/目录结构镜像 src/(例如 tests/unit/core/api/stream-mode.test.ts 测试 src/core/api/stream-mode.ts),通过 @/ 路径别名导入被测源码。

Rstest 在 frontend/rstest.config.ts 中定义了两个 project,这是理解整个单测体系的关键:

project 环境 匹配文件 适用对象
node node *.test.ts / *.test.tsx 纯逻辑测试,几乎覆盖全量套件
dom happy-dom *.dom.test.ts / *.dom.test.tsx 需要 document 的测试

两类文件的命名规则本身就是一种声明

  • 需要真实 React 行为(effect 顺序、卸载清理、store 变化触发重渲染)的 Hook,通过 @testing-library/reactrenderHook 驱动,必须放入 .dom.test.* 文件,而不是在 node 测试里 mock react
  • 需要渲染组件的测试同理。

设计动机在文档与配置注释中都写得很直白:DOM 环境的运行开销约为 node 套件的 3 倍,因此凡不渲染的测试都不应"升舱"到 DOM 环境。把测试成本显式写进工程文档,能让后续贡献者自动形成"默认纯逻辑、按需 DOM"的成本意识。

配置中还有一个值得借鉴的细节:bundleDependencies: ["streamdown", "katex"] —— 因为 Streamdown 会以副作用形式引入 KaTeX CSS,打包这两个依赖可让 Rsbuild 处理该 CSS 导入,而不是让 Node 直接加载它。

5.2 Playwright E2E:全量 mock 后端

E2E 测试位于 tests/e2e/,由 frontend/playwright.config.ts 驱动:

  • 仅 Chromium 桌面浏览器 project;
  • 通过 page.route() 网络拦截 mock 全部后端 API,测试真实页面交互(导航、聊天输入、流式响应),因此 E2E 无需真实后端即可稳定运行;
  • webServer 默认执行 next build && next start,并注入 SKIP_ENV_VALIDATION=1DEER_FLOW_AUTH_DISABLED=1 环境变量(跳过环境变量校验、关闭认证,专为测试铺路);
  • 支持 PLAYWRIGHT_BASE_URL 指向已运行服务,以及 PLAYWRIGHT_SKIP_WEB_SERVER=1 跳过内置启动;
  • CI 下 workers=1、失败重试 2 次、使用 github reporter;本地默认 html reporter,trace: "on-first-retry" 便于诊断。

这条"E2E 也 mock 后端"的路线与架构一致:前端真正需要自证的是"页面逻辑与流式渲染正确",而不是后端的真实行为——后者属于后端 E2E 的职责边界。

六、环境变量与网络配置:nginx 优先、直连兜底

前端环境配置体现了"生产默认走反代、开发可直连"的哲学,是排查"页面不响应"类问题时的必读内容。

6.1 两个可选的 API 地址

NEXT_PUBLIC_BACKEND_BASE_URL=http://localhost:8001
NEXT_PUBLIC_LANGGRAPH_BASE_URL=http://localhost:8001/api

文档明确指出这两个变量可以留空:标准 make dev / Docker 流程中,nginx 对外提供 /api/langgraph/* 公共前缀并改写转发到 Gateway 的原生 /api/* 路由,因此本地开发无须手工配置。从 frontend/next.config.jsrewrites() 实现可以印证这一设计:

  • NEXT_PUBLIC_LANGGRAPH_BASE_URL 未设置时,把 /api/langgraph/api/langgraph/:path* 重写到内部网关地址;
  • NEXT_PUBLIC_BACKEND_BASE_URL 未设置时,把 /api/agents/api/skills 以及其余全部网关 API(models、threads、memory、mcp、artifacts、uploads、suggestions、runs 等)通过 /api/:path* 兜底重写;
  • 内部网关默认取 DEER_FLOW_INTERNAL_GATEWAY_BASE_URL,缺省回退到 http://127.0.0.1:8001
  • 注释特别提醒:LangGraph 兼容路由的 rewrite 必须排在网关原生 /api/:path* 兜底之前,以保持其公共前缀。

也就是说:变量一旦显式设置,前端便绕过 nginx/rewrite 直连指定后端;否则全部请求收敛到 Next 的 rewrites 层。排查"登录后无响应"等联通问题时,先分清请求走的是反代还是直连。

6.2 环境变量校验(t3-env + zod)

frontend/src/env.js 基于 @t3-oss/env-nextjs 与 zod 对服务端、客户端变量做 schema 校验:

  • 服务端:GITHUB_OAUTH_TOKENNODE_ENV(枚举 development/test/production);
  • 客户端(NEXT_PUBLIC_* 前缀才能暴露给浏览器):NEXT_PUBLIC_BACKEND_BASE_URLNEXT_PUBLIC_LANGGRAPH_BASE_URLNEXT_PUBLIC_STATIC_WEBSITE_ONLY
  • 通过 SKIP_ENV_VALIDATION 可跳过校验(Docker 构建场景);
  • emptyStringAsUndefined: true —— 空字符串按未定义处理,避免 '' 误触发必填校验。

6.3 DEER_FLOW_DEV_ALLOWED_ORIGINS:非 localhost 开发的关键

当开发服务器需通过局域网地址或反向代理主机名访问(而非 localhost)时,必须设置:

DEER_FLOW_DEV_ALLOWED_ORIGINS=192.168.1.20,my-proxy.internal

(逗号分隔;填写完整 URL 也会被自动规约为纯 host。)它喂给 Next 的 allowedDevOrigins,用于门控 /_next/*、字体与 HMR 资源。缺少它会发生什么? 这些资源请求返回 403,页面虽完成 SSR 但永远无法水合(hydrate)——页面看起来渲染了,但包括登录表单在内的所有交互都无响应。

其解析逻辑在 frontend/src/dev-origins.js 中实现得相当细致:normalizeHost() 会剥离 scheme、去掉 /? 后的路径段、单独处理 IPv6 括号字面量,且只在恰好一个冒号(host:port)时剥离端口,避免误伤裸 IPv6。注释点明了陷阱:Next 只按 host 匹配,带 scheme/端口/路径的条目无法命中任何请求。同时该配置仅开发期生效,生产构建会忽略它——这是一个应当写进任何 Agent 工程"常见坑"清单的配置。

七、代码风格约定:让 AI Agent 产出可预测的代码

frontend/AGENTS.md 的 Code Style 一节短小但对 Agent 极其关键——它把审美问题转化为可执行的机械规则:

约定 规则
导入顺序 builtin → external → internal → parent → sibling,组内按字母序,组间空行
类型导入 使用内联类型导入:import { type Foo }
未使用变量 前缀 _ 显式声明"有意不用"
条件类名 cn()(来自 @/lib/utils,封装 clsx + tailwind-merge)
路径别名 @/* 映射 src/*
生成组件 ui/ai-elements/ 由 Shadcn、MagicUI、React Bits、Vercel AI SDK 的 registry 生成,不要手改(二者也被 ESLint 忽略)

对 AI 编码助手而言,这些规则直接决定了 diff 是否可被人类审查者接受;尤其"生成组件不改、导入分组有序"两条,能显著减少 Agent 改动带来的无谓冲突。

八、贡献规范与前端资源预算门禁(pnpm perf:check

文档给出了向 DeerFlow 前端添加功能的标准动作序列,这本质上也是 AI Agent 的"开发流程 checklist":

  1. 遵循既有的 src/ 结构(新业务逻辑进 core/ 对应领域);
  2. 补充 TypeScript 类型与完善的错误处理;
  3. tests/unit/ 写单测(pnpm test),在 tests/e2e/ 写 E2E(pnpm test:e2e);
  4. 提交前运行 pnpm check
  5. 当架构、命令或约定变化时同步更新本文档(AGENTS.md 自身处于版本管理之下)。

一个容易被忽视的高价值命令是 pnpm perf:check(对应 package.json 中 node scripts/measure-route-assets.mjs --check)。文档说明了它的完整机制:

  • 从一个正常生产构建开始测量 /login
  • 再以 static-demo 模式构建由 fixture 支撑的 workspace 路由;
  • 在临时本地端口启动生产服务器,测量代表性路由实际引用的唯一 JavaScript 与 CSS 文件
  • 详细结果写入 .next/performance-results.json
  • 将总计与 frontend/performance-budgets.json 中的预算(例如 /login 的 CSS 170KB / JS 850KB,/workspace/chats 的 CSS 190KB / JS 1750KB,deep chat 页 JS 上限 4100KB)比对,失败即告警。

文档给出的处置原则是:预算失败时应修复路由归属或代码拆分点,而不是上调上限;确需提高上限,必须记录并评审被实测出的劣化回归。这种"预算文件 + 归因命令 + 升级审批"的组合,比单纯口头要求"注意包体积"可靠得多,是值得在文章里单独强调的工程实践。

九、为贡献者与 Agent 提炼的实用清单

综合 frontend/AGENTS.md 全篇,可沉淀出四条在 DeerFlow 前端高效工作的实用结论:

  1. 先读文档再动手:AGENTS.md 是唯一事实来源,src/AGENTS.md 提供分区细节;架构演进时这些文档会被要求同步更新。
  2. 按域落代码、按需选测试环境:业务逻辑进 core/ 对应领域;不渲染的测试写 *.test.ts(node),涉及真实 React 行为的 Hook/组件才写 *.dom.test.ts(happy-dom),E2E 一律 mock 后端。
  3. 提交前跑 pnpm check,预算靠 pnpm perf:check:前者拦静态错误,后者拦路由体积劣化。
  4. 联通问题先查环境:默认反代路径下不需要设置任何 NEXT_PUBLIC_*;一旦页面 SSR 成功却无法交互,优先检查是否为非 localhost 访问且缺少 DEER_FLOW_DEV_ALLOWED_ORIGINS 所致(403 水合失败);相关校验入口见 frontend/src/env.jsfrontend/src/dev-origins.js

若需进一步理解后端侧能力,可继续阅读 backend/docs/API.mdbackend/docs/ARCHITECTURE.md,结合本仓库根目录 frontend/README.md 与本篇共同构成 DeerFlow 前端的完整认知地图。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.81 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
920
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.79 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
390