4月29号晚上11点半,我第一次用 git init 初始化了 skill-platform 这个项目。
5月3号下午,92次提交之后,项目正式上线。前端部署在 Cloudflare Pages,后端跑在 Railway,Python Agent Runtime 跑在 Docker 容器里。140个源文件,24000行代码。Dashboard、Skill 市场、智能体对话、知识库、权限管理——一个完整的 AI 技能管理平台。
我是一个产品经理,不是程序员。不会写 TypeScript,不会写 Python,不会配 Docker。五年前的工作是画流程图和写 PRD。
但这五天里,我经历了从零到上线的完整软件工程周期:需求定义、技术选型、架构设计、前后端开发、联调、部署、502 崩溃排查、权限重构、移动端适配。每一个环节都是 AI 在写代码,但每一个决策都是我在做。
这篇文章,我想把整个过程拆开来讲。不是讲感受,是讲方法。讲一个非技术人员怎么用 AI coding 完成一个全栈项目,讲中间踩了哪些坑、省了哪些钱、做对了什么、做错了什么。如果你也想试,希望你能从这篇文章里找到一条可复制的路径。
一、先交代背景:为什么是我在做这件事
我的职业背景是 AI 产品经理 + 流程管理专家。日常做的是产品规划、需求分析、业务流程设计。写代码这件事,从来不在我的工作范围里。
但我一直有个执念:一个做 AI 产品的人,如果自己不会用 AI 把想法变成产品,那对 AI 的理解永远是二手的。你评审过再多技术方案,面试过再多工程师,自己没下过场,很多东西就是理解不了。
所以 skill-platform 这个项目,本质上是一次"下场验证"。验证的核心命题是: 一个非技术人员,借助 AI coding 工具,能不能独立完成一个专业级的全栈产品?
答案是能。但过程远比想象中曲折。
二、产品定义:我想做一个什么东西
Skill Platform(中文名:詹老师的智能体平台)是一个 AI 技能管理与智能体运行平台。简单说,它解决的问题是: 怎么让 AI 从"能聊天"变成"能干活"。
核心功能模块:
1. Skill 管理 —— AI 技能的创建、版本管理、市场分发。每个 Skill 可以理解为一个"AI 能力包",包含提示词、执行配置、API 对接方式等。
2. 智能体(Agent)管理 —— 创建对话式 AI 智能体,绑定不同的 Skill,用户通过聊天的方式调用技能。
3. Deep Agent 运行时 —— 一个 Python 写的 Agent Runtime,内置 8 类工具:文档生成(Word/Excel/PPT)、代码执行、互联网搜索、数据分析、图表生成等。这是让 AI "能干活"的核心引擎。
4. 知识库 —— 上传文档、自动解析,为智能体提供领域知识。
5. 权限体系 —— 访客/注册用户/管理员三层角色,登录弹窗而非独立页面,降低使用门槛。
三、技术架构:三层分离,各司其职
这是我做的第一个关键决策。作为一个产品经理,我本能地选择了"分层架构"——因为这就是业务流程设计的思路:每一层做好自己的事,层与层之间通过标准接口通信。
整个系统分三层:
前端层(Frontend)
技术栈:React 18 + Vite 5 + Ant Design 5 + Zustand(状态管理)+ React Router v6
部署:Cloudflare Pages(全球 CDN,免费额度充足)
代码量:约 40 个文件,涵盖 Dashboard、Skill 市场、智能体对话、知识库、用户管理等页面
后端层(Backend)
技术栈:NestJS 10 + TypeORM + better-sqlite3 + JWT 认证
部署:Railway(支持 Docker 构建,自动 HTTPS)
代码量:约 80 个文件,包含 13 个 Entity、完整的 REST API、Swagger 文档
Agent 运行时层(Agent Runtime)
技术栈:Python FastAPI + LangChain + LangGraph + 阿里云百炼 SDK
部署:Docker 容器(与后端合并部署,共用一个 Railway 服务)
代码量:约 20 个文件,包含 8 类内置工具(共 11 个工具文件)
为什么选这个架构?三个原因:
第一,前后端分离是现在的主流范式,教程多、资料全,AI 写代码的时候不容易犯架构级错误。第二,SQLite 作为数据库不需要额外部署数据库服务,省掉了一大块运维成本。第三,Python Agent Runtime 独立部署,和 Node.js 后端通过 HTTP 通信,语言栈不耦合,后续可以独立升级。
这些决策不是我当时就能想清楚的。是 AI 在我描述需求的时候,给出了这个方案,我根据自己的产品经验判断它合理,就采纳了。
四、Token 成本策略:该省省,该花花
这是我觉得最值得分享的经验之一。
很多人觉得用 AI coding 做项目,Token 费用是个无底洞。但实际上,只要你掌握一个原则—— 用对的模型做对的事 ——成本完全可以控制。
4.1 前端开发阶段:用便宜模型就够了
前端页面的开发,大部分工作是"把设计稿变成代码"。React 组件、Ant Design 样式、路由配置——这些任务的复杂度是相对固定的,不需要最强的推理能力。
我在构建前端页面的时候,用的是相对便宜的模型(比如 GPT-4o-mini 级别或 Claude Sonnet 级别)。一个 Dashboard 页面,一轮对话就能出来 80% 的骨架。然后微调样式、调整布局,几轮交互就完成了。
这个阶段的 Token 消耗特点是:单次对话不长(几百行代码),但对话轮次多(每个页面 5-10 轮)。所以便宜的模型在成本上优势很大——大概是一个零头的价格。
4.2 后端架构和 Agent 设计:该用贵的就用贵的
真正需要强模型的是后端架构设计和 Agent Runtime 的实现。这些涉及:
数据库 Schema 设计(13 个 Entity,关联关系复杂)
TypeORM 的 synchronize 机制和 migration 策略
JWT 认证 + Passport 守卫的完整实现
流式响应(SSE)的前后端联调
这些任务的共同特点是:逻辑链长、边界条件多、一个错误会导致整个系统崩溃。用强模型(Claude Opus / GPT-4 级别),虽然单次 Token 成本是便宜模型的 5-10 倍,但减少的调试轮次远超这个差价。
我做过一个对比:后端的 AI Service(核心对话逻辑),用便宜模型写了三版,每版都有不同的 bug——第一版返回格式不对,第二版流式输出断开,第三版 Function Calling 的 JSON 解析失败。换成强模型,一版通过。
4.3 调试排障阶段:强模型是刚需
项目上线后遇到 502 崩溃。后端日志显示 TypeORM 在 synchronize 时因为 phone 字段的 NOT NULL 约束报错。这种问题的根因分析,需要 AI 理解 TypeORM 的 synchronize 机制、SQLite 的 ALTER TABLE 限制、以及 Entity 定义和数据库实际表结构之间的差异。这不是便宜模型能搞定的事。
用强模型,一轮对话就定位到了问题:phone 字段在 Entity 里没有标记 nullable,但数据库里已有的记录 phone 为空。解决方案是在 Entity 里加一行 @Column({ nullable: true })。一个字的修改,但需要理解整个上下文才能找到。
4.4 我的 Token 成本估算
整个项目下来,Token 费用大约在 200-400 元人民币。其中:
前端开发(占代码量 40%):约 50 元,大部分用便宜模型
后端开发(占代码量 35%):约 150 元,大部分用贵模型
Agent Runtime(占代码量 15%):约 80 元,全部用贵模型
调试排障(占时间 30%):约 70 元,全部用贵模型
部署和配置(占时间 15%):约 50 元,混合使用
如果全程用最贵的模型,成本会翻 3-4 倍。如果全程用最便宜的模型,开发周期可能要翻 2 倍(因为调试轮次暴增)。所以 核心策略就是:前端用便宜模型快速出活,后端和调试用强模型一次搞定。
五、开发时间线:92 次提交的真实节奏
整个项目从初始化到上线,Git 记录了 92 次提交。我把关键节点梳理出来:
Day 0 · 4月29日 · 深夜
git init。项目初始化,第一次提交。前端骨架搭建(React + Vite + Ant Design)。
Day 1 · 4月30日
前端核心页面开发:Dashboard、Skill List、Skill 创建、Skill 详情页。后端初始化:NestJS + TypeORM + SQLite,13 个 Entity 定义。第一次 Railway 部署尝试。
Day 2 · 5月1日
功能裁剪:移除组织架构、架构管理、评审管理、租户管理等非核心模块。登录功能降级——移除强制登录,实现免登录访问。前后端首次联调成功。
Day 3 · 5月2日
Agent Runtime 开发:Python FastAPI 服务,8 类工具实现。Dockerfile 编写和调试。Railway 部署——502 崩溃排查。phone 字段 nullable 修复。
Day 4 · 5月3日
权限系统重构:三层角色模型(访客/用户/管理员)。Agent Runtime 独立部署配置。Chat streaming 502 异常修复。Skill 三级级联筛选。最终上线验证。
六、踩过的坑:每个都是一整个下午换来的
坑 1:环境变量编译成字面量
前端用的是 Vite,环境变量通过 import.meta.env.VITE_API_URL 注入。问题在于,Vite 在 build 时会把环境变量直接替换成字符串字面量。如果构建时没有正确设置环境变量,线上代码里就会写着 http://localhost:3000。
第一次部署后,前端所有的 API 请求都打到了 localhost。解决方案:删除 .env.production 文件,改为在构建命令中注入: VITE_API_URL=https://xxx.railway.app vite build。
这个坑的教训是: Vite 的环境变量不是"运行时读取"的,而是"构建时替换"的。理解这个机制,就能避免一整类部署问题。
坑 2:TypeORM synchronize 导致 502 崩溃
这是最让人崩溃的一个 bug。现象是:后端服务启动后,一切正常。过一会儿,所有 API 返回 502。
排查了半天,发现是 TypeORM 的 synchronize: true 配置。每次服务启动,TypeORM 会自动对比 Entity 定义和数据库表结构,如果有差异就执行 ALTER TABLE。但 SQLite 对 ALTER TABLE 的支持有限——它不能直接给已有列添加 NOT NULL 约束。而 phone 字段在 Entity 里没有标记 nullable: true,TypeORM 尝试同步时就崩了。
修复方式:在 Entity 里加 @Column({ nullable: true })。一行代码。但找到这一行代码,花了整个下午。
坑 3:Docker 基础镜像选错
后端用了 better-sqlite3,这是一个需要编译原生模块的库。最初用的 Docker 基础镜像是 node:20-alpine,Alpine Linux 缺少编译工具链,导致 npm install 失败。
中间试过在 Alpine 里手动安装 build-base python3,但编译出来的二进制文件在 Alpine 的 musl libc 下又和 better-sqlite3 不兼容。
最终方案:换成 node:20-slim (基于 Debian),天然支持原生模块编译。Dockerfile 从 30 行简化到 15 行。
教训: 如果你的 Node.js 项目依赖原生模块,不要用 Alpine 镜像。slim 镜像虽然大一点,但省去了无数编译问题。
坑 4:Chat Streaming 的 502 异常
AI 对话功能用的是 Server-Sent Events(SSE)实现流式输出。问题是:当 AI 回复过程中出现错误(比如 API 超时),后端会 throw 异常。但此时 HTTP header 已经发送了(SSE 的特性),throw 会导致连接异常中断,前端收到的是 502 而不是正常的错误消息。
修复方式:在 catch 块里,用 SSE 的 event: error 格式发送错误消息,然后正常结束连接。这样前端能收到完整的错误信息,用户体验不会中断。
坑 5:前端 TypeScript 编译的未定义变量
AI 生成的组件代码里,偶尔会引用一些还没有定义的变量或类型。本地开发时因为 Vite 的 HMR(热更新),可能看不出来。但 build 的时候,TypeScript 编译器会严格检查,直接报错。
最典型的一次是 SkillList.tsx 组件里引用了 mockData,但这个变量只在开发时用过,后来删了忘了清理。解决方式是全局搜索引用,逐个修复。
教训: 每次 AI 生成代码后,立即跑一遍 build,不要积攒到最后一起解决。
坑 6:Railway 环境变量覆盖 Dockerfile ENV
在 Dockerfile 里设置了 ENV AGENT_RUNTIME_URL=http://agent-runtime:8001,但 Railway 的环境变量配置里有一个旧的值,Railway 会用环境变量覆盖 Dockerfile 的 ENV,导致后端找不到 Agent Runtime。
解决方案:在 Railway 的环境变量配置里,把 AGENT_RUNTIME_URL 设置为 http://localhost:8001 (因为 Agent Runtime 和后端在同一个 Docker 容器里运行)。
教训: Docker ENV 和 Railway 环境变量的优先级关系要搞清楚。平台的环境变量永远优先于 Dockerfile 的 ENV。
七、架构决策回顾:做对了什么,做错了什么
做对了的
1. 先做减法,再做加法。
最初的产品规划里,有组织架构管理、架构树编辑、流程画布、评审系统、租户管理——非常完整。但到了第二天,我果断砍掉了这些模块,只保留 Skill 管理、智能体对话、知识库、Dashboard 这四个核心。
原因很简单:作为一个验证项目,砍掉非核心功能,意味着减少 50% 的代码量和 70% 的联调复杂度。上线比完美重要。
2. 登录降级策略。
最初设计了完整的登录系统(JWT + Passport 守卫),但上线后发现:没有用户基础的时候,强制登录只会劝退访客。所以我做了降级——移除强制登录,改为弹窗提示。访客可以浏览所有功能,只有创建和编辑操作需要登录。
这个决策来自产品经验:先让人用起来,再设计门槛。
3. SQLite 而不是 PostgreSQL。
作为一个验证项目,SQLite 是最优选择。零配置、零运维、文件级存储、数据随代码走。Railway 部署时只需要一个 volume 挂载,不需要额外的数据库服务。
如果后续需要迁移到 PostgreSQL,TypeORM 的抽象层让迁移成本很低——改一下连接配置就行。
4. 三层角色模型。
访客(可浏览)、注册用户(可创建)、管理员(全权限)。这个设计刚好覆盖了平台的运营需求,又不会过度设计。
做错了的
1. Dockerfile.combined 的反复折腾。
最初想用一个 Dockerfile 同时部署后端和 Agent Runtime(supervisor 管理两个进程)。但 Docker 里跑多进程是个坑——日志管理、进程崩溃恢复、端口冲突,每一个都是问题。
最后回退到简单方案:后端和 Agent Runtime 各自独立部署。虽然多了一个服务,但稳定性和可维护性都好很多。
2. 前端移动端适配做得太晚。
最初所有页面都按桌面端设计,到上线前一天才做移动端适配。如果一开始就用移动优先(Mobile First)的设计思路,很多布局问题就不会出现。
八、Deep Agent 工具链:AI 从"聊天"到"干活"的关键
这是整个项目里最有技术含量的部分。
普通的 AI 聊天,就是一问一答。但 Skill Platform 的目标是让 AI 真正"干活"——生成文档、搜索互联网、执行代码、分析数据。这就需要一个工具调用机制:Function Calling。
8.1 工具架构
Agent Runtime 内置了 8 类工具:
文档生成工具(document_generator.py)
支持生成 Word、Excel、PowerPoint 文档。用 python-docx、openpyxl、python-pptx 实现。用户说"帮我生成一份项目报告",AI 就能生成一份 .docx 文件并提供下载链接。
代码执行工具(code_exec.py)
在沙箱中执行 Python 代码。用 subprocess 隔离运行,限制执行时间,防止恶意代码。
互联网搜索工具(web_search.py)
用 DuckDuckGo Search API 搜索互联网。AI 可以实时获取信息,而不是只依赖训练数据。
数据分析工具(data_tools.py)
用 Pandas 处理结构化数据,支持统计分析、数据清洗。
图表生成工具(media_tools.py)
用 Matplotlib 生成各类图表,输出为 PNG 图片。
文件操作工具(file_ops.py)
读写文件、管理临时文件、处理上传下载。
知识库工具(knowledge_tools.py)
检索知识库中的相关文档,为 AI 提供领域知识。
网络抓取工具(web_scrape.py)
用 BeautifulSoup 抓取网页内容,提取正文。
8.2 Function Calling 循环
核心机制是"循环调用":
第 1 步:用户发消息。
第 2 步:AI 分析意图,决定是否需要调用工具。
第 3 步:如果需要,生成工具调用参数(JSON 格式),后端执行工具。
第 4 步:把工具执行结果返回给 AI。
第 5 步:AI 继续分析,决定是继续调工具还是直接回答。
第 6 步:循环直到 AI 给出最终回复。
这个循环最多跑 10 轮,防止无限循环。
九、部署实战:从本地到线上
9.1 部署架构
前端 → Cloudflare Pages
Cloudflare Pages 的优势:免费额度大、全球 CDN、自动 HTTPS、支持 GitHub 仓库自动构建。前端 build 出来的静态文件,推到 GitHub 后自动触发部署。
后端 → Railway
Railway 支持 Docker 构建、自动 HTTPS、环境变量管理。后端代码推到 GitHub 后,Railway 自动拉取、构建、部署。
Agent Runtime → Docker 容器(与后端合并)
最初想独立部署,但两个服务之间的网络配置比较麻烦(Railway 的内部网络需要额外配置)。最终选择合并部署——在一个 Dockerfile 里同时启动 Node.js 后端和 Python Agent Runtime。
9.2 部署踩坑清单
Cloudflare Pages 的坑:
首次部署前需要先在 Cloudflare 上创建项目,否则 CLI 部署会报错
构建命令要写对: npm run build,输出目录是 dist
环境变量要在 Cloudflare 的项目设置里配置,不能只写在本地 .env 文件里
Railway 的坑:
Railway 不需要安装 CLI,直接通过 GitHub 集成部署
环境变量的优先级:Railway 设置的 > Dockerfile ENV 的
构建日志要认真看——很多部署失败的原因藏在日志中间,不是最后一行
Alpine 镜像的原生模块编译问题,前面已经讲过
十、AI Coding 的方法论:给后来者的建议
五天下来,我总结了七条方法论。这些不是理论,是每一次报错、每一次崩溃、每一次"为什么又不工作了"之后提炼出来的。
1. 先想清楚产品,再让 AI 写代码
AI coding 最常见的失败模式是:没有产品定义,上来就让 AI 写代码。结果写了一堆功能,但拼不成一个产品。
我的做法是:先花半天时间把功能树画出来。哪些是核心功能,哪些是锦上添花,哪些是以后再说。这个功能树不需要很专业——我用的是 XMind 格式,但纸笔画也行。
有了功能树,AI 就有了边界。它知道哪些功能该做、哪些不该做。这比"你帮我做一个智能体平台"这种模糊描述,效率高 10 倍。
2. 分阶段交付,每个阶段都要能跑
不要一口气让 AI 把所有功能都写完。我的节奏是:
Day 0:项目骨架 + 首页能跑
Day 1:核心 CRUD 功能能跑
Day 2:联调通过 + 功能裁剪
Day 3:高级功能(Agent Runtime)能跑
Day 4:部署上线 + 修复
每个阶段结束时,项目都是"可运行"的状态。这样即使后续出问题,也可以回退到上一个稳定状态。
3. 描述需求时,用"给实习生讲需求"的方式
AI coding 的核心能力是理解自然语言。但"理解"不等于"猜对"。你说"做一个好看的登录页",AI 能做出来,但大概率不是你想要的。
更好的方式是像给实习生讲需求一样:具体、有参照、有边界。"做一个登录页,左边是品牌 Logo 和标语,右边是登录表单,支持 和密码登录。风格参考 Notion 的登录页——简洁、留白多、黑白灰为主色。"
描述越具体,AI 的输出越接近预期。修改轮次越少,Token 费用越低。
4. 代码审查:你不需要看懂每一行,但要看懂每一块
非技术人员做 AI coding,最大的心理障碍是"代码看不懂"。
实际上,你不需要看懂每一行代码。你需要看懂的是"每一块代码在做什么"。方法很简单:让 AI 给你解释。每次它写完一个模块,你说"解释一下这段代码的思路",它会用自然语言给你讲。
你能理解的部分,验证它是否符合你的需求。你不能理解的部分,跑一遍看效果。效果对了就过,效果不对就说清楚哪里不对。
5. 遇到报错,把完整错误信息给 AI
这是最省 Token 的调试方式。不要自己翻译错误信息,不要只截一段报错给 AI。把完整的错误日志(包括 stack trace)直接贴过去,让 AI 自己分析。
AI 从完整日志中定位问题的能力,远强于从你转述的片段中猜测。这不是偷懒,是效率最大化。
6. 一个问题的修改可能引发另一个问题
在 AI coding 过程中,最危险的不是单个 bug,而是连锁反应。你修复了一个 TypeScript 编译错误,结果引入了一个运行时类型不匹配。你修改了 Entity 定义,结果 TypeORM 的 synchronize 又出问题了。
应对方式: 每次修改后,立即跑 build + 冒烟测试。不要攒着一起改。每改一处,验证一处。这比一口气改 10 处然后花一整天排查要高效得多。
7. 部署不是最后一步,是贯穿全程的事
很多人的做法是:本地开发完成 → 部署。但部署本身就是一个复杂的工程环节。我的建议是:第一天就尝试部署,哪怕只部署一个空壳。部署成功了,后续每次提交都有线上验证。
如果最后才部署,你会发现一堆环境问题(环境变量、Docker 配置、网络、数据库),解决这些问题可能比开发本身还耗时。
十一、一些数字
代码量: 140 个源文件,24000 行代码(不含 node_modules 和 dist)
Git 提交: 92 次
开发周期: 5 天(4月29日 — 5月3日)
技术栈: React + NestJS + Python FastAPI + SQLite + Docker
部署服务: Railway(后端)+ Cloudflare Pages(前端)
Token 成本: 约 200-400 元人民币
截图数量: 288 张(开发过程中的每个关键节点都有截图记录)
核心模块: 5 个(Skill 管理、智能体管理、Agent Runtime、知识库、权限系统)
Agent 工具: 8 类(文档生成、代码执行、互联网搜索、数据分析、图表生成、文件操作、知识库检索、网页抓取)
十二、写在最后:AI Coding 改变的是什么
Anthropic 在 2026 年的 Agentic Coding 趋势报告里写了一句话:"编程能力正在民主化,非技术人员开始构建自己的工具。"我不是看了这份报告才开始的,但做完项目再看这段话,感受完全不同。
因为"民主化"不是一个抽象概念——它是实实在在的。一个产品经理,5 天时间,24000 行代码,一个上线运行的全栈平台。这在两年前是不可能的。
但我想说的是另一面。
AI coding 改变的不是"谁会写代码",而是 "谁有能力定义问题"。
在传统开发模式里,产品经理和程序员之间有一条清晰的边界:产品经理负责"做什么",程序员负责"怎么做"。这条边界的存在,是因为"怎么做"的门槛很高——你需要学编程语言、学框架、学部署、学调试。
AI coding 降低了"怎么做"的门槛,但它没有降低"做什么"的门槛。恰恰相反——当"怎么做"不再是瓶颈的时候,"做什么"变成了唯一的瓶颈。
你需要知道做出来的东西用户会不会用。你需要知道哪些功能该砍、哪些该留。你需要在 502 崩溃的时候判断是数据库的问题还是网络的问题。你需要在 Token 预算有限的时候决定哪里用便宜模型、哪里用贵模型。
这些判断力,不是 AI 能给你的。它来自你的产品经验、你的业务理解、你对用户需求的洞察。
所以,如果你也是一个非技术人员,想尝试 AI coding,我的建议是: 从一个你真正理解的问题开始。
不需要是一个宏大的 idea。一个你自己工作中的痛点、一个你每天重复的操作、一个你觉得"应该有工具但就是没有"的场景——这些就是最好的起点。因为你对问题的理解越深,AI 的输出质量就越高。
AI coding 不是一个让非技术人员变成程序员的技术。它是一个让每个人都能把自己的专业能力"代码化"的技术。你不需要学编程,你只需要知道自己想做什么。
剩下的,AI 会帮你。
— 全文完 —