首页
/ PrivateGPT Workbench 的 AI 编码代理约定(ui/AGENTS.md):如何约束 Codex 等代理安全修改单文件演示 UI

PrivateGPT Workbench 的 AI 编码代理约定(ui/AGENTS.md):如何约束 Codex 等代理安全修改单文件演示 UI

2026-09-06 09:33:23作者:秋阔奎Evelyn

本文以 ui/AGENTS.md 为核心,逐条解读 PrivateGPT 仓库中用于规范 Codex 及其他 OpenAI 风格编码代理在 ./ui 目录下工作流的约定文件,并结合 ui/README.mdui/docs/SOURCE_OF_TRUTH.mdui/docs/PRD.mdui/docs/STYLE_GUIDE.mdui/index.html 等真实文件说明每条规则的落地方式。读完本文,你将掌握一套可直接复用的“AI 代理 + 单文件前端”协作模式:强制阅读顺序、变更范围边界、文档同步纪律,以及一条可复制的 node 内联脚本校验命令。

一、背景:ui/ 是 PrivateGPT 的轻量演示层,AGENTS.md 是它的代理入口

PrivateGPT 是一个面向本地模型的完整 API 层,覆盖 RAG、skills、tools、MCP、text-to-Sql 等能力,可对接任意 OpenAI 兼容的推理服务。在此之上,./ui 目录中的 PrivateGPT Workbench 是一个轻量级静态演示 UI:它把 PrivateGPT 的 API 能力(文档问答、工具调用、代码执行等)变成可直观体验的产品界面,但刻意保持为“轻演示器,而非主产品”。ui/docs/PRD.md 明确写道:

This UI should remain a lightweight demonstrator, not the main product. It now lives inside the PrivateGPT repository under ./ui and must not become a heavy frontend application or a maintenance burden.

正因如此,ui/ 的组织方式极为克制——运行时实现全部收敛在单个文件里,其余全部是文档与参考资料。ui/README.md 给出的目录地图如下:

文件 职责
ui/index.html 唯一的运行时实现文件(全文件约 7974 行,内联全部 HTML/CSS/JS)
ui/AGENTS.md Codex / OpenAI 风格代理的工作流约定
ui/CLAUDE.md Claude Code 的工作流约定
ui/docs/PRD.md 产品行为与信息架构需求
ui/docs/STYLE_GUIDE.md 视觉与交互方向
ui/docs/SOURCE_OF_TRUTH.md 权威路径、API 契约与文档所有权
ui/references/ 供风格指南使用的视觉参考图

ui/AGENTS.md 的标题是 “Codex Instructions”,开篇一句话点明服务对象:

This file is for Codex and other OpenAI-style coding agents working in ./ui.

它的结构只有三部分:Read First(强制阅读顺序)、Scope(变更范围边界)、Codex-Specific Notes(执行纪律)。下面逐节展开,并说明每条规则在仓库中如何被真实文件支撑。

二、Read First:代理动手前的强制阅读清单

ui/AGENTS.md 要求代理在“改变行为、UI 或 API 接线之前”,按固定顺序先读以下五个文件:

  1. README.md
  2. docs/SOURCE_OF_TRUTH.md
  3. docs/PRD.md
  4. docs/STYLE_GUIDE.md
  5. index.html

