AI 架构设计有点菜,我写了个 Skill 给它补课

我最近越来越强烈地感觉到一件事:AI 写代码已经挺能打了,速度很快,补函数、改组件、写测试都能帮上很多忙。

但一到架构设计,情况就不一样了。很多时候,AI 能把代码写出来,却不太能决定系统应该怎么拆、边界应该放在哪里、哪些抽象现在值得做,哪些应该先忍住。最后架构还是得人自己定。

那人怎么定?一个很常见的做法,就是去调研别人已经做过的项目:看看成熟仓库怎么组织模块、怎么处理主流程、怎么把复杂度收起来。本来我以为这件事也可以交给 AI,让它帮我分析一下参考项目的架构。结果经常发现,AI 分析别人项目的能力也不太行,经常读到最后只剩目录结构、函数调用关系和一些泛泛的模块说明。

它很像一个刚入职、很努力、但还没学会抓重点的同事。

你把一个项目丢给它,它会认真读 README,扫目录,列模块,画几个箭头。说得都对,但你读完总觉得少了点什么。

少的不是"信息",而是"判断"。

比如你真正想知道的是:

  • 这个项目为什么这么拆模块?
  • 哪条主流程最能暴露作者的设计意图?
  • 哪些抽象值得我偷师,哪些只是历史包袱?
  • 如果要把这种设计迁移到自己的项目,该复制什么,千万别复制什么?

但普通提示词下的 AI,经常给你一份"目录树豪华版"。看上去很充实,脑子里还是没有架构。

于是我写了一个项目:Arch Insight。它是一个 Agent Skill,目标不是让 AI "总结代码",而是让 AI 把源码仓库转成设计判断

更准确地说,它试图教 AI 一件事:

读代码不是把文件读完,而是找到系统真正站在什么设计选择上。

目前我已经开源,放在GitHub上,欢迎stars。

安装命令

arduino 复制代码
npx arch-insight install-release

并且花了3个小时做了个官网展示(前端已经死的很安详)。

一、我为什么要写它:AI 读仓库时,经常很努力但跑偏了

AI 通常会很配合:

  1. 先介绍项目是干什么的。
  2. 再列目录结构。
  3. 再说每个模块负责什么。
  4. 最后给一段"整体架构清晰、模块职责明确"的评价。

这当然不算错,但不够有用。

真正的问题在于,AI 默认并不知道"架构分析"到底要分析什么。它很容易把架构理解成:

txt 复制代码
目录结构 + 模块职责 + 调用关系 + 一点点总结

可在真实工程里,架构更像是:

txt 复制代码
问题约束 + 主流程 + 核心抽象 + 边界设计 + 取舍理由 + 可迁移条件

这两个东西差别很大。

前者像把厨房里的抽屉都打开,告诉你锅在哪、刀在哪、盐在哪。后者才是在解释:为什么这个厨房这么布局,主厨每天最高频的动作是什么,什么设计提升了效率,什么设计以后会卡住扩张。

我遇到的具体痛点主要有五个。

第一,Token 烧得太快。 每次新对话都把整个仓库扫一遍,上下文哗啦哗啦烧掉,真正需要深挖的文件反而没读透。

第二,重复劳动。 同一个项目,今天问一次,明天换个角度再问,AI 又从零开始读。你付过的"理解成本",下一轮不一定能复用。

第三,分析太浅。 AI 很擅长复述"这里有什么",但回答"为什么这么设计"不太稳定。尤其是项目有构建层、安装层、发布层、适配层时,它容易被文件数量带着走。

第四,风格不对。 有时我想要一篇能发表的技术长文,它给我模板报告;有时我想要结构化研究包,它又写得像博客散文。

第五,不会引导。 我自己有时也说不清该问什么。AI 如果没有一套固定研究路径,就会在"读得很多"和"读得有用"之间摇摆。

所以 arch-insight 的出发点不是"再写一个总结工具",而是把我希望 AI 遵守的源码研究方法固化成 Skill。

它不是让 AI 更会夸项目,而是让 AI 更会质疑项目。

二、先看效果:好的架构分析应该长什么样

说一堆"研究路径""设计判断",确实容易变成空话。更直接的方式,是看它到底能产出什么。

由于最近在写Agent相关,要设计项目的coding workflow提效和Agent的Memory的设计。所以我用 arch-insight跑过两类参考项目:一类是 LLM coding workflow,一类是 agent memory system。它们的共同点是:如果只按目录和函数调用读,很容易读成"这个文件调用那个文件";但真正有用的地方,是它们背后的工程取舍。

1. 分析 LLM coding workflow:不只是列功能,而是比较协作机制

