V1从跑通到放弃 be Coding初体验如何通过Vibe Coding从零构建一个Agent对于LLM和Agent我之前只是粗浅地了解过没有相关的技术背景但是既然SNS上把Vibe Coding吹的神乎其神叠加此时的养龙虾热我自然是信心满满。开发流程很简单打开对标的产品先体验其交互然后告诉Claude Code“我要有XXX功能这个功能需要XXX”/“页面布局为XXXXX”等等等等。等Claude Code写代码我启动服务器进行测试发现有bug就让Claude Code继续改如此循环。不出意外遇到了很多问题前端交互改起来很费时间我毕竟是后端出身对于前端没有那么了解同一个bug反复改很久才改好。有时还会出现bug1修了1天修好了开始修bug2bug2修好了bug1又重现了。大模型限流。虽然是公司提供的coding plan但是用的太狠还是限流。但说来也怪尽管各种不顺Vibe Coding 会让人上瘾。一旦开始写代码完全停不下来有点像刚毕业那会儿大展拳脚的感觉——把想法丢给 AI看着代码在面前长出来那种即时反馈让人沉迷甚至游戏都不香了。V1跑通了跑不动了经过一点一点探索和尝试还真的把 Agent 写出来了也就是 Cloud Agent V1。它用 Python FastAPI 搭建6 周时间、170 个commit多次squash实际更多、约 1.7 万行代码纯 Vibe Coding没有手写一行代码。V1 的核心是 LLM 输出带 XML 标签的 Python 脚本正则解析后在沙箱环境执行。能对话、能操作文件、能执行脚本、能加载 Skill、能调用 MCP跑通了完整链路。3 月份的各种产品演示都靠它撑了下来但每次演示前心里都在打鼓——怕 LLM 输出跑偏怕对话突然卡死。能跑但没有任何优势。CherryStudio、Openclaw 这类开箱即用的 Agent 同样能对话、能操作文件、能接 MCPV1 没有差异化。更要命的是V1 已经改不动了继续加功能只会让它更不可控。下面说致命的部分。V1 的致命伤致命伤 一句话 直接后果XML 当协议 LLM 生成任意 Python 脚本正则提取执行 不可靠、不可调试、无法区分错误类型上下文混乱 按轮数硬裁 提示词失控 优化全治错地方 失忆、token 烧光、越优化越慢God 类膨胀 无初始架构Vibe Coding 堆功能越堆越大 改不动、测不了、牵一发动全身致命伤一XML 标签当协议这是 V1 最根本的架构问题。系统不是通过 API 原生的 tool_use / function calling 机制执行操作而是让 LLM 用 XML 标签包裹生成的Python代码用正则匹配提取后在python沙箱执行。流程可以简化为两阶段用户输入│▼┌─────────────┐│ Judge 阶段 │ 轻量 LLM 调用 → 决定加载哪些 Skill、文件└──────┬──────┘▼┌─────────────┐│ 处理阶段 ││ ││ ◄── 循环 ──┤ LLM 生成自由代码无约束。 LLM 生成的是任意 Python 脚本不是带 schema 的函数调用。参数是凭空捏的函数名是幻觉出来的文件路径是猜的。代码语法错误、import 不存在、变量未定义全靠沙箱报错才知道。一个脚本干所有事。 LLM 倾向于把多个操作塞进一个 字符串解析就断了。唯一的恢复手段是让 LLM 再试一次但它不知道哪错了只能反复生成代码、反复失败直到运气好成功、轮数耗尽或用户放弃。沙箱文件复制的开销。 每次执行脚本前先把相关文件复制到隔离沙箱安全但每轮多一次 I/O。多轮任务跑下来大量时间耗在文件搬运上实际计算反而占比不高。致命伤二上下文管理混乱粗暴的轮数裁剪历史消息不做 token 精算唯一的措施是只保留最近 N 轮更早的直接丢弃。简单粗暴但结果是两个方向都崩保留太少聊几轮 LLM 就忘了开头说过什么反复追问用户已经回答过的问题保留太多一轮交互轻松破 10 万 token。模型也就 200K 的上下文窗口几轮就烧完了。要么触发 API 400 直接拒绝要么 LLM 静默丢弃早期上下文同样是失忆。根本不存在一个稳得住的平衡点。核心循环最多跑 50 步每步无条件追加 assistant 响应和脚本执行结果反馈到消息列表。加上聊天历史全部按轮数硬裁没有优先级、没有摘要压缩、没有关键信息标记。前面讨论的业务背景、确认过的文件路径几轮之后就跟从来没出现过一样。提示词失控系统提示词约 200 行硬编码在 Python 源码里。每次 LLM 调用动态拼接基础提示词 MCP 工具描述含完整 JSON Schema 项目文件预览Excel 表名、列名、数据样本 Skill 指令全文。一次普通业务调用提示词本身烧掉 1-2 万 token。而且每次从头构建没有缓存复用。这意味着 Skill 指令也是跟着上下文一起膨胀花大量时间和用户一轮轮调试优化 Skill 的触发条件和提示词但优化完之后塞进已经臃肿的上下文里LLM 到底有没有按指令走、触发是否准确完全不可知。优化了一整天效果全凭感觉。治错地方的优化两个失败的 token 节省策略Judge Phase开发和测试中我意识到了上下文问题设计了一个 Judge 阶段来解决它这也是 V1 里我的原创设计。想法不复杂每次执行任务前先做一次轻量级 LLM 调用判断用户要处理哪些文件、需要加载哪些 Skill然后只把筛选后的内容注入完整上下文。想法没问题但忽略了一个基本账本多一次 LLM 调用用户就多等一轮。每次操作都要先等 Judge 返回再等执行结果响应速度直接被拖慢。如果能用轻量模型来做消耗倒不至于太大。但当时根本没往这想。而且 Judge Phase虽然削减的是文件预览和 Skill 内容但上下文真正的大头是历史对话。前几轮生成的大段 Python 脚本、沙箱返回的几千字节执行结果、反复重试的失败记录。省掉的提示词跟历史对话这个黑洞比完全是杯水车薪。File Preview类似的还有文件预览机制。我观察到一个规律LLM 处理文件时总是先瞄一眼Excel 读第一个 Sheet 的前几行PDF 看前几页文本从不会一上来就做全量分析。于是加了一套文件预览上传时解析一次Excel 提取表名和样本数据PDF 提取文本Word 提取段落和表格结果存为 preview_data。Judge 阶段只发精简版文件名 维度处理阶段发完整版含样本行和文本摘录。思路和 Judge 一样用空间换 token。但问题也一样根本没做缓存复用。同一份 Excel 预览数据循环 50 步就在 50 次 LLM 调用里原样发了 50 遍每次都是从头拼系统提示词。V1 的优化始终停在传什么层面从没触及怎么不反复传。后者要等 V2 的 prompt caching 才真正解决。致命三God 类膨胀和架构失控最根本的问题是我一开始就没定架构。不是因为偷懒而是此前从没做过类似的应用根本不知道该长什么样。Vibe Coding 的方式是描述功能让 AI 写不是先画蓝图再施工。结果是架构随功能有机生长每多加一个模块前面的设计债务就重一层。executor.py2000 行。这一个类干了多少事判断阶段Judge、执行阶段Execute、脚本运行、MCP 过滤、重试逻辑、错误处理、上下文拼接。全部耦合在一个类里没有清晰边界。除了它context.py 900 行chat_service.py 600 行每个都是同样的毛病。开发过程中其实也让 AI 帮忙做过架构优化分模块、拆文件、抽函数、建分层这些 AI 都能执行。但有两个问题。第一AI 只负责当前这次修改没人持续盯着全局结构。今天拆出去三个函数明天为了修一个 bug 又塞回两个后天加新功能再堆一层 if-else。第二架构优化只在版本稳定时才能做功能跑通了、演示没压力了才敢动手。平时改需求、修 bug 时根本不敢大动结构怕拆出新问题修不回来。结果优化窗口越来越窄债越欠越多。重写还是重构这个决策我纠结了将近一周。不是因为看不清方向而是沉没成本太重。V1 毕竟是可以用的。3 月份好几场产品演示都靠它扛下来的虽然每次演示前提心吊胆但功能确实一项项跑通了。而且已经加了一个月的班每天跟 AI 较劲到半夜好不容易折腾出一个能跑起来的版本。调研项目有公司的时间节点不是无限期探索。推倒重来意味着前面一个月的加班全部归零新方案能不能按时跑出来当时根本没底。与此同时用户提的 bug 越攒越多。修好一个冒出两个越来越看不到头。但继续在 V1 上修补代价同样算得清。前文提的三个致命伤每一个细看都不是重构能解决的。继续修补 V1 推倒重写──────────── ──────────✓ 能跑、演示扛住了 ✓ 三个致命伤重构解决不了✓ 加班成果不归零 ✓ 参考其他开源Agent源码但不知道选哪个✗ 时间节点越来越不可预期 ✗ 一个月加班归零风险未知✗ bug 越修越多看不到头 ✗ 1.7 万行代码作废✗ 架构缺陷是骨架层的问题XML 标签当协议是 V1 的根基。把 XML 解析换为标准 tool_use意味着整个 agent loop 从 executor、parser、context 到 LLM 调用链路全部推倒。这不是重构 executor.py 的一部分而是删除它存在的理由。即使有 Vibe Coding重构的工作量也不会少。零测试兜底意味着每次改完只能靠人肉验证告诉 AI “这里有问题改成 X”跑一遍发现崩溃了再告诉 AI 修崩溃再跑一遍。还有一个语言层面的问题V1 用 Python 只是因为当时熟悉 Python并不意味着后端就应该用 Python。Claude Code 源码是 TypeScript 写的要继续深入参考它的设计用同一种语言显然比在 Python 和 TypeScript 之间做概念翻译更顺畅。继续守着 V1 的 Python 代码意味着往后的每一轮优化都在隔着一层语言做映射。这个成本重构省不掉。最后一个砝码V1 还处于内部小范围 demo 阶段没有历史数据要兼容没有线上用户要迁移。推倒重来最重的代价只是扔掉代码不需要做数据迁移、协议兼容、灰度切换这些工作。V1 的价值在于验证方向、积累认知不在于那 1.7 万行代码本身。契机当我在纠结要不要重写时Claude Code 的源码泄露了。消息出来那天我就把源码拉了下来不过比起直接啃源码真正帮我下定决心的是社区里陆续出现的解读文章。这些文章讨论的方向主要有几个Agent 循环设计tool注册和调度prompt caching 的分段策略上下文压缩的分级机制多 Agent 的协作模式权限系统的分层拦截当时我看得似懂非懂很多概念还没建立起完整的认知。但我知道这就是我应该参考的方向。经过一个多月高强度使用 Claude Code再看社区的评价感受更确定了。大家反复提的几个点和我自己的体验完全重合对代码库的理解不像关键词搜索更像一个读完代码再动手的工程师多文件重构时不会拆东墙补西墙共享逻辑自然合并每一步操作都附带自解释的上下文像一个不需要文档的工具。更棒的是Claude Code并不是一个纯粹面向coding而是面向通用工作设计的Agent即使直接将财务领域或其他业务领域的文件丢给它处理它也能三下五除二地搞定这对我来说足够了。一个让我每天用都不烦的设计一定是值得跟着走的。再次抉择用 SDK 还是尽可能参考源码参考方向有了怎么落地组里一直有声音建议直接用 Claude Code 的 SDK。毕竟官方封装好了 agent loop、工具调度、流式处理上手最快。但经过前面一个多月的折腾我很清楚这次不能只图快。如果只是用 SDK 拼业务逻辑不过是换了一套 APIV1 的架构问题一个也解决不了。动手重写前我做了最后一次评估。方案 A基于 Claude Code SDK。 anthropic-ai/claude-agent-sdk 封装了 agent loop、工具调度、流式处理接入即用。优点是开发周期短缺点是架构受 SDK 约束权限模型、缓存粒度、中断机制、SSE 事件定义能用但不能改。方案 B参考 Claude Code 源码自行实现。 研究 Claude Code 的架构设计、技术栈选择、模块划分用自己的方式重写一遍。优点是每一层都可控缺点是工作量大。我选了方案 B。理由四个控制力。 SDK 封装了核心能力使用方只能按它的接口接入。我需要的是自定义每一个关键环节工具执行策略怎么设计、权限模型怎么隔离、缓存粒度怎么控制、中断机制怎么触发、SSE 事件怎么命名和传递。这些在 SDK 里是封闭的在源码里是透明的。集群部署。 SDK 的心智模型是单机运行fork process 隔离。项目一开始就规划了集群部署多实例 会话亲和 状态外置 SSE 跨节点转发。这要求 HTTP 层和流式传输层都是自主可控的。源码方式从 Hono server 到 SSE 流全是自己的做分布式改造时不会有SDK 封装的东西改不了的尴尬。技术栈对齐。 Claude Code 本身就是 TypeScript Bun 构建的。V2 选同样的技术栈模块结构、类型体系可以和参考实现保持一致降低理解成本。技术积累。 实际的开发方式不是读完源码再动手写而是让 Agent 写代码并同步整理技术文档辅助理解。遇到拿不准的地方回到 Claude Code 源码看对应的实现然后在Claude Code 里复现同一个场景观察它是怎么处理的。源码不是照着抄的模板是遇到问题随时回去查的参考答案。V2 的技术方向┌──────────────────────────┬──────────────────────────┬───────────────────────────┐│ 原则一 │ 原则二 │ 原则三 ││ 技术栈靠拢 Claude Code │ 按模块推进不照抄 │ 预留集群扩展空间 │├──────────────────────────┼──────────────────────────┼───────────────────────────┤│ TS Bun Zod 对齐 cc │ 提取核心设计思想 │ 会话外置 → SQLite / JSONL ││ Hono 做 HTTP原生 SSE │ 适配需求做改写和简化 │ SSE → 预留跨节点转发接口 ││ React ViteWeb 前端 │ 先确保能跑起来 │ 文件 → 抽象 storage 层 ││ SQLite 持久化 │ 卡住时回源码查参考答案 │ 不假设单机杜绝以后改不了 │└──────────────────────────┴──────────────────────────┴───────────────────────────┘动手之前定了三条原则。第一技术栈向 Claude Code 靠拢。 理由很简单Claude Code的源码是现成的参考答案同一种语言翻起来最顺畅。具体选型以 Claude Code为基准场景不同的地方做适配层面 Claude Code V2 说明运行时 Bun Bun 一致语言 TypeScript TypeScript 一致校验 Zod Zod 一致UI Ink React终端 React Vite浏览器 Claude Code是 CLI 工具V2 面向 Web 用户HTTP 层 — Hono cc 无需 HTTP serverV2 需要选 Hono 是因为轻量、原生支持 SSE 流存储 — SQLite cc 主要操作本地文件系统V2 需要持久化会话、用户、配置数据第二按功能模块推进不搞像素级拷贝。 Claude Code是通用 CLI 工具V2 是面向业务的 Web 应用场景不同决定了不能全抄。开发策略是从源码提取核心设计思想适配自己的需求做改写和简化在和Claude Code的流程一致的前提下先确保能跑起来。当简化版确实满足不了需求时再回头参考源码看 Claude Code 在同类场景下是怎么处理的。第三预留集群部署的扩展空间。 项目规划中就有多实例部署的需求。这意味着从第一行代码开始就要考虑状态不能长在进程内会话数据外置到 SQLite/JSONLSSE 连接不能假设单机跨节点转发预留接口文件存储不能依赖本地磁盘抽象 storage 层。不一定一开始就把集群搭起来但架构上不能有以后改不了的单机假设。V1 的代码被全部丢弃但 V1 验证的方向Skill 系统、MCP 集成、产品形态全部保留。Vibe Coding 实战心得除了V1本身的经验教训外我还总结了一些通用的Vibe Coding经验。善用 git 做小步提交。 每次 commit 只做一件事。commit 粒度太大前端改版 后端调整 提示词修改全塞一起出了 bug 根本定位不到哪次改动引入的。更常见的是 bug A 修好了下一个改动又把它带回来因为提交太乱AI 理不清哪些代码是修 bug 的、哪些是新功能的。小步提交、每个 commit 可独立回滚省掉大量排查时间。控制上下文窗口。 不论是 Vibe Coding 还是设计 Agent上下文管理都是 AI 时代程序员的核心能力。对话长了 AI 会忘事前面说过的规则、约定、已经修好的 bug一旦被压缩出去就不在了。压缩本质是丢信息没有两全方案。所以实际开发中要刻意保持对话聚焦一个需求通路走到底就开新会话不要在一条里反复横跳。把 AI 的记忆当成一种需要主动管理的稀缺资源而不是默认它什么都能记住。自己管运行环境别让 Agent 插手。 可能是我用的LLM能力不足Agent 启动的服务有时候 kill 不掉端口被占着回收不了只能手动 lsof -i 再 kill -9。吃过几次亏之后就定了规矩Agent 只负责生成代码人负责启动