转换为仓库根相对路径即 ui/README.mdui/docs/SOURCE_OF_TRUTH.mdui/docs/PRD.mdui/docs/STYLE_GUIDE.mdui/index.html。这个顺序并非随意排列,它体现了一条“从地图到实现”的信息漏斗:

  • README.md 提供目录地图。如上表所示,它先让代理知道每个文件管什么,避免把产品规则误写入运行时文件、或把参考图混进实现目录。
  • SOURCE_OF_TRUTH.md 定义文档所有权ui/docs/SOURCE_OF_TRUTH.md 用一节 “Working Rules” 明确划分:产品需求归 docs/PRD.md,视觉规则归 docs/STYLE_GUIDE.md,代理专属规则归 AGENTS.mdCLAUDE.md,参考图归 references/,运行时代码归 index.html。它同时指出 API 契约的权威来源是 Fern 生成的 fern/openapi/openapi.json,并特别强调“Do not maintain a duplicated UI-local OpenAPI snapshot”——即 UI 层不得维护第二份 OpenAPI 快照。
  • PRD.md 描述产品行为ui/docs/PRD.md(约 999 行)列举了 PrivateGPT 的能力清单(Chat/messages API、文件摄取、带引用检索、Text-to-SQL、CSV 沙箱分析、Web 搜索与抓取、MCP、Skills、自定义工具、Embeddings 与底层原语),并列出 Workbench 依赖的关键端点,如 POST /v1/messagesGET /v1/modelsPOST /v1/artifacts/ingestPOST /v1/primitives/searchPOST /v1/tools/database-query 等;同时要求实现必须以 Fern 生成的 OpenAPI 中 ChatBodyMessageInputToolSpecBodyContextFilterFileArtifactSqlDatabaseArtifactMcpServerConfig 等 Schema 为准,PRD 中的示例仅作示意。
  • STYLE_GUIDE.md 约束视觉语言ui/docs/STYLE_GUIDE.md(约 599 行)规定深色氛围化工作区风格(深海军蓝/炭色底、细噪点纹理、毛玻璃面板、蓝橙紫渐变点缀),并声明 ui/references/ 下的四张参考图(如 primary-chat-layout.pngsearch-overlay.pngchat-tools-composer.pngcontext-knowledge-base.png)分别对应主聊天布局、搜索弹层、输入区与知识库面板的视觉基准;还要求 PrivateGPT Logo 以内联 SVG 方式直接嵌入 index.html,使页面运行时不依赖外部 Logo 资源。
  • index.html 才是实现本体。代理最后才读它,因为前四份文档已经回答了“要做什么、做成什么样、契约是什么”,最后一步才是对照现有代码。从源码看,ui/index.html<script> 块自第 3936 行起,状态持久化键为 STORAGE_KEY = "privategpt-workbench-state-v1",API 基地址的默认逻辑是:window.location.origin === "null"(如 file:// 直接打开)时回落到 http://127.0.0.1:8080,否则使用当前 origin(见 ui/index.html)。这解释了演示 UI 既可以同源部署在 PrivateGPT 服务后面,也可以作为静态文件直接打开并指向本地 8080 端口。

三、Scope:变更的边界规则

ui/AGENTS.md 的 “Scope” 一节给出四条边界,其本质是把“低维护成本”这一 PRD 级目标翻译成代理可执行的动作:

  1. Keep the app as a simple static demo —— 保持应用是一个简单的静态演示,不允许代理顺手引入构建工具链、模块化拆分或重型框架。这与 PRD 中 “must not become a heavy frontend application or a maintenance burden” 直接对应。
  2. Keep index.html as the only runtime implementation file unless the user explicitly asks —— index.html 保持为唯一运行时实现文件,除非用户明确要求不同结构。ui/docs/SOURCE_OF_TRUTH.md 在 “Runtime Implementation” 一节同样声明 ../index.html(即 ui/index.html)是 Workbench 演示的唯一运行时实现文件,两份文档互为印证。
  3. Treat docs/SOURCE_OF_TRUTH.md as the canonical pointer to API contract paths and documentation ownership —— 把 ui/docs/SOURCE_OF_TRUTH.md 视为 API 契约路径与文档所有权的权威指针。也就是说,代理在“某条规则应该写在哪份文档、某个 API 路径以什么为准”这类问题上,不再自行判断,而是以该文件为准:契约指向 fern/openapi/openapi.json,文档归属按 “Working Rules” 划分。
  4. Update the relevant docs in docs/ whenever behavior, visuals, persistence, security posture, or API request/response handling changes —— 一旦行为、视觉、持久化、安全姿态或 API 请求/响应处理发生变化,必须在同一次变更中更新 docs/ 下相应文档。ui/docs/SOURCE_OF_TRUTH.md 末尾重复了这条规则,且 ui/README.md 的 “Working Rules” 也以 “Keep docs and implementation aligned” 呼应,三处一致说明这是 ui/ 模块最核心的纪律。

值得注意的是,ui/docs/SOURCE_OF_TRUTH.md 还专设 “Key Implementation Notes” 一节,记录那些“光读 index.html 看不出来”的实现事实,例如:Collection 名集中存放在 Settings 的 state.context.documents.defaultCollection 中;Appearance 覆写通过 applyAppearance() 驱动的 CSS 自定义属性生效;代码执行开启时必须把 chat.id 作为 container 字段随 ChatBody 发送以复用同一沙箱会话;文件上传走 POST /v1/files?scope_id={chat.id},下载走 GET /v1/files/{file_id}/content?scope_id={chat.id}。这类“非显而易见的实现注记”正是 Read First 清单中第二份文件的实际价值所在——它把散落在近 8000 行单文件代码中的隐性约定提炼成代理可快速检索的文字。

四、Codex-Specific Notes:执行纪律

ui/AGENTS.md 的 “Codex-Specific Notes” 针对代理执行过程定下三条纪律:

  • Follow the validation steps documented in README.md and docs/SOURCE_OF_TRUTH.md —— 遵循 ui/README.mdui/docs/SOURCE_OF_TRUTH.md 中记载的校验步骤,而不是自创校验方式。
  • If implementation and docs disagree, fix the disagreement in the same change —— 如果发现实现与文档不一致,必须在同一次变更中修掉这种不一致,不允许“先改代码、文档以后再补”。
  • When finishing work, summarize what changed, what validation ran, and any known limitations —— 完成工作时必须总结:改了什么、跑了哪些校验、存在哪些已知限制。

这三条与 “Scope” 第 4 条共同构成了一个闭环:文档是契约 → 契约变化必须随代码同步 → 不一致必须当场修复 → 交付时主动披露校验情况与局限。

校验命令:README 中的一行 node 脚本

AGENTS.md 要求遵循 README 中的校验步骤,该步骤即 ui/README.md 给出的这条命令(在仓库根目录执行):

node -e "const fs=require('fs'); const html=fs.readFileSync('./ui/index.html','utf8'); const m=html.match(/<script>([\s\S]*)<\/script>/); if(!m) throw new Error('script tag not found'); new Function(m[1]); console.log('script ok')"

这条命令的作用是把 ./ui/index.html 中第一个 <script> 块的完整内容用正则提取出来,交给 new Function() 做一次语法解析;若找不到 script 标签则抛错,解析通过则输出 script ok。它不启动浏览器、不访问网络,是一条零依赖的“内联脚本语法门禁”,恰好匹配“单文件运行时”的结构:整个应用的 JS 都在一个 script 标签里,校验它即可拦截最常见的回归——JS 语法错误。这也解释了为什么单文件结构反而是优点:校验目标明确、无构建步骤、代理改动后可立即自检。

五、AGENTS.md 与 CLAUDE.md:同一契约的两个入口

ui/ 目录同时维护了第二份代理约定文件 ui/CLAUDE.md,服务对象是 Claude Code:

See @README.md, @docs/SOURCE_OF_TRUTH.md, @docs/PRD.md, and @docs/STYLE_GUIDE.md before editing index.html.

两份文件的分工可以从源码结构看得很清楚:核心规则(保持静态单文件、以 SOURCE_OF_TRUTH 为权威指针、行为/视觉/持久化/安全/API 处理变化时同步文档)在两份文件中保持一致;差异只在“入口习惯”——AGENTS.md 用编号列表给出五份必读文件(含最后的 index.html),CLAUDE.md 则用 Claude Code 的 @file 引用语法压缩成一句话,并且多出一条代理专属提示:“Use the shared docs above as the source of truth instead of duplicating product or design rules here”(以共享文档为准,不要把产品/设计规则复制进代理指令文件)。这种“规则集中在共享文档、代理文件只保留入口与专属纪律”的做法,避免了多份代理文件各自演化后互相矛盾。

六、设计启示:这套约定的可复用要点

ui/AGENTS.md 放到整个 ui/ 目录的背景下看,它示范了一套适合“AI 代理参与维护的静态前端”的工程约束,可归纳为五点:

  1. 单一运行时文件 + 单一契约来源。实现只有 ui/index.html 一个文件,API 契约只认 fern/openapi/openapi.json 一份(且明确禁止 UI 本地快照)。代理的决策空间被压缩到最小,幻觉与漂移的余地也最小。
  2. 固定的阅读顺序代替模糊的“先看文档”。Read First 清单把“理解项目”拆成确定性的五个动作,顺序从目录地图(README)到所有权定义(SOURCE_OF_TRUTH)再到需求(PRD)、视觉(STYLE_GUIDE)、最后才触碰代码(index.html)。
  3. 文档所有权显式化。“Working Rules” 逐条规定哪类内容住哪个文件,代理改任何一类内容时都能唯一确定落点。
  4. 同变更同步纪律。“实现与文档不一致时,在同一变更中修复”把一致性从口头要求变成验收项;配合 “Key Implementation Notes” 记录隐性实现事实,文档始终能跟上近 8000 行单文件代码的演化。
  5. 可执行的轻量校验。一行 node -e 命令即可完成内联脚本语法门禁,与交付时“说明改了什么、跑了什么校验、有哪些局限”的总结要求配套,形成最小但完整的验证闭环。

七、小结

ui/AGENTS.md 全文不长,但它与 ui/README.mdui/docs/SOURCE_OF_TRUTH.mdui/docs/PRD.mdui/docs/STYLE_GUIDE.md 一起,构成了 PrivateGPT Workbench 这套“代理工作流”的完整契约:五步强制阅读顺序定义了信息获取路径,四条 Scope 规则定义了变更边界,三条 Codex-Specific Notes 定义了执行与交付纪律,而 ui/README.md 中的一行 node 命令则提供了可立即复制执行的校验手段。对于任何需要在单文件静态应用中引入 AI 编码代理的团队,这套“共享文档承载规则、代理文件只做入口、同变更同步文档、最小语法门禁”的模式都是值得参照的范本;而阅读它的最佳入口,正是按 AGENTS.md 指定的顺序,从 ui/README.md 读起。

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