以下文章都是通过Arch Insight直接生成

比如这篇样例:五个 LLM 编码助理工作流的深度对比分析

它分析的不是单个仓库,而是 cc-sdd、Compound Engineering、Superpowers、Trellis、Spec Kit 五个项目。普通分析很可能会写成:

txt 复制代码
每个项目有哪些命令、有哪些 skill、有哪些模板、有哪些 agent。

但真正有价值的分析应该先把它们放到同一张坐标系里:

维度 真正要看的问题
工作流编排 人类和 LLM 的职责边界在哪里?哪些阶段必须审批?
子代理机制 是一个 agent 从头做到尾,还是 per-task 隔离实现、审查和调试?
上下文管理 项目知识靠 prompt 临时塞进去,还是有文件系统/JSONL/状态协议承接?
知识积累 一次工作结束后,经验会不会进入下一次默认上下文?
跨平台策略 是单平台 prompt,还是把同一套工作流翻译到多个编码助理?

这样一对比,项目之间的性格就出来了:

  • cc-sdd 押注的是契约驱动:spec 不是"给 agent 的说明书",而是系统各部分之间的边界契约。
  • Compound Engineering 押注的是复合效应:每次工程工作都应该让后续工作更容易,而不是只完成当下任务。
  • Superpowers 押注的是流程纪律:防止 agent 一上来就写代码,强制先设计、再计划、再执行、再审核。
  • Trellis 押注的是结构化上下文:用 .trellis/ 目录、任务状态和 JSONL 注入,替代 LLM 不可靠的短期记忆。
  • Spec Kit 押注的是规格平台化:让 spec 不只是文档,而是可以驱动代码生成和扩展生态的输入。

这就不是"函数调用关系"了,而是在回答:

如果我要设计自己的 AI coding workflow,应该借鉴谁的哪一部分,又应该避开谁的代价?

比如样例里最后给出的启示,就已经很接近可迁移的设计建议:

值得借鉴的机制 来源 为什么有用
workflow-state breadcrumb 协议 Trellis 用很轻的文本标签,让 agent 每轮都知道自己处在哪个阶段
Boundary-First 任务切分 cc-sdd 避免 agent 在长 session 里被上下文污染
多 persona 并行 code review Compound Engineering 用不同视角弥补单个 agent 的审查盲区
每 task 三角色闭环 cc-sdd / Superpowers 把实现、审查、调试拆开,降低自我确认偏差
文档复合系统 Compound Engineering 让一次解决问题的经验进入后续工作

这才是我想要的架构分析:不是告诉我"它有几个命令",而是告诉我"这些命令背后在押注什么协作模型"。

2. 分析 agent memory:找出设计分水岭,而不是堆 API 名字

另一篇样例是:代理记忆系统的设计哲学

这个主题更容易被 AI 分析歪。因为 memory 项目里有大量 API、数据库、embedding、search、tool calling,如果没有抓重点,很容易写成:

txt 复制代码
mem0 有 add/search,Graphiti 有 add_episode/search,Letta 有 memory block,LangMem 有 manage_memory tool。

这些都对,但没什么决策价值。

真正的重点,是先问一个更上层的问题:

"记忆"到底以什么物理形式存在,什么时候进入模型视野?

这个问题一出来,五个项目马上分成两类:

类型 代表项目 核心取舍
基于检索 mem0 / Graphiti / LangMem / Basic Memory 记忆放在外部,需要时检索,规模大,但可能检索失败
基于编译 Letta 核心记忆每轮编译进上下文,不会漏,但受上下文窗口限制

这个分水岭比"用了什么数据库"重要得多。因为它直接决定了系统的使用场景:

对于任务长、工具结果多的 CLI 编程代理,基于检索更合适;对于需要稳定知道"用户是谁"的聊天同伴或客服代理,基于编译更合适。通用代理平台往往需要两者都要。

再往下,样例不是平铺五个项目的功能,而是继续抽出真正的设计权衡:

设计选择 代表项目 背后的判断
ADD-only vs CRUD mem0 / LangMem 是把写入做简单,还是让记忆始终代表最新状态?
时态图 vs 向量数据库 Graphiti / mem0 是要关系和时间推理,还是先满足语义相似检索?
自动提取 vs agent 主动管理 mem0 / LangMem / Basic Memory 是保证重要信息不丢,还是相信 agent 自己判断何时记住?
人类可读 vs 机器优化 Basic Memory / 向量记忆系统 人类是否需要检查、编辑、拥有最终控制权?

比如 mem0 V3 的 ADD-only 设计,表面看是一个实现细节:只追加,不更新,不删除。真正的架构判断是:

把写入时的冲突解决成本,转移到检索时的排序和筛选成本。

这句话就有迁移价值。它会提醒你:如果你的记忆主要是用户偏好、项目约定、经验沉淀,ADD-only 可能很稳;如果你的记忆是权限、配置、规则这种必须准确的事实,那就不能简单照抄。

Graphiti 的事实有效性窗口也是类似:

txt 复制代码
EntityEdge {
  valid_at
  invalid_at
}

这不是"多了两个字段"。它表达的是一种设计哲学:

不删除旧事实,但也不让旧事实继续污染当前判断。

这类结论才是我想从参考项目里带走的东西。

3. 这些样例真正展示了什么

看完这两篇样例,我觉得好的架构分析至少应该有三个特征。

第一,它会主动找分水岭。 比如 memory 系统里的"检索 vs 编译",coding workflow 里的"流程刚度 vs 灵活性"。分水岭找到了,后面的模块和文件才有意义。

第二,它会把实现细节翻译成工程取舍。 ADD-only、workflow breadcrumb、Boundary-First、human/persona block,这些都不是孤立技巧,而是在用不同方式解决成本、可靠性、上下文污染、知识积累这些问题。

第三,它会给迁移建议。 不是"这个项目很好",而是"什么场景适合借,什么场景不要借,先验证哪一个风险"。

所以 arch-insight 想解决的不是"让 AI 多读几个文件"。

我真正想要的是:当我准备设计自己的系统时,AI 能先帮我把别人的项目读成可复用的设计判断。

三、我是怎么把这套分析方法做成 Skill 的

有了上面这些样例之后,下一步就是把这种分析方式固定下来。

我不想每次都在对话里重新解释:"不要只列目录""先找设计分水岭""要给迁移建议""不要把函数调用关系当架构"。这些要求靠临场 prompt 可以做到一次,但很难稳定复用。

所以我做 arch-insight 的思路很简单:把一次有效的架构分析过程拆成几个固定动作,再把这些动作写进 Skill 里。

大概流程是:

txt 复制代码
先问清楚这次想看什么
-> 再决定哪些代码要重点读
-> 找出项目最关键的那条主线
-> 解释作者为什么这么设计
-> 最后写成能直接参考的内容

这几步其实是在把我平时手动分析项目的过程写下来。

比如先问清楚目标,是为了避免 AI 一上来就把仓库全扫一遍;先决定重点读哪些代码,是为了把精力放在真正决定系统形状的地方;找主线和解释设计原因,是为了让它不要停在"这个函数调用那个函数";最后写成能参考的内容,是为了让分析结果真的能帮我设计自己的项目。

这部分写完以后,我一开始以为差不多了:不就是把提示词整理好,放进 SKILL.md,然后让 AI 按这套流程工作吗?

但很快我发现,新的问题出现了。

如果这个 Skill 只给自己用,可能确实就是写好文件,放到对应目录,结束。可一旦想让它在 Codex、Claude、Gemini、OpenCode、Pi、Kiro、Cursor 这些环境里都能安装和使用,它就会从"写一份提示词"变成"做一个多平台发行工具"。

这也是我实现过程中踩得最多的工程问题:同一套分析方法,怎么构建成不同平台能识别的包,怎么装到正确位置,怎么确认装完以后真的能被平台看见。

1. Skill 不只是提示词,还要工程化

arch-insight 不是一个复杂业务系统,更像一个"Skill 分发器 + Skill 本体"的组合。

整个项目有两条主线:

  1. Skill 主线:定义 AI 应该如何分析仓库。
  2. 工程主线:把这个 Skill 构建、发布、安装到不同 Agent 平台。

2. CLI 只做调度,平台差异放到后面

入口在 bin/arch-insight.js,实际调度在 src/cli/run.js

runCli 解析命令,然后分发到几个核心动作:

  • build:从 .agents 构建平台包。
  • install:从本地 bundle 安装。
  • install-release / update / upgrade:从发布产物下载安装。
  • release:构建发布清单和 bundle。

设计很直接,但边界很清楚:CLI 只做调度,不直接知道每个平台怎么生成 manifest,也不直接知道每个平台怎么安装。

src/cli/run.js 是控制层,不是平台知识层。

这个边界很重要。因为多平台发行真正麻烦的不是"多复制几份文件",而是每个平台都在问不同的问题:manifest 长什么样、入口文件叫什么、默认目录在哪里、装完以后平台能不能看见。

3. 构建层处理 manifest 差异

构建主流程在 src/build/build-bundles.js

