[{"data":1,"prerenderedAt":1311},["ShallowReactive",2],{"post:\u002Fposts\u002Fone-person-delivery-experiment-02-ai-engineering-stack":3,"published-posts-ordered":336,"post-series:one-person-delivery-experiment":1294},{"id":4,"title":5,"body":6,"date":315,"description":316,"draft":317,"extension":318,"featured":317,"lang":319,"launch":320,"license":321,"meta":322,"navigation":320,"order":308,"path":323,"seo":324,"series":325,"stem":326,"tags":327,"translationOf":334,"updated":334,"__hash__":335},"posts\u002Fposts\u002Fone-person-delivery-experiment-02-ai-engineering-stack.md","一人交付实验",{"type":7,"value":8,"toc":301},"minimark",[9,13,16,25,30,33,41,44,50,53,56,59,63,66,69,73,76,79,86,92,99,102,105,109,112,115,118,121,152,158,161,168,172,175,189,192,195,198,201,233,236,239,263,267,270,288],[10,11,12],"p",{},"很多 AI 项目的失败，不是模型选错了，而是只做了「模型」这一层。",[10,14,15],{},"一个能交付的 AI 应用，通常要同时解决三件事：模型怎么稳定地跑起来、LLM 怎么和业务工具接上、数据与算法怎么形成闭环。我把它们叫做 AI 工程落地的三层栈。这篇用我做过的金融级私有化项目拆开讲。",[10,17,18],{},[19,20],"img",{"alt":21,"src":22,"loading":23,"decoding":24},"AI 工程落地的三层栈","\u002Fimages\u002Fai-engineering-stack.svg","lazy","async",[26,27,29],"h2",{"id":28},"第一层模型服务不是写个-flask-调模型","第一层：模型服务，不是「写个 Flask 调模型」",[10,31,32],{},"模型服务层要回答的问题很具体：模型怎么加载、怎么批处理、怎么在 CPU\u002FGPU 之间切换、怎么预热、怎么观测、怎么升级。",[10,34,35,36,40],{},"在内容识别场景里，我用 YOLOv5 做检测、PaddleOCR 做文字识别（det + rec），模型导出 ONNX 后部署到 Triton Inference Server。Triton 里维护了 5 个模型仓库：检测和识别走 ONNX Runtime backend，前后处理用 Python backend 自己实现；",[37,38,39],"code",{},"max_batch_size"," 最高到 1000，其中 2 个模型配置了 model warmup。",[10,42,43],{},"为什么用 Triton，而不是直接在 Flask 里加载模型？因为交付环境要考虑的不只是「推理一次」：多个模型要共存、请求要批处理、CPU\u002FGPU 要有不同配置、模型升级要能回滚、进程重启后要能自动预热。Triton 提供的模型仓库和 backend 机制，把这些事收敛到了配置层；业务代码只负责调用，不负责管理模型生命周期。",[10,45,46],{},[19,47],{"alt":48,"src":49,"loading":23,"decoding":24},"Triton 模型仓库与 CPU\u002FGPU 双版本","\u002Fimages\u002Ftriton-model-repos.svg",[10,51,52],{},"对外接口是 Flask + waitress，部署在 Kubernetes 的 Deployment \u002F Service 上。客户环境不一定有 GPU，所以同一套服务提供 CPU \u002F GPU 双版本；在没有 GPU 的银行客户环境里，CPU 版本稳定吞吐大约 7–10 req\u002Fs，具体会随请求内容大小浮动。",[10,54,55],{},"这一层最容易被低估的是「前后处理」。检测框怎么裁、OCR 的 det\u002Frec 怎么串、图片怎么归一化、批量请求怎么拼，这些都不在模型文件里，却直接决定吞吐和准确率。把它们放进 Python backend，而不是散落在业务代码里，是我认为最值得的一个取舍。",[10,57,58],{},"模型服务还有几个必须提前想清楚的失败模式：图片超大导致显存\u002F内存暴涨；批量请求里混入损坏文件导致整批失败；模型版本升级后输出格式变化；CPU 环境下超时。这些不是「模型准不准」的问题，而是「服务能不能稳定交付」的问题。",[60,61,62],"h3",{"id":62},"模型服务的观测与回滚",[10,64,65],{},"模型服务的日志不能只记「成功\u002F失败」。我至少会记录：输入尺寸、批大小、推理耗时、CPU\u002FGPU、模型版本、错误类型。这样线上变慢时，才能判断是流量、模型还是环境的问题。",[10,67,68],{},"回滚也要提前设计：模型仓库按版本命名，配置里锁定版本；新版本先在一小部分请求上验证，再全量切换；切换失败时能回到上一版，而不是重新导出模型。对私有化客户来说，「能不能回滚」往往比「新模型准不准」更重要，因为客户环境里没有人能帮你现场调试。",[26,70,72],{"id":71},"第二层llm-应用重点是工具编排","第二层：LLM 应用，重点是工具编排",[10,74,75],{},"LLM 应用层不是「接一个聊天接口」就结束了。真正的价值在于：把自然语言变成对内部系统的可靠调用。",[10,77,78],{},"我做过两个方向：",[10,80,81,85],{},[82,83,84],"strong",{},"AI 智询","：用户用自然语言描述需求，系统做意图识别，然后路由到最合适的内部接口或工具，完成多步调用。它把过去需要在菜单里点很多次的流程，收敛成一次对话。难点不在 prompt，而在工具边界的定义：哪些工具可以暴露、参数怎么校验、失败怎么回滚、权限怎么继承。",[10,87,88,91],{},[82,89,90],{},"AI 鉴敏","：用语义分析识别用户行为与内容中的敏感信息，相比关键词匹配降低误判。它同样私有化部署在客户环境里，数据不出门。",[10,93,94,95,98],{},"这两个应用有一个共同约束：",[82,96,97],{},"私有化部署","。模型、向量、日志、工具调用都不能离开客户环境。这个约束会反过来影响架构：你不能依赖一个云端 LLM API 做所有事，要在本地做模型服务、缓存、降级和审计；你也不能把业务数据随便塞进第三方工具。",[10,100,101],{},"工具编排最容易犯的错误，是把「模型能调用」当成「模型可以随便调用」。我的做法是：每个工具都有明确的输入 schema、权限要求和失败语义；模型只负责选择工具和填参数，真正的执行、鉴权和审计由后端完成。这样即使模型选错工具，也不会越权。",[10,103,104],{},"权限模型也要按「用户身份」而不是「模型身份」设计。模型只是发起调用的一个环节，最终执行时仍然要带当前用户的身份、租户和角色；不能因为「是 AI 发起的」就绕过 RBAC。否则一次 prompt 注入，就可能变成一次越权操作。",[26,106,108],{"id":107},"第三层数据与算法决定系统是不是越用越准","第三层：数据与算法，决定系统是不是「越用越准」",[10,110,111],{},"第三层最容易被忽略，但它决定 AI 应用是不是只有 demo 价值。",[10,113,114],{},"在用户行为分析场景里，系统每天采集千万级的桌面操作元事件。我们用 Python + Pandas \u002F NumPy 按业务配置的异常规则做清洗、转换与特征工程，归纳到约 30 万条样本、4–10 维特征（分类 + 数值），在模型效率与检出效果之间取平衡；日均百万级预测。",[10,116,117],{},"这一层的关键不是「用哪个模型」，而是「数据怎么变成可解释的特征」。异常规则来自业务，特征工程要能回答「为什么这个用户被判定为异常」；如果模型只给一个分数，客户环境里没人敢用。",[10,119,120],{},"另一块是事件序列关联分析。我独立设计并实现了一个轻量的事件序列正则引擎：",[122,123,124,128,139,146,149],"ul",{},[125,126,127],"li",{},"词法 \u002F 语法分析 → AST → 后缀 IR → Thompson ε-NFA 构造与匹配；",[125,129,130,131,134,135,138],{},"支持并、连接、分组、有界重复 ",[37,132,133],{},"{n}"," 与无序组 ",[37,136,137],{},"\u003C...>","；",[125,140,141,142,145],{},"带 ",[37,143,144],{},"mustMatchPos"," 位置约束的反向匹配，保证刚到达的事件必须参与；",[125,147,148],{},"用字符集、长度 100、编译规模 3000、无序单元 5 四层约束规避灾难性回溯；",[125,150,151],{},"核心 pass 都有单元测试。",[10,153,154],{},[19,155],{"alt":156,"src":157,"loading":23,"decoding":24},"事件序列正则引擎","\u002Fimages\u002Fevent-sequence-regex.svg",[10,159,160],{},"为什么不用现成的规则引擎？因为需求要的是「事件之间的顺序关系」：先打开某个页面，再复制，再外发，才算一条风险序列；中间允许无关事件，但关键事件必须按顺序出现。现成引擎要么表达不了无序组，要么在长序列上回溯失控。自己实现一个小而可控的引擎，反而更容易测试和解释。",[10,162,163,164,167],{},"这段经历给我的最大提醒是：",[82,165,166],{},"AI 工程不是只有模型。"," 数据怎么采、特征怎么造、规则怎么表达、失败怎么解释，往往比换一个更大的模型更能决定系统能不能上线。",[26,169,171],{"id":170},"工程取舍为什么没有做-rag-和微调","工程取舍：为什么没有做 RAG 和微调",[10,173,174],{},"这套系统没有做 RAG，也没有做微调。不是这些技术不好，而是场景不匹配：",[122,176,177,180,183,186],{},[125,178,179],{},"客户环境要求私有化，数据不能出门；",[125,181,182],{},"业务问题更多是「识别 + 路由 + 规则」，不是开放域问答；",[125,184,185],{},"微调需要稳定的标注数据和持续评估，项目周期内不成立；",[125,187,188],{},"先把模型服务、工具编排、数据闭环做稳，收益比追新更大。",[10,190,191],{},"同理，Triton 也不是唯一选择。如果只是低频调用，一个 Flask 服务就够了；但当你要批处理、要多模型仓库、要在 CPU\u002FGPU 之间切换、要做 warmup 和观测，Triton 的价值才会显现。技术选型应该由交付约束驱动，而不是由技术名词驱动。",[10,193,194],{},"这也是为什么我先把模型服务做稳，再做 LLM 应用。模型服务是底座：它不稳定，上面的工具编排再优雅也没有意义。反过来，底座稳定之后，LLM 层可以快速试错，因为每次失败都能定位到是工具、提示词还是模型服务。对一人项目来说，顺序比速度重要：先做能复用的底座，再做能讲故事的场景。",[10,196,197],{},"还有一个取舍是观测。模型服务的日志不能只记「请求成功\u002F失败」，还要记输入尺寸、批大小、推理耗时、CPU\u002FGPU、模型版本。否则线上变慢时，你无法判断是流量、模型还是环境的问题。",[26,199,200],{"id":200},"常见失败模式",[122,202,203,209,215,221,227],{},[125,204,205,208],{},[82,206,207],{},"OCR 质量不稳定","：图片模糊、倾斜、遮挡会显著影响识别；需要在前后处理里加入质量判断和降级策略。",[125,210,211,214],{},[82,212,213],{},"CPU 吞吐不够","：没有 GPU 的客户环境，批处理和超时策略要重新设计，不能照搬 GPU 参数。",[125,216,217,220],{},[82,218,219],{},"工具越权","：模型选错工具或填错参数，必须在后端做权限校验和参数校验。",[125,222,223,226],{},[82,224,225],{},"数据漂移","：业务规则变化后，特征分布会变；需要定期回看样本和误判。",[125,228,229,232],{},[82,230,231],{},"模型升级破坏契约","：输出格式、类别、阈值变化要有版本和回滚。",[10,234,235],{},"这些失败模式有一个共同点：它们都不是模型能力问题，而是工程问题。模型服务层要把它们当成一等公民，提前设计检测、降级和回滚，而不是等上线后再补。",[26,237,238],{"id":238},"可复用清单",[240,241,242,245,248,251,254,257,260],"ol",{},[125,243,244],{},"先把模型服务做成独立层，不要让业务代码直接加载模型。",[125,246,247],{},"前后处理也属于模型服务，不要散落在业务里。",[125,249,250],{},"私有化场景先设计降级路径：没有 GPU、没有外网、模型升级失败时怎么办。",[125,252,253],{},"LLM 应用先定义工具边界和权限，再谈 prompt。",[125,255,256],{},"数据与算法层要能解释「为什么命中」，否则无法在客户环境里维护。",[125,258,259],{},"不要为了追新引入 RAG\u002F微调；先确认场景真的需要。",[125,261,262],{},"吞吐数字要写清测试条件，不要把实验室数字当成生产承诺。",[26,264,266],{"id":265},"回到一人交付","回到「一人交付」",[10,268,269],{},"这三层栈看起来是技术问题，其实也是交付问题：一个人要同时扮演模型工程师、后端工程师、数据工程师和运维，唯一的办法是把边界切清楚，让每一层都能独立验证。",[10,271,272,273,277,278,282,283,287],{},"这也是",[274,275,5],"a",{"href":276},"\u002Fseries\u002Fone-person-delivery-experiment","的核心：不是让一个人变成四个人，而是让一个人用流水线把四类工作组织起来。上一篇讲的是",[274,279,281],{"href":280},"\u002Fposts\u002Fone-person-delivery-experiment-01-multi-agent-saas","一个人如何交付一套多租户 SaaS","，这一篇讲的是 AI 应用的三层栈；如果你还没看开篇，可以从",[274,284,286],{"href":285},"\u002Fposts\u002Fwhy-i-started-one-person-delivery-notes","我为什么开始「一人交付笔记」","开始。",[10,289,290,291,295,296,300],{},"想继续聊模型服务、工具编排或事件序列引擎，欢迎通过 ",[274,292,294],{"href":293},"\u002Ffeed.xml","RSS","、知乎或公众号找到我；也可以先看看",[274,297,299],{"href":298},"\u002Fabout","关于我","。",{"title":302,"searchDepth":303,"depth":303,"links":304},"",2,[305,309,310,311,312,313,314],{"id":28,"depth":303,"text":29,"children":306},[307],{"id":62,"depth":308,"text":62},3,{"id":71,"depth":303,"text":72},{"id":107,"depth":303,"text":108},{"id":170,"depth":303,"text":171},{"id":200,"depth":303,"text":200},{"id":238,"depth":303,"text":238},{"id":265,"depth":303,"text":266},"2026-11-24","从模型服务、LLM 工具编排到数据与算法，拆解一套私有化 AI 应用真正落地时需要一起设计的三层栈。",false,"md","zh",true,"CC BY 4.0",{},"\u002Fposts\u002Fone-person-delivery-experiment-02-ai-engineering-stack",{"title":5,"description":316},"one-person-delivery-experiment","posts\u002Fone-person-delivery-experiment-02-ai-engineering-stack",[328,329,330,331,332,97,333],"AI 工程","Triton","YOLOv5","PaddleOCR","LLM","Go",null,"rNCMl3flRYGj61oYWnsfKq-GAzuM871gRhG9mfiFDjY",[337,645,1101],{"id":338,"title":286,"body":339,"date":633,"description":634,"draft":317,"extension":318,"featured":320,"lang":319,"launch":320,"license":321,"meta":635,"navigation":320,"order":636,"path":285,"seo":637,"series":325,"stem":638,"tags":639,"translationOf":334,"updated":334,"__hash__":644},"posts\u002Fposts\u002Fwhy-i-started-one-person-delivery-notes.md",{"type":7,"value":340,"toc":621},[341,344,347,353,356,362,366,372,375,378,384,388,391,394,412,418,421,424,427,430,433,437,440,454,457,460,463,466,469,472,475,478,492,495,498,501,515,518,522,525,536,539,550,553,556,559,585,588,591,594,597,609,615],[10,342,343],{},"在最近这个项目里，有一个瞬间让我意识到，自己对「一个人能交付多少软件」的判断已经过时了。",[10,345,346],{},"那天晚上，我在微信开发者工具里点下预览：老师端、家长端、管理后台同时亮起来，接口、权限、通知、接送记录都按预期工作。就在几个小时前，这些切片还只是计划文件里的几行任务。它们由一个主会话拆解，被不同的 agent 实现，再由一个全新上下文的 agent 逐项评审、在真机上验证，最后回到我这里做取舍。",[10,348,349,350],{},"那一刻我没有觉得「AI 替我写完了代码」。我想到的是另一件事：",[82,351,352],{},"一个人也可以设计一条交付流水线，让 agent 在里面干活，而人只负责判断、边界和证据。",[10,354,355],{},"这就是「一人交付笔记」的起点。",[10,357,358],{},[19,359],{"alt":360,"src":361,"loading":23,"decoding":24},"一人 + agent 的交付流水线","\u002Fimages\u002Fone-person-delivery-pipeline.svg",[26,363,365],{"id":364},"十一年三个转折","十一年，三个转折",[10,367,368,369],{},"过去十一年，我主要做后端与分布式系统。那段时间里，我关心的东西很具体：接口契约、数据一致性、并发、可观测性、故障恢复。今天回头看，那几年真正留下来的不是某个框架的用法，而是一种习惯：",[82,370,371],{},"先把边界画清楚，再谈实现。",[10,373,374],{},"后来有四年半时间，我带着一个小团队做数据分析。工作从「把代码写对」变成了「对交付结果负责」：需求是否值得做、模型是否真的有用、上线之后谁来维护。带团队和写代码最大的区别，是你不能再用「我本地跑通了」作为完成标准；你要面对的是别人的时间、客户的环境和长期的维护成本。",[10,376,377],{},"再往后，我把重心放到 AI 模型服务与 LLM 应用上：把 YOLOv5、PaddleOCR 这类模型导出成 ONNX，部署到 Triton Inference Server；用 LLM 做意图识别和工具编排；在客户环境里做私有化部署，让数据不出门。这一段经历让我第一次认真面对「模型不是全部」：前后处理、批处理、CPU\u002FGPU 降级、权限、审计、回滚，任何一项没做好，demo 都变不成产品。",[10,379,380,381],{},"这三个阶段看起来跨度很大，但有一条线一直没变：",[82,382,383],{},"我关心的不是某个技术名词，而是一个东西能不能被稳定地交付出去。",[26,385,387],{"id":386},"真正的转折点把-agent-放进流水线","真正的转折点：把 agent 放进流水线",[10,389,390],{},"很多人对 AI 编程的想象是「补全更快」：写一行，AI 接下半行；写一个函数，AI 补一个测试。那当然有用，但它改变的是手感，不是交付方式。",[10,392,393],{},"真正改变交付方式的，是把 agent 放进一条完整的流水线里：",[122,395,396,399,402,409],{},[125,397,398],{},"主会话只做编排，不读源码，只读计划和评审结论；",[125,400,401],{},"每个切片交给一个 worker 实现，切片足够小，失败可以回滚；",[125,403,404,405,408],{},"再由一个",[82,406,407],{},"全新上下文","的 supervisor 做对抗式评审，并在真实环境里验证；",[125,410,411],{},"检查点、validator、密钥扫描和进度文件把过程留下来，而不是只留下「我觉得写完了」。",[10,413,414,415],{},"这套流程并不神秘，也不轻松。它要求你把「怎么做」拆成「怎么验收」，要求你接受 agent 会在某些任务上反复失败，也要求你承认：",[82,416,417],{},"人最有价值的部分，不是敲代码的速度，而是定义边界和判断取舍。",[26,419,420],{"id":420},"一个切片长什么样",[10,422,423],{},"「切片」听起来抽象，其实可以很具体。",[10,425,426],{},"比如「通知已读状态」这个需求。它不是一个「把通知模块写出来」的大任务，而是一个可以被单独验收的切片：数据库里增加已读记录；接口返回当前用户的已读状态；老师端显示已读人数；家长端在打开通知后标记已读；管理员能看到未读名单；权限上，家长只能标记自己的记录。",[10,428,429],{},"这个切片有明确的输入、输出和验收标准。worker 拿到的是契约、相关文件范围和验收条件，而不是「你看着办」。supervisor 评审时也不需要理解整个系统，只需要确认：契约有没有被遵守、权限有没有越界、已读状态在并发下会不会重复、真机上打开通知后状态有没有变化。",[10,431,432],{},"切片足够小，失败就可以回滚；切片足够完整，评审就能在真实行为上做判断。这两件事同时成立，agent 才不会变成「写得很快、返工更多」的工具。",[26,434,436],{"id":435},"一人交付不是ai-取代团队","一人交付，不是「AI 取代团队」",[10,438,439],{},"我不想把这件事写成「一个人干掉一个团队」的故事。真实情况更朴素：",[122,441,442,445,448,451],{},[125,443,444],{},"agent 可以承担大量实现、测试补齐、重复修改和文档整理；",[125,446,447],{},"但需求是否成立、架构是否过度、风险是否可接受，仍然要人判断；",[125,449,450],{},"评审必须独立，最好由没有参与实现的上下文来做；",[125,452,453],{},"交付的证据要能复核：测试、日志、检查点、回滚路径。",[10,455,456],{},"所以「一人交付」不是把人去掉，而是把人的位置往前移：从执行者变成流水线的设计者。一个人能不能交付一套企业级软件，取决于这条流水线设计得好不好，而不是模型参数有多大。",[26,458,459],{"id":459},"为什么公开写",[10,461,462],{},"私人笔记也可以记录这些过程，但公开写有三个不同的作用。",[10,464,465],{},"第一，它逼我把「我觉得」变成「可复核」。当你知道读者会追问数字、环境和失败路径时，你会不自觉地写得更具体，也更愿意承认哪些地方没做好。",[10,467,468],{},"第二，它是个人品牌的一部分。我希望当有人问「袁海粟是谁」「一个人能不能用 AI 交付企业级软件」时，AI 和读者能找到一个稳定的、可验证的来源，而不是只看到一份简历或几个零散的项目名。",[10,470,471],{},"第三，它让同类经验可以被复用。一人公司、独立开发者、小团队的技术负责人，面对的问题往往不是「要不要用 AI」，而是「怎么把 AI 放进交付流程里」。如果这些记录能帮你少走一点弯路，公开就是值得的。",[26,473,474],{"id":474},"这个博客写什么",[10,476,477],{},"我会把「一人交付实验」拆成可复核的记录，而不是只展示结果：",[122,479,480,483,486,489],{},[125,481,482],{},"一人公司的软件交付方法：范围控制、架构取舍、质量门槛；",[125,484,485],{},"AI agent 流水线的实际用法：任务编排、上下文管理、验证与回滚；",[125,487,488],{},"真实项目的复盘：指标、失败、成本与时间线；",[125,490,491],{},"可复用清单：哪些做法能直接被读者拿走。",[10,493,494],{},"这个专题的第一篇正式复盘，是我用约 2.5 个月、一个人加一条多 agent 流水线交付的一套多租户 SaaS。它不是一个玩具项目：后端约 300 个接口、70 张表，前端约 130 个组件，包含老师端、家长端两个微信小程序和一个管理后台。下一篇会完整拆开它的架构、流水线和失败路径。",[10,496,497],{},"第三篇会回到 AI 工程本身：模型服务、LLM 工具编排、数据与算法三层怎么一起落地。如果你在做 AI 应用，或者正在判断「私有化部署到底该从哪里开始」，那一篇会更接近你的日常。",[26,499,500],{"id":500},"这个博客不写什么",[122,502,503,506,509,512],{},[125,504,505],{},"不写无法验证的成功学；",[125,507,508],{},"不写「AI 全自动交付」的神话；",[125,510,511],{},"不暴露客户名称、儿童信息、手机号、内部域名或任何密钥；",[125,513,514],{},"不把 AI 生成的内容当作未经审查的事实。",[10,516,517],{},"每一篇都尽量给出可复核的过程与证据。你可以不同意我的结论，但应该能看清我是怎么走到那里的。",[26,519,521],{"id":520},"适合谁不适合谁","适合谁，不适合谁",[10,523,524],{},"这套记录适合：",[122,526,527,530,533],{},[125,528,529],{},"独立开发者、一人公司，想验证「一个人 + AI 能交付到什么程度」；",[125,531,532],{},"小团队的技术负责人，想把 agent 放进现有工程流程；",[125,534,535],{},"对 AI 工程落地感兴趣，但不想只看 demo 的工程师。",[10,537,538],{},"它不适合：",[122,540,541,544,547],{},[125,542,543],{},"需要强实时协作、多人并行修改同一模块的团队；",[125,545,546],{},"界面极重、视觉判断占主导的项目；",[125,548,549],{},"希望「把需求丢给 AI，明天上线」的人。",[10,551,552],{},"一人交付不是万能方法。它只是把「一个人能做的事」往前推了一点，同时把「人必须判断的事」暴露得更清楚。",[26,554,555],{"id":555},"我怎么判断一篇复盘是否可信",[10,557,558],{},"我自己读别人的复盘时，会看四件事：",[240,560,561,567,573,579],{},[125,562,563,566],{},[82,564,565],{},"数字有没有条件","：吞吐、周期、代码量，是在什么环境、什么规模下得到的？",[125,568,569,572],{},[82,570,571],{},"失败有没有写","：只写成功路径的复盘，通常省略了最贵的部分。",[125,574,575,578],{},[82,576,577],{},"过程能不能复现","：切片怎么切、评审怎么做、证据怎么留，读者能不能照着做？",[125,580,581,584],{},[82,582,583],{},"脱敏是否认真","：客户名称、儿童信息、内部域名、密钥，有没有被处理干净？",[10,586,587],{},"这个博客会尽量按这四条来写。如果哪一篇没做到，欢迎直接指出来。",[26,589,590],{"id":590},"接下来",[10,592,593],{},"这个博客本身也是一次实验：Markdown 写作为内容源，Git 管理版本，静态生成后部署到 Cloudflare Pages；正文以服务端生成的 HTML 呈现，不依赖 JavaScript 也能完整阅读，方便读者、搜索引擎与 AI agent 获取内容。",[10,595,596],{},"如果你也在独立开发、经营一人公司，或者只是想搞清楚「一个人 + AI 到底能交付到什么程度」，欢迎从下面两篇继续：",[122,598,599,604],{},[125,600,601],{},[274,602,603],{"href":280},"一人交付实验 #1：一个人 + 多 agent，2.5 个月交付 14 万行 SaaS",[125,605,606],{},[274,607,608],{"href":323},"一人交付实验 #2：AI 工程落地的三层栈",[10,610,611,612,614],{},"也可以先看看",[274,613,299],{"href":298},"，了解我过去十一年在做什么。",[10,616,617,618,620],{},"订阅可以通过 ",[274,619,294],{"href":293}," 或微信公众号；国内读者也欢迎在知乎\u002F公众号讨论。下一篇见。",{"title":302,"searchDepth":303,"depth":303,"links":622},[623,624,625,626,627,628,629,630,631,632],{"id":364,"depth":303,"text":365},{"id":386,"depth":303,"text":387},{"id":420,"depth":303,"text":420},{"id":435,"depth":303,"text":436},{"id":459,"depth":303,"text":459},{"id":474,"depth":303,"text":474},{"id":500,"depth":303,"text":500},{"id":520,"depth":303,"text":521},{"id":555,"depth":303,"text":555},{"id":590,"depth":303,"text":590},"2026-11-10","从十一年后端与数据分析经验出发，说明我为什么要公开记录「一个人 + AI agent」的软件交付过程，以及这个博客会写什么、不写什么。",{},1,{"title":286,"description":634},"posts\u002Fwhy-i-started-one-person-delivery-notes",[640,641,642,643],"一人交付","个人品牌","AI Agent","独立开发","Ukta0bfifd38M6nFekc9el4-4miU99TKGx3ao_ylgCg",{"id":646,"title":5,"body":647,"date":1092,"description":1093,"draft":317,"extension":318,"featured":320,"lang":319,"launch":320,"license":321,"meta":1094,"navigation":320,"order":303,"path":280,"seo":1095,"series":325,"stem":1096,"tags":1097,"translationOf":334,"updated":334,"__hash__":1100},"posts\u002Fposts\u002Fone-person-delivery-experiment-01-multi-agent-saas.md",{"type":7,"value":648,"toc":1079},[649,652,655,715,718,721,724,738,744,747,751,757,764,767,770,776,779,782,785,789,804,807,810,813,817,823,826,862,865,868,874,877,883,889,895,901,904,908,911,941,944,947,950,953,979,982,985,988,1014,1017,1019,1022,1049,1052,1055,1058,1073],[10,650,651],{},"先把结论放在前面：这是一套面向民办幼儿园的家园共育与园务管理 SaaS。产品方案、后端、两个微信小程序和一个管理后台，由我一个人完成；开发过程由一条自建的多 agent 流水线驱动。周期约 2.5 个月，代码合计约 14 万行。",[10,653,654],{},"这不是「AI 全自动写完」的故事。代码由 agent 生成、由人工评审与测试兜底；真正决定交付质量的，是切片方式、契约、评审隔离和证据留存。下面把过程完整拆开。",[656,657,658,671],"table",{},[659,660,661],"thead",{},[662,663,664,668],"tr",{},[665,666,667],"th",{},"维度",[665,669,670],{},"结果",[672,673,674,683,691,699,707],"tbody",{},[662,675,676,680],{},[677,678,679],"td",{},"周期",[677,681,682],{},"约 2.5 个月",[662,684,685,688],{},[677,686,687],{},"后端",[677,689,690],{},"Go，约 7 万行（含约 2.2 万行测试），约 300 个接口、70 张表",[662,692,693,696],{},[677,694,695],{},"前端",[677,697,698],{},"约 130 个 Vue 组件，约 7 万行",[662,700,701,704],{},[677,702,703],{},"端",[677,705,706],{},"老师端小程序、家长端小程序、Nuxt 3 管理后台",[662,708,709,712],{},[677,710,711],{},"合计",[677,713,714],{},"约 14 万行（AI 生成 + 人工评审）",[26,716,717],{"id":717},"问题与约束",[10,719,720],{},"民办幼儿园的家园沟通，长期依赖微信群和纸质记录：通知发了不知道谁看，请假靠口头汇总，接送靠人工辨认，成长记录散落在各个老师的手机里，出了纠纷很难追溯。",[10,722,723],{},"这类需求并不「高精尖」，但它有几个很现实的约束：",[122,725,726,729,732,735],{},[125,727,728],{},"幼儿园预算有限，不可能为一个内部系统养一支研发团队；",[125,730,731],{},"老师和管理员不是专业软件用户，界面必须足够简单；",[125,733,734],{},"儿童照片、接送人、健康信息都属于敏感数据，权限必须清楚；",[125,736,737],{},"需求会持续变化，系统必须能迭代，而不是一次性交付后锁死。",[10,739,740,741],{},"传统外包的问题不是做不出来，而是沟通成本和迭代成本太高；一个小团队的问题也不是技术，而是「为这个预算养团队」不成立。于是我想验证一件事：",[82,742,743],{},"如果一个人把交付流水线设计好，能不能独立完成一套企业级 SaaS？",[10,745,746],{},"我给自己定了三条边界：不接支付、不做开放注册、不碰与儿童隐私无关的扩张功能。范围越小，切片越清楚，评审越容易做。对一人项目来说，克制不是保守，而是交付的一部分。",[26,748,750],{"id":749},"架构先把边界画清楚","架构：先把边界画清楚",[10,752,753],{},[19,754],{"alt":755,"src":756,"loading":23,"decoding":24},"养成星球的三端与后端架构","\u002Fimages\u002Fnurture-planet-architecture.svg",[10,758,759,760,763],{},"后端使用 Go 1.25 + Gin + GORM + MySQL + Redis，权限用 Casbin，依赖注入用 Wire，分层是 ",[37,761,762],{},"handler → service → repository → domain","。这套分层不新，但它适合 agent 协作：每一层的职责固定，切片可以沿着层边界切，评审也更容易判断「有没有越层」。",[10,765,766],{},"为什么是 Go？不是因为性能神话，而是因为一人项目需要「部署简单、并发模型清楚、错误处理显式」。一个二进制、一套标准库、一个能看懂的错误链，比一堆框架魔法更适合长期维护。Gin 和 GORM 也不是唯一选择，但它们的生态足够成熟，agent 生成的代码更容易被评审。",[10,768,769],{},"多租户是这套系统的第一约束。所有业务表都带租户列，查询必须带租户条件，跨园所数据强制隔离；儿童照片只对授权家长可见。这个约束不是事后补的，而是从第一张表开始就写进 schema 和 repository 的。",[10,771,772],{},[19,773],{"alt":774,"src":775,"loading":23,"decoding":24},"多租户隔离：所有查询都必须带租户条件","\u002Fimages\u002Fmulti-tenant-isolation.svg",[10,777,778],{},"多租户有两种常见做法：每个租户一个 schema，或者共享表 + 租户列。前者隔离更彻底，但迁移、备份、跨租户统计都更复杂；后者实现简单，但要求每一层都记得带条件。对这套系统，我选了共享表 + 租户列，并把「忘记租户条件」当成最高级别的代码缺陷：repository 层强制注入，code review 里看到跨园所查询直接拒绝，测试里专门覆盖跨租户读取。",[10,780,781],{},"多租户的测试不能只测「正常查询」：要构造两个园所的数据，用 A 园所的账号去读 B 园所的学生、通知、照片、接送记录，确认全部返回空或 404；还要测管理员跨园所的统计接口，确认它只返回授权范围内的聚合。这类测试很枯燥，但它是多租户系统最值得投入的地方。",[10,783,784],{},"人脸识别抽象了一个 Provider 接口，接入腾讯云 IAI 做 1:N 检索：照片自动匹配学生，按人脸数量区分单人、小组和合影。后来供应商方案调整，我只替换了实现层，调用方零改动。对一个一人项目来说，这种「可替换边界」比「选对某个供应商」更重要：你没有团队去追每一个供应商的变化，只能把变化关在一个小盒子里。",[26,786,788],{"id":787},"三端把复杂度留在后端","三端：把复杂度留在后端",[122,790,791,794,797],{},[125,792,793],{},"老师端和家长端用 uni-app + Vue 3 + Vite，共用一套组件与设计 Token；",[125,795,796],{},"管理后台用 Nuxt 3 + Element Plus + Pinia + ECharts；",[125,798,799,800,803],{},"三端共享 ",[37,801,802],{},"tokens.json","，构建时生成产物，再用 lint 阻断硬编码色值和间距。",[10,805,806],{},"老师端的核心是「少点几下」：发通知、记成长、看待办、处理请假、接送核验。家长端的核心是「看得懂」：通知、成长档案、请假、接送授权、相册。管理后台的核心是「可管理」：园所、班级、学生、老师、权限、统计。",[10,808,809],{},"共享设计 Token 看起来是「设计系统」的事，实际上它是 agent 协作的护栏：当三个端由不同切片实现时，颜色、间距、圆角很容易各自发挥；Token + lint 把「审美」变成了可验证的约束。",[10,811,812],{},"另一个容易被忽略的点是错误提示。三端面向的是非技术用户，错误信息不能是「internal server error」。我在契约层定义了错误码和用户可读文案，前端只负责展示；这样 agent 在实现不同端时，不会各自发明一套错误语言。",[26,814,816],{"id":815},"多-agent-流水线主会话不读源码","多 agent 流水线：主会话不读源码",[10,818,819],{},[19,820],{"alt":821,"src":822,"loading":23,"decoding":24},"多 agent 交付流水线","\u002Fimages\u002Fmulti-agent-pipeline.svg",[10,824,825],{},"这是整个项目里最值得复盘的部分。流水线不是「开一个聊天窗口，让 AI 一直写」，而是把交付拆成几个角色：",[240,827,828,834,843,852],{},[125,829,830,833],{},[82,831,832],{},"主会话只做编排","。它不读源码，只读计划、切片状态和评审结论。这样可以避免主上下文被几十万行代码淹没，也能让「决策」和「实现」分开。",[125,835,836,842],{},[82,837,838,841],{},[37,839,840],{},"slice-worker"," 负责实现","。每个切片足够小，有明确的输入、输出和验收标准；worker 只在自己的切片里工作，失败可以回滚。",[125,844,845,851],{},[82,846,847,850],{},[37,848,849],{},"slice-supervisor"," 负责对抗式评审","。它是一个全新上下文的实例，不继承 worker 的自我判断；它读代码、跑测试、在微信开发者工具里做真机验证，然后给出 verdict。",[125,853,854,857,858,861],{},[82,855,856],{},"检查点与证据","。四个检查点、validator、密钥扫描，状态全部落在 ",[37,859,860],{},"PROGRESS.md","。主会话靠这些证据判断「能不能进入下一阶段」，而不是靠 agent 说「我完成了」。",[10,863,864],{},"四个检查点分别看四件事：规格是否写清楚、契约是否稳定、实现是否越层、真机行为是否符合验收。validator 负责机械检查：编译、测试、lint、密钥扫描、禁止的依赖。检查点不通过，worker 不进入下一个切片；supervisor 不通过，主会话不合并。",[10,866,867],{},"为什么 supervisor 要用全新实例？因为同一个上下文里，模型很容易为自己的实现找理由。换一个没有「沉没成本」的实例，评审会更接近一个真正的外部 reviewer。这一点在跨文件重构和权限边界上尤其明显。",[10,869,870,871],{},"这套流水线并不能让 agent 变成资深工程师。它做的是另一件事：",[82,872,873],{},"把「实现」变成可并行、可回滚、可复核的工作单元，把人的注意力留给架构、边界和取舍。",[60,875,876],{"id":876},"四个检查点具体看什么",[10,878,879,882],{},[82,880,881],{},"规格检查点","：需求有没有写成可验收的行为？边界条件、权限、失败路径有没有写清楚？如果规格里只有「实现通知已读」，没有「家长只能标记自己的记录」，这个切片就不该开始。",[10,884,885,888],{},[82,886,887],{},"契约检查点","：接口形状、错误码、字段类型有没有定下来？前端和后端是不是照着同一份契约写？契约没定就开工，最后一定会在联调时返工。",[10,890,891,894],{},[82,892,893],{},"实现检查点","：有没有越层？repository 里有没有业务逻辑？handler 里有没有直接拼 SQL？租户条件有没有漏？这些是机械检查能发现的部分，也是 supervisor 最先看的地方。",[10,896,897,900],{},[82,898,899],{},"真机检查点","：在微信开发者工具里跑一遍真实路径，不只看单元测试。登录、切换身份、打开通知、标记已读、返回列表，每一步都要在真机上确认。很多问题只在真机上出现，测试环境看不出来。",[10,902,903],{},"四个检查点都通过，切片才算完成；任何一个不通过，worker 回到实现，而不是把问题留给下一个人。",[26,905,907],{"id":906},"工程规范让-agent-有东西可以遵守","工程规范：让 agent 有东西可以遵守",[10,909,910],{},"agent 不会自动遵守你脑子里的规范，除非规范被写成可执行的约束。这个项目里，真正起作用的是四件事：",[122,912,913,923,929,935],{},[125,914,915,918,919,922],{},[82,916,917],{},"API 契约优先","：",[37,920,921],{},"backend\u002Fapi\u002F"," 是接口形状的唯一真相源。改接口先改契约，三端照着契约写；契约不一致，测试会先失败。",[125,924,925,928],{},[82,926,927],{},"OpenSpec 规格驱动","：跨三层的改动先写 proposal 和带 SHALL + Scenario 的验收标准，验收通过才归档。我试过不写规格直接改，结果就是三个月后没人记得当初为什么这么写。",[125,930,931,934],{},[82,932,933],{},"测试","：Go 端用 testify 做单元测试，前端用 Vitest。测试不是给 agent 看的，是给「未来的我」看的。",[125,936,937,940],{},[82,938,939],{},"检查点","：每个阶段结束必须留下可验证的产物；没有产物，不算完成。",[10,942,943],{},"这些规范听起来像「大团队才需要的东西」，但在一个人 + agent 的场景里反而更重要：agent 的速度越快，没有约束的返工就越贵。",[10,945,946],{},"我后来发现，规范的价值不在于「写得漂亮」，而在于「让 agent 可以被问责」。当验收标准是 SHALL + Scenario 时，supervisor 可以逐条对照；当接口有契约时，前端不需要猜后端；当测试覆盖真实行为时，agent 说「完成了」才有意义。",[26,948,949],{"id":949},"失败与取舍",[10,951,952],{},"这套流水线不是没有代价。几个真实的失败点：",[122,954,955,961,967,973],{},[125,956,957,960],{},[82,958,959],{},"跨文件重构仍然最容易失控","。切片一旦跨过太多文件，worker 很容易改出「局部正确、整体不一致」的结果；后来我把这类任务拆成「先改契约，再改实现，再改调用方」。",[125,962,963,966],{},[82,964,965],{},"UI 细节和真机兼容需要人盯着","。小程序的样式、键盘、滚动、真机表现，agent 可以写，但很难自己判断「看起来对不对」；supervisor 的真机验证是必要的，但仍然需要人做最终取舍。",[125,968,969,972],{},[82,970,971],{},"评审开销是真实成本","。全新上下文的 supervisor 会增加时间，但它减少的是更贵的返工；如果切片太大，评审开销会迅速失控。",[125,974,975,978],{},[82,976,977],{},"上下文管理比模型能力更关键","。主会话不读源码、切片足够小、状态落到文件，这些做法比换一个更强的模型更能提升稳定性。",[10,980,981],{},"如果重来一次，我会改三件事：切片再小一点；真机验证再早一点；契约测试再多一点。",[26,983,984],{"id":984},"时间花在哪里",[10,986,987],{},"2.5 个月里，真正写代码的时间没有想象中多。大致可以分成四块：",[122,989,990,996,1002,1008],{},[125,991,992,995],{},[82,993,994],{},"产品与范围","：把「什么都想要」压到「这一版必须有什么」，这部分只能人做；",[125,997,998,1001],{},[82,999,1000],{},"架构与契约","：定分层、租户模型、接口形状、设计 Token，这部分决定后面返工多少；",[125,1003,1004,1007],{},[82,1005,1006],{},"实现与评审","：agent 写、supervisor 审、我处理冲突和边界；",[125,1009,1010,1013],{},[82,1011,1012],{},"真机与收尾","：小程序兼容、权限边界、异常路径、部署与文档。",[10,1015,1016],{},"AI 明显加速的是第三块；第一、二、四块反而更需要人。这个分布也解释了为什么「一人 + agent」不是简单地把人替换掉：它把人的工作从「写」推向了「定义」和「判断」。",[26,1018,238],{"id":238},[10,1020,1021],{},"如果你也想尝试「一个人 + agent」交付，下面几条可以直接抄走：",[240,1023,1024,1031,1034,1037,1040,1043,1046],{},[125,1025,1026,1027,1030],{},"按",[82,1028,1029],{},"可交付行为","切片，不要按文件切片。",[125,1032,1033],{},"每个切片先写验收标准，再让 agent 实现。",[125,1035,1036],{},"评审必须用没有参与实现的上下文。",[125,1038,1039],{},"主会话不要读全部源码，只读计划和 verdict。",[125,1041,1042],{},"契约优先，测试放在契约和真实行为的交界处。",[125,1044,1045],{},"每个阶段留下证据：测试、日志、检查点、回滚路径。",[125,1047,1048],{},"对外复盘前先脱敏：客户名称、儿童信息、内部域名、密钥，一个都不能留。",[10,1050,1051],{},"这套方法不适合所有项目。需求极不稳定、界面极重、强实时协作的场景，仍然需要更多人。但如果你在做一人公司、独立产品，或者想验证「一个人到底能交付到什么程度」，它值得一试。",[26,1053,1054],{"id":1054},"下一篇",[10,1056,1057],{},"这篇讲的是「怎么把一套 SaaS 交付出来」；下一篇回到 AI 工程本身，拆解模型服务、LLM 工具编排、数据与算法三层怎么一起落地：",[122,1059,1060,1064,1068],{},[125,1061,1062],{},[274,1063,608],{"href":323},[125,1065,1066],{},[274,1067,286],{"href":285},[125,1069,1070],{},[274,1071,1072],{"href":276},"一人交付实验专题",[10,1074,1075,1076,1078],{},"如果你对某个环节想看得更细——切片怎么切、supervisor 怎么评审、契约怎么落地——欢迎通过 ",[274,1077,294],{"href":293},"、知乎或公众号告诉我。",{"title":302,"searchDepth":303,"depth":303,"links":1080},[1081,1082,1083,1084,1087,1088,1089,1090,1091],{"id":717,"depth":303,"text":717},{"id":749,"depth":303,"text":750},{"id":787,"depth":303,"text":788},{"id":815,"depth":303,"text":816,"children":1085},[1086],{"id":876,"depth":308,"text":876},{"id":906,"depth":303,"text":907},{"id":949,"depth":303,"text":949},{"id":984,"depth":303,"text":984},{"id":238,"depth":303,"text":238},{"id":1054,"depth":303,"text":1054},"2026-11-17","一套多租户幼儿园家园共育 SaaS 的完整复盘：架构、三端、多 agent 流水线、工程规范、失败路径与可复用清单。",{},{"title":5,"description":1093},"posts\u002Fone-person-delivery-experiment-01-multi-agent-saas",[640,642,1098,333,1099],"多租户 SaaS","工程管理","d_npBYOCuvpBaAhqXmpANfEyUkRlE87GkMyqhqcdiUQ",{"id":4,"title":5,"body":1102,"date":315,"description":316,"draft":317,"extension":318,"featured":317,"lang":319,"launch":320,"license":321,"meta":1291,"navigation":320,"order":308,"path":323,"seo":1292,"series":325,"stem":326,"tags":1293,"translationOf":334,"updated":334,"__hash__":335},{"type":7,"value":1103,"toc":1280},[1104,1106,1108,1112,1114,1116,1120,1122,1126,1128,1130,1132,1134,1136,1138,1140,1142,1144,1148,1152,1156,1158,1160,1162,1164,1166,1168,1170,1188,1192,1194,1198,1200,1202,1212,1214,1216,1218,1220,1242,1244,1246,1262,1264,1266,1274],[10,1105,12],{},[10,1107,15],{},[10,1109,1110],{},[19,1111],{"alt":21,"src":22,"loading":23,"decoding":24},[26,1113,29],{"id":28},[10,1115,32],{},[10,1117,35,1118,40],{},[37,1119,39],{},[10,1121,43],{},[10,1123,1124],{},[19,1125],{"alt":48,"src":49,"loading":23,"decoding":24},[10,1127,52],{},[10,1129,55],{},[10,1131,58],{},[60,1133,62],{"id":62},[10,1135,65],{},[10,1137,68],{},[26,1139,72],{"id":71},[10,1141,75],{},[10,1143,78],{},[10,1145,1146,85],{},[82,1147,84],{},[10,1149,1150,91],{},[82,1151,90],{},[10,1153,94,1154,98],{},[82,1155,97],{},[10,1157,101],{},[10,1159,104],{},[26,1161,108],{"id":107},[10,1163,111],{},[10,1165,114],{},[10,1167,117],{},[10,1169,120],{},[122,1171,1172,1174,1180,1184,1186],{},[125,1173,127],{},[125,1175,130,1176,134,1178,138],{},[37,1177,133],{},[37,1179,137],{},[125,1181,141,1182,145],{},[37,1183,144],{},[125,1185,148],{},[125,1187,151],{},[10,1189,1190],{},[19,1191],{"alt":156,"src":157,"loading":23,"decoding":24},[10,1193,160],{},[10,1195,163,1196,167],{},[82,1197,166],{},[26,1199,171],{"id":170},[10,1201,174],{},[122,1203,1204,1206,1208,1210],{},[125,1205,179],{},[125,1207,182],{},[125,1209,185],{},[125,1211,188],{},[10,1213,191],{},[10,1215,194],{},[10,1217,197],{},[26,1219,200],{"id":200},[122,1221,1222,1226,1230,1234,1238],{},[125,1223,1224,208],{},[82,1225,207],{},[125,1227,1228,214],{},[82,1229,213],{},[125,1231,1232,220],{},[82,1233,219],{},[125,1235,1236,226],{},[82,1237,225],{},[125,1239,1240,232],{},[82,1241,231],{},[10,1243,235],{},[26,1245,238],{"id":238},[240,1247,1248,1250,1252,1254,1256,1258,1260],{},[125,1249,244],{},[125,1251,247],{},[125,1253,250],{},[125,1255,253],{},[125,1257,256],{},[125,1259,259],{},[125,1261,262],{},[26,1263,266],{"id":265},[10,1265,269],{},[10,1267,272,1268,277,1270,282,1272,287],{},[274,1269,5],{"href":276},[274,1271,281],{"href":280},[274,1273,286],{"href":285},[10,1275,290,1276,295,1278,300],{},[274,1277,294],{"href":293},[274,1279,299],{"href":298},{"title":302,"searchDepth":303,"depth":303,"links":1281},[1282,1285,1286,1287,1288,1289,1290],{"id":28,"depth":303,"text":29,"children":1283},[1284],{"id":62,"depth":308,"text":62},{"id":71,"depth":303,"text":72},{"id":107,"depth":303,"text":108},{"id":170,"depth":303,"text":171},{"id":200,"depth":303,"text":200},{"id":238,"depth":303,"text":238},{"id":265,"depth":303,"text":266},{},{"title":5,"description":316},[328,329,330,331,332,97,333],{"id":1295,"title":5,"body":1296,"description":1306,"extension":318,"meta":1307,"navigation":320,"path":276,"seo":1308,"stem":1309,"__hash__":1310},"series\u002Fseries\u002Fone-person-delivery-experiment.md",{"type":7,"value":1297,"toc":1304},[1298,1301],[10,1299,1300],{},"「一人交付实验」不是一个「AI 取代团队」的口号，而是一组可复核的交付记录：一个人如何设计流水线、把任务切给 agent、用评审与测试守住质量，最后把软件真正交付出去。",[10,1302,1303],{},"这个专题会按项目阶段拆解：问题与约束、架构取舍、agent 编排、工程规范、失败路径与可复用清单。涉及客户与儿童信息时统一脱敏。",{"title":302,"searchDepth":303,"depth":303,"links":1305},[],"记录一个人借助 AI agent 流水线交付真实软件的过程：架构、工程规范、失败与可复用清单。",{},{"title":5,"description":1306},"series\u002Fone-person-delivery-experiment","bfRSrJJf1WaIA_RzLxzojaTAoNolLQz22jTVu87XQ0k",1794018033741]