DeerFlow 前端智能体协作体系解析:基于 CLAUDE.md 与 AGENTS.md 的工程规范、测试架构与开发实战 DeerFlow 前端智能体协作体系解析基于 CLAUDE.md 与 AGENTS.md 的工程规范、测试架构与开发实战【免费下载链接】deer-flowAn open-source long-horizon SuperAgent harness that researches, codes, and creates. With the help of sandboxes, memories, tools, skill, subagents and message gateway, it handles different levels of tasks that could take minutes to hours.项目地址: https://gitcode.com/GitHub_Trending/de/deer-flow本篇围绕 frontend/CLAUDE.md 这一前端智能体入口文档展开讲解 DeerFlow开源长周期 SuperAgent 框架前端如何以一份共享的AGENTS.md作为唯一事实来源统一 Claude Code、Codex 等编码智能体的协作规范。读完你将掌握 DeerFlow 前端完整的技术栈、命令体系、Rstest 双项目单测架构、Playwright E2E 方案、路由重写与环境配置原理以及基于performance-budgets.json的路线资产预算机制能够直接照此规范参与该项目的开发与智能体辅助编码。CLAUDE.md一个共享智能体指南的导入式入口frontend/CLAUDE.md 全文只有五行其核心设计是一行导入指令The frontend agent guidance lives in [AGENTS.md](https://link.gitcode.com/i/c7cca5fce93011bc93d1aa4a43455f61) so it is shared across coding agents (Claude Code, Codex, and others). Claude Code imports it below. AGENTS.md这是多智能体协作仓库中一个值得借鉴的模式CLAUDE.md不再承载任何独立内容而是通过 Claude Code 的file导入语法引用同目录的 frontend/AGENTS.md。带来的好处有三点单一事实来源Single Source of TruthAGENTS.md明确声明 It is the source of truth; the siblingCLAUDE.mdimports it viaAGENTS.md。所有编码智能体Claude Code、Codex 以及其他支持 AGENTS.md 约定的工具读到的是同一份规范避免了CLAUDE.md 一套说法、其他智能体另一套说法的分叉风险。维护成本减半规范演进只需修改AGENTS.md一处贡献流程中也有对应要求——Update thisAGENTS.mdwhen architecture, commands, or conventions change。分层下钻AGENTS.md末尾还指明 More specificAGENTS.mdfiles undersrc/contain the frontend sections split from this file仓库中确实存在 frontend/src/AGENTS.md承载了按数据流Data Flow、关键模式Key Patterns、交互所有权Interaction Ownership组织的更细粒度约定形成根级概览 源码级细则的两层文档结构。下文以 frontend/AGENTS.md 的原始内容为骨架逐节展开并用仓库中的真实配置文件与源码印证每一条约定的落点。项目概览与技术栈AGENTS.md对 DeerFlow 前端的定义是a Next.js 16 web interface for an AI agent system——一个与 LangGraph 后端通信、提供线程thread式 AI 对话、流式响应、制品artifacts与技能/工具系统的 Web 界面。官方声明的完整技术栈为Next.js 16、React 19、TypeScript 5.8、Tailwind CSS 4、pnpm 10.26.2要求 Node.js 22 与 pnpm 10.26.2。这与 frontend/package.json 完全一致next: ^16.2.11、react: ^19.0.0、typescript: ^5.8.2、tailwindcss: ^4.0.15且文件末尾通过packageManager: pnpm10.26.2钉死了包管理器版本配合 pnpm 的 packageManager 校验机制保证团队与 CI 使用同一版本。核心依赖AGENTS.md列出的四项在 frontend/package.json 中均可对应到LangGraph SDKlangchain/langgraph-sdk^1.5.3——Agent 编排与流式通信是整个聊天界面的生命线LangChain Corelangchain/core^1.1.15——基础 AI 构件TanStack Querytanstack/react-query^5.90.17——服务端状态管理UI 层Shadcn UI、MagicUI、React Bits 与 Vercel AI SDK 元素均由注册表registry生成不手工维护。此外从依赖清单还能看到该前端的重渲染特征streamdownshikikatexrehype-*/remark-*全家桶用于流式 Markdown、代码高亮与公式渲染uiw/react-codemirror及多语言包用于制品编辑xyflow/react、gsap、motion服务于可视化与动效。这些依赖正是 frontend/src/AGENTS.md 中大量数据流约定流式 Markdown、制品自动打开、SSE 重放缺口恢复等的落地基础。命令体系一张表看懂前端日常操作frontend/AGENTS.md 给出的命令表如下已按 frontend/package.json 的scripts字段逐条核实命令用途pnpm dev启动开发服务器默认 Webpackpnpm build生产构建pnpm checkLint 类型检查提交前必跑pnpm lint仅 ESLintpnpm lint:fixESLint 自动修复pnpm formatPrettier 检查pnpm format:write写入修复pnpm test使用 Rstest 运行单元测试pnpm test:e2e使用 PlaywrightChromium运行 E2E 测试pnpm typecheckTypeScript 类型检查tsc --noEmitpnpm start启动生产服务器对照package.json有几处细节值得注意pnpm check实际是eslint . --ext .ts,.tsx tsc --noEmit的串联一条命令同时把静态检查与类型检查挡在提交之前pnpm dev并不是直接next dev而是node scripts/dev.mjs——一个自定义启动脚本用来控制开发打包器选择下文详述规范中还有一条未列入表格但同等重要的命令pnpm perf:checknode scripts/measure-route-assets.mjs --check用于执行路线资产预算检查。开发服务器为何包了一层 dev.mjsAGENTS.md指出Webpack is the default development bundler. UseDEER_FLOW_DEV_BUNDLERturbowithpnpm devto opt in to Turbopack。实现位于 frontend/scripts/dev.mjsexport function getDevBundler(_platform process.platform, env process.env) { const override env.DEER_FLOW_DEV_BUNDLER?.trim(); if (override) { if (override ! turbo override ! webpack) { throw new Error(DEER_FLOW_DEV_BUNDLER must be either turbo or webpack); } return override; } // Keep Webpack as the cross-platform default while #5132s Turbopack // PostCSS worker leak remains unfixed in a stable Next.js release. ... return webpack; }从源码可以确认两点一是DEER_FLOW_DEV_BUNDLER只接受turbo或webpack两个取值非法值直接抛错避免拼写错误静默失效二是默认走 Webpack 的原因被明确写在注释里——上游 Next.js 的 Turbopack PostCSS worker 内存泄漏问题在稳定版修复前跨平台默认值保守地选择 Webpack而保留platform参数使未来恢复平台感知默认值只需小改动。这是一种带逃生舱的默认值设计出问题时可一条环境变量切换到 Turbopack 定位是否是打包器自身的问题。单元测试架构Rstest 双项目拆分 node 与 DOMAGENTS.md对测试布局的约定是单元测试位于tests/unit/且目录结构镜像src/例如tests/unit/core/api/stream-mode.test.ts对应src/core/api/stream-mode.ts通过/路径别名导入源模块。真正有信息量的是它对环境拆分的解释原文要点是Rstest 将测试拆为两个项目运行——*.test.ts(x)在纯node环境占套件绝大部分*.dom.test.ts(x)在happy-dom环境供renderHook驱动的 hook 测试与组件测试使用DOM 环境耗时约为 node 套件的 3 倍所以不渲染的测试不应进入 DOM 环境且行为只存在于真实 React 中的 hookeffect 顺序、卸载清理、store 变更重渲染应放在.dom.test.*文件里而不是在 node 测试中 mockreact。这份解释与 frontend/rstest.config.ts 的实现对得上号const shared { plugins: [pluginReact()], resolve: { alias: { : resolve(__dirname, src) } }, output: { // Streamdown imports KaTeX CSS as a side effect. Bundle these packages so // Rsbuild processes that CSS import instead of Node trying to load it. bundleDependencies: [streamdown, katex], }, }; export default defineConfig({ projects: [ { ...shared, name: node, include: [tests/unit/**/*.test.ts, tests/unit/**/*.test.tsx], // A DOM environment costs roughly 3x the runtime of this suite, ... exclude: { patterns: [**/*.dom.test.*], override: false }, }, { ...shared, name: dom, testEnvironment: happy-dom, include: [tests/unit/**/*.dom.test.ts, tests/unit/**/*.dom.test.tsx], }, ], });三个实现细节直接印证了文档约定命名即环境node 项目显式排除**/*.dom.test.*dom 项目只 include*.dom.test.*两者互斥且完全由文件后缀决定开发者按后缀选环境零配置/别名在两个项目中一致都指向src保证测试导入与生产代码解析同一份路径bundleDependencies: [streamdown, katex]解决了一个真实痛点——Streamdown 会以副作用方式导入 KaTeX CSS若不在 Rsbuild 侧打包Node 环境会试图直接加载 CSS 文件而崩溃。E2E 测试Playwright 全量 mock 后端 真实页面交互AGENTS.md描述 E2E 策略为测试位于tests/e2e/使用 Playwright Chromium所有后端 API 通过page.route()网络拦截进行 mock测试的是真实页面交互导航、聊天输入、流式响应配置见playwright.config.ts。frontend/playwright.config.ts 给出了该策略的完整工程化细节const baseURL process.env.PLAYWRIGHT_BASE_URL ?? http://localhost:3000; const skipWebServer process.env.PLAYWRIGHT_SKIP_WEB_SERVER 1; export default defineConfig({ testDir: ./tests/e2e, fullyParallel: true, forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, reporter: process.env.CI ? github : html, timeout: 30_000, use: { baseURL, locale: en-US, trace: on-first-retry }, projects: [{ name: chromium, use: { ...devices[Desktop Chrome] } }], webServer: skipWebServer ? undefined : { command: pnpm exec next build pnpm exec next start, url: baseURL, reuseExistingServer: !process.env.CI, timeout: 120_000, env: { SKIP_ENV_VALIDATION: 1, DEER_FLOW_AUTH_DISABLED: 1 }, }, });值得点出的设计E2E 跑的是生产构建而非 dev serverwebServer.command是next build next start本地可复用已存在的服务器reuseExistingServer: !CICI 则冷启动、单 worker、失败重试 2 次并强制forbidOnly防止test.only被误提交——这是典型的本地快、CI 稳双模配置用环境变量关掉前端自身的防护注入SKIP_ENV_VALIDATION1跳过 frontend/src/env.js 的环境变量校验见下文与DEER_FLOW_AUTH_DISABLED1关闭认证让 mock 后端的页面可以直接进入受保护路由PLAYWRIGHT_SKIP_WEB_SERVER1提供了与已存在服务器协作的逃生舱trace: on-first-retry只在重试时留痕控制产物体积。由于后端被page.route()全量拦截E2E 可以在完全没有 Gateway/LangGraph 后端的情况下验证导航、输入、流式响应这条用户路径这正是AGENTS.md所称 test real page interactions 的含义。架构与源码布局AGENTS.md给出的端到端链路是Frontend (Next.js) ──▶ LangGraph SDK ──▶ LangGraph Backend (lead_agent) ├── Sub-Agents └── Tools Skills产品形态上前端是一个有状态聊天应用用户创建 thread对话、发送消息、设置 thread 级/goal完成条件接收流式 AI 响应后端编排的 agent 可以产出artifacts文件/代码、todos与 goal 状态更新。src/目录布局约定并已在仓库目录结构中核实app/— Next.js App Router。路由包括/落地页、/showcase/[thread_id]白名单内的公开只读演示、/workspace/chats/[thread_id]认证后的聊天、/workspace/agents/[agent_name]与/workspace/agents/new自定义 Agent、/artifacts/view无浏览器 chrome 的窗口用面板自己的渲染器渲染单个 Markdown 制品、/blog/…、(auth)/{login,setup,auth/callback}认证流、/[lang]/docs/…多语言文档、以及/api/…路由处理器如/api/memorycomponents/— React 组件其中ui/与ai-elements/是注册表自动生成的ESLint 忽略禁止手改workspace/是聊天页组件消息、制品、设置landing/、docs/分别对应落地页与 MDX 渲染core/— 业务逻辑核心the heart of the app。frontend/src/core 目录实测包含threads/创建、流式、状态、api/LangGraph 客户端单例、agents/、subagents/、auth/、artifacts/制品、channels/IM 连接、integrations/Lark CLI 等第三方集成、i18n/en-US、zh-CN、settings/、memory/、skills/、messages/、mcp/、models/、input-polish/发送前草稿重写、voice-input/浏览器语音识别、suggestions/、tasks/、todos/、tools/、workspace-changes/运行级变更文件摘要与 diff 拉取、config/、notification/、blog/以及渲染辅助streamdown/与utils/hooks/— 共享 React hookslib/— 工具函数clsx tailwind-merge 组合出的cn()content/— 被应用渲染的 MDX 内容博客、文档styles/— 使用 Tailwind v4import语法与主题 CSS 变量的全局 CSStypings/— 环境类型声明根文件env.js环境变量校验、mdx-components.tsMDX 组件映射。这个布局体现了清晰的表现层 / 领域层分界app/与components/只负责路由与渲染一切与 LangGraph、认证、制品相关的状态与副作用都收敛在core/下而 frontend/src/AGENTS.md 则以数据流 → 关键模式 → 交互所有权的结构把每个关键文件的职责钉死例如LangGraph client 是core/api/中通过getAPIClient()获得的单例、thread 路由必须经core/threads/utils.ts::pathOfThread()构造以正确 percent-encode 自定义 Agent 名与 thread ID供智能体与人类共同遵循。代码风格约定frontend/AGENTS.md 的四条硬性风格规则导入顺序强制builtin → external → internal → parent → sibling组内字母序组间空行类型导入使用内联形式import { type Foo }未使用变量以下划线_前缀显式声明弃用意图类名组合条件 Tailwind 类一律通过/lib/utils的cn()组合而不是字符串拼接路径别名/*映射到src/*ui/与ai-elements/来自注册表生成不要手动编辑。这些规则与测试侧的/别名配置见 frontend/rstest.config.ts保持一致意味着测试、构建、Lint 三处对模块解析的理解完全同构。环境配置可选的后端 URL、Next 重写与开发源放行后端地址是可选的默认走 nginx 代理AGENTS.md给出的两个环境变量均为可选NEXT_PUBLIC_BACKEND_BASE_URLhttp://localhost:8001 NEXT_PUBLIC_LANGGRAPH_BASE_URLhttp://localhost:8001/api原文要求标准make dev/ Docker 流程下保持它们不设置因为 nginx 会对外提供/api/langgraph/*前缀并重写到 Gateway 原生的/api/*路由。不设置时由谁兜底答案在 frontend/next.config.js 的rewrites()中——Next.js 自身也实现了一套同构代理if (!process.env.NEXT_PUBLIC_LANGGRAPH_BASE_URL) { rewrites.push({ source: /api/langgraph, destination: ${gatewayURL}/api }); rewrites.push({ source: /api/langgraph/:path*, destination: ${gatewayURL}/api/:path* }); } if (!process.env.NEXT_PUBLIC_BACKEND_BASE_URL) { // /api/agents、/api/skills 逐条重写 ... rewrites.push({ source: /api/:path*, destination: ${gatewayURL}/api/:path* }); // 兜底 }从这段源码结构看有两层设计意图其一只有当对应NEXT_PUBLIC_*变量未设置时才注入重写显式配置永远优先于内置代理其二/api/langgraph的重写必须先于/api/:path*兜底规则注释中特意强调 this must come AFTER the /api/langgraph rewrite ... so that LangGraph-compatible routes keep their public prefix while Gateway receives its native /api/* paths——即客户端继续说 LangGraph 方言前缀Gateway 收到的是原生路径。gatewayURL可经DEER_FLOW_INTERNAL_GATEWAY_BASE_URL覆盖默认http://127.0.0.1:8001。环境变量校验与 SKIP_ENV_VALIDATIONfrontend/src/env.js 使用t3-oss/env-nextjs Zod 定义校验模式服务端可选变量GITHUB_OAUTH_TOKEN、NODE_ENV枚举development/test/production默认 development客户端仅暴露带NEXT_PUBLIC_前缀的NEXT_PUBLIC_BACKEND_BASE_URL、NEXT_PUBLIC_LANGGRAPH_BASE_URL、NEXT_PUBLIC_STATIC_WEBSITE_ONLY。两个细节值得注意skipValidation: !!process.env.SKIP_ENV_VALIDATION提供了跳过开关Docker 构建场景常用emptyStringAsUndefined: true把空字符串视为未设置避免z.string()被空串击穿。这也正是 PlaywrightwebServer注入SKIP_ENV_VALIDATION1的原因见上文。DEER_FLOW_DEV_ALLOWED_ORIGINSLAN/代理场景下的开发源放行AGENTS.md描述了一个具体故障模式当开发服务器要在 localhost 之外的地址LAN 地址或代理主机名访问时必须把该 host 列入DEER_FLOW_DEV_ALLOWED_ORIGINS逗号分隔完整 URL 会被归约为主机名。它喂给 Next 的allowedDevOrigins管控/_next/*、字体与 HMR 请求——否则这些请求返回 403页面能服务端渲染但永不水合hydrate登录表单在内的一切都没有响应。仅限开发生产构建会忽略该配置。解析逻辑在 frontend/src/dev-origins.js并被 frontend/next.config.js 以allowedDevOrigins: getAllowedDevOrigins()接入。normalizeHost()的防御性细节很能说明问题剥掉 schemehttps://、path、query、hash因为Next 只按 host 匹配仍带 scheme/port/path 的条目匹配不到任何东西调用者将原样遭遇本想修复的 403兼容方括号 IPv6[::1]:3000归约为::1只有恰好一个冒号时才视为host:port并剥掉端口——裸 IPv6 字面量有多个冒号且无端口可剥避免了误伤。函数入口注释直接引用了上文故障模式a dev stack opened on a LAN address or a proxied hostname serves the SSR HTML but never hydrates文档与实现互为镜像。性能预算pnpm perf:check 与 performance-budgets.jsonAGENTS.md的 Contributing 部分定义了路线资产route asset预算机制这是容易被忽略但极具实战价值的部分pnpm perf:check从一次普通生产构建测量/login再以 static-demo 模式构建 fixture 驱动的 workspace 路由在临时本地端口启动生产服务器测量代表路由所引用的去重后JavaScript 与 CSS 文件总量详细结果写入.next/performance-results.json总量与performance-budgets.json对比超预算时修复路线所有权或拆分点禁止在未记录并评审实测回归的情况下抬高上限。预算数值见 frontend/performance-budgets.json单位字节路由CSS 上限JS 上限/login170,000850,000/175,0001,050,000/workspace/chats190,0001,750,000/workspace/chats/thread_id190,0004,100,000/en/docs270,0004,200,000/blog/posts270,0004,200,000这张表本身就是架构决策的化石记录/login最轻登录页不携带聊天负载带真实 thread 的聊天页 JS 预算4.1 MB显著高于空的/workspace/chats1.75 MB因为前者会装配流式渲染、CodeMirror、子代理面板等聊天专属依赖而/en/docs与/blog/posts同为重内容路由共享 4.2 MB 档位。frontend/src/AGENTS.md 中保持/静态、把富内容 CSS 留在渲染它的路由上Static root boundary的约定正是维持这套预算可行的前提。贡献流程小结AGENTS.md的 Contributing 章节规定了新增功能的五步闭环遵循既有src/结构补充 TypeScript 类型与恰当的错误处理在tests/unit/pnpm test写单元测试、在tests/e2e/pnpm test:e2e写 E2E 测试提交前运行pnpm check当架构、命令或约定变化时同步更新AGENTS.md本身——这一步把文档随代码演进从口头约定变成了检查项也是CLAUDE.md这种导入式 shim 模式能长期成立的关键保障。小结frontend/CLAUDE.md 用一行AGENTS.md演示了一个可复制的开源协作模式入口文档只负责导入实质规范收敛到一份跨智能体共享的 frontend/AGENTS.md再向 frontend/src/AGENTS.md 下钻源码级细则。围绕这份规范DeerFlow 前端形成了完整可验证的工程闭环——技术栈由 frontend/package.json 的packageManager钉版、pnpm check串联 ESLint 与 tsc、frontend/rstest.config.ts 以文件后缀划分 node/DOM 双测试环境、frontend/playwright.config.ts 以生产构建 全量网络拦截支撑 E2E、frontend/next.config.js 的环境变量感知重写消除硬编码后端地址、frontend/src/dev-origins.js 修复 LAN 开发 403、frontend/performance-budgets.json 给每条路由的 JS/CSS 总量设了量化红线。对开发者与编码智能体而言这套文档即契约照着它组织代码、写测试、跑检查就能与仓库现状保持一致。【免费下载链接】deer-flowAn open-source long-horizon SuperAgent harness that researches, codes, and creates. With the help of sandboxes, memories, tools, skill, subagents and message gateway, it handles different levels of tasks that could take minutes to hours.项目地址: https://gitcode.com/GitHub_Trending/de/deer-flow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考