它先调用 validatePluginSource(sourceDir) 检查 .agents 是否完整,再用 loadPluginSource(sourceDir) 把 Skill、Runner、prompts、templates 读成统一结构,然后根据目标平台调用对应 builder。

关键映射:

js 复制代码
const TARGET_BUILDERS = {
  claude: buildClaudeBundle,
  codex: buildCodexBundle,
  gemini: buildGeminiBundle,
  opencode: buildOpenCodeBundle,
  pi: buildPiBundle,
  kiro: buildKiroBundle,
  cursor: buildCursorBundle
};

这是项目的第一个核心抽象:target builder

它把"平台差异"集中在 src/build/targets/*.js,不污染 Skill 本体。

Codex 需要 .codex-plugin/plugin.json,里面有 interface.displayNamecapabilitiesdefaultPrompt 等字段;Claude 需要 .claude-plugin/plugin.json,还涉及本地 marketplace 注册;Gemini 使用 gemini-extension.json,并额外放入 GEMINI.md。OpenCode、Pi、Kiro、Cursor 又各有自己的插件或 skill 约定。

所以项目没有试图写一个"万能 manifest",而是用 src/build/targets/*.js 为每个平台生成自己的外壳。

同一个 Skill 内容,不同平台外壳。这是一种很实用的架构选择:领域内容保持稳定,平台包装单独变化。

别假装平台差异不存在,把差异收口到适配器里。

4. 安装层处理路径和可见性

构建完还不够。Skill 不是放进某个目录就一定可用。

安装主流程在 src/install/install-bundle.js,通过 TARGET_INSTALLERS 选择平台 installer,再通过 resolvePlatformInstall 决定默认安装路径。

不同平台路径差异很明显:

  • Codex:~/.codex/skills/arch-insight
  • Gemini:~/.gemini/skills/arch-insight
  • OpenCode:~/.config/opencode/skills/arch-insight
  • Cursor:~/.cursor/plugins/local/arch-insight
  • Claude:~/.claude/plugins/local/arch-insight

这是项目的第二个核心抽象:target installer

builder 解决"包长什么样",installer 解决"放哪里、怎么让平台识别"。

更麻烦的是,"复制成功"不等于"平台可见"。

有些平台只要文件在目录里就行;有些平台需要重启;有些平台会出现同名 Skill 冲突;有些平台还要额外注册。

比如 Gemini installer 里有 detectGeminiVisibility,会调用 gemini skills list,检查是否存在 arch-insight、是否出现 Skill conflict detected,并返回 visibilityCheck

这说明安装器不应该只做:

txt 复制代码
copy files -> done

更合理的是:

txt 复制代码
copy files -> verify entrypoint -> detect visibility -> give failure hint

一个给人用的安装器,最重要的不是永远成功,而是失败时知道下一步该干什么。

5. 发布层让安装可以跨机器复用

如果只支持本地安装,用户需要 clone 仓库、构建、再安装。对一个 Skill 来说,门槛太高。

所以项目还有发布主线:

  • src/release/build-release-artifacts.js:构建 dist/bundles/<platform>install-manifest.json
  • src/release/download-release-bundle.js:根据 manifest 下载对应平台 bundle,用 cache key 复用本地缓存。

发布层的价值在于,用户可以直接:

bash 复制代码
npx arch-insight install-release

不需要关心仓库内部怎么构建。

到这里,工程主流程就完整了。

实现不炫技,但有一个清晰的工程判断:

Skill 的内容和 Skill 的分发是两件事,应该解耦。

6. 交互安装、CI 安装和缓存是发行工具的细节

项目支持:

bash 复制代码
npx arch-insight install-release

也支持:

bash 复制代码
npx arch-insight install-release --platform codex --platform claude

前者适合人用,会进入多选交互;后者适合脚本或 CI。

但这带来一个细节:--json 模式下必须显式传 --platform,否则不能弹交互选择。这个约束在 src/cli/run.jsresolveTargetPlatforms 里处理。

这类小设计很容易被忽略,但它决定了工具是否适合自动化。

如果每次安装都重新下载,不仅慢,也容易被网络状态影响。

所以 downloadReleaseBundle 用 release URL、manifest version、platform 生成 cache key,并校验 bundle-index.json 的文件数量和 hash。

不是为了显得复杂,而是因为发布工具一旦给别人用,就要对"我到底装了什么"有基本可追溯性。

写到这里我才意识到:一个 Skill 真正产品化后,已经不只是 prompt 文件了。

它变成了:

txt 复制代码
认知流程 + 文件规范 + 构建系统 + 安装器 + 发布机制 + 可见性诊断

也就是说,AI 时代的"提示词工程",最后还是会长回软件工程。

四、哪些设计可以借鉴,哪些别急着复制

如果你也想写类似的 Skill,arch-insight 里有几件事值得借鉴。

可以借鉴:别把所有要求塞进一段提示词

我以前也会写那种很长的提示词:既要求它看目录,又要求它找主线,还要求它写得像文章,最后再补一句"请深入分析"。

这种写法的问题是,所有要求混在一起,AI 很容易不知道先做什么。

后来我改成拆步骤:先问清楚目标,再挑重点代码,再找主线,最后再写结果。

这比一上来丢一句"请深入分析架构"稳定得多。

可以借鉴:把平台差异放进 target adapter

如果你的 Skill 也要支持多个 Agent 平台,建议一开始就区分:

  • source:唯一内容源。
  • build target:生成平台包。
  • install target:安装和验证。
  • release:分发和缓存。

别为每个平台维护一份复制出来的 Skill 内容。短期省事,长期一定漂移。

可以借鉴:让 AI 明确证据等级

在分析文章里,我很喜欢区分:

  • Fact:源码或文档直接支持。
  • Inference:从多个事实推导出来。
  • Pending Verification:当前证据不够,但值得保留。

这能让 AI 的语气更诚实,也让读者更容易判断哪些结论可以直接拿走。

不建议复制:一上来就做全平台支持

如果只是给自己用,先支持一个平台就够了。

多平台支持真正麻烦的不是写几个路径,而是:

  • manifest 不同。
  • 安装行为不同。
  • 用户验证方式不同。
  • 冲突诊断不同。
  • 文档说明不同。
  • 版本发布不同。

只有当你明确希望别人安装,或者自己在多个 Agent 环境之间切换时,多平台分发才值得做。

不建议复制:把静态分析当成架构真相

arch-insight 主要处理源码阅读和设计判断,但它不能替代运行时观测。

比如并发行为、真实数据流、性能瓶颈、生产环境故障路径,只靠静态代码不一定看得准。

所以它适合做设计参考、源码导览、架构文章,不适合直接当成生产审计结论。

五、AI 缺的不是聪明,是工作方法

我写 arch-insight 之后,对 AI Coding 有一个更强的感觉:

很多时候,AI 不是不会做,而是不知道你心里那套"好工作"的标准。

你让它"分析架构",它就用默认理解去分析。默认理解不一定差,但很可能不是你要的。

Skill 的意义,就是把你的标准写下来。

你希望它先定边界,就写进 Skill。 你希望它少复述目录树,就写进 Skill。 你希望它用源码路径支撑判断,就写进 Skill。 你希望它区分报告、长文和仓库导览,就写进 Skill。 你希望它每次都记得这些,而不是靠你现场提醒,也写进 Skill。

所以这篇文章的标题虽然有点开玩笑,说"AI 架构设计不太行",但更准确的说法可能是:

AI 不是天生不会做架构分析,只是它需要一套可执行的架构阅读训练。

arch-insight 就是我给它写的那套补课材料。

如果一个人类工程师可以通过 code review、复盘、架构文档逐渐形成判断力,那 AI 也可以通过 Skill,把一次次好的工作流沉淀成下一次的默认动作。

这件事真正有意思的地方不在于"我写了一个工具",而在于它暗示了一种新的工程习惯:

不只让 AI 帮我们写代码,也把我们读代码、判断设计、形成经验的方法,反过来工程化地教给 AI。

这可能才是 Agent Skill 最值得玩的地方。

最后

如果想了解更多,可以来我个人Blog,里面有Agent相关的文章,还有Claude Code源码解析。

相关推荐
人工智能AI技术2 小时前
循环结构基础:for、while、递归性能对比
人工智能
盼小辉丶2 小时前
PyTorch强化学习实战(5)——PyTorch Ignite 事件驱动机制与实践
人工智能·pytorch·python·强化学习
eastyuxiao10 小时前
思维导图拆解项目范围 3 个真实落地案例
大数据·运维·人工智能·流程图
风落无尘10 小时前
《智能重生:从垃圾堆到AI工程师》——第五章 代码与灵魂
服务器·网络·人工智能
冬奇Lab10 小时前
RAG 系列(八):RAG 评估体系——用数据说话
人工智能·llm
landyjzlai11 小时前
蓝迪哥玩转Ai(8)---端侧AI:RK3588 端侧大语言模型(LLM)开发实战指南
人工智能·python
舒一笑11 小时前
用几十行代码搞定 Chat 接口透明转发:跨环境轻量级网关实战
后端·程序员·架构