为什么你写的 Agent 只是个 demo:一套运行时系统该长什么样

哈喽,我是飞飞。
前阵子有个朋友给我看他写的 Agent,几十行代码,用户问一句、模型想一下、调个工具、把结果丢回去。跑起来挺像那么回事,他挺得意。我问他:让它连着跑半小时、中途断网、读进来一个特别大的文件,扛得住吗。他愣了一下,说那不就崩了吗。
这就是 demo 和产品的分界线。我自己天天用 Claude Code,还在它上面搭了十几个 skill 跑写作流水线,越用越确定一件事。一个能交付的 Agent,难处不在模型选哪家、接了几个工具,而在模型外面那一整套东西扛不扛得住。这篇我结合自己踩过的体感,挑最有用的四条原则讲透,最后给你一条上手路径。
Agent 不是一个 prompt,是一套运行时系统
先说个最容易掉进去的坑。很多人理解的 Agent 就是这条线:用户输入,模型思考,调用工具,返回答案。这条线写 demo 够用,撑不起真东西。
成熟的 Agent 要在模型外面管一大堆事:怎么把上下文喂进去,怎么判断操作能不能做,工具失败了怎么恢复,上下文爆了怎么办,子任务跑完怎么把结果接回来。模型只是这台机器里的一个零件,难的是机器本身。
说人话就是:模型像一个聪明但健忘、还容易冲动的实习生,运行时系统就是管着他的那套规章制度和安全绳。你不能光夸他聪明,得有人盯着他别把生产数据库删了,别说太长把自己绕晕,活干到一半别掉链子。我一直挂着一个判断标准:你现在写的,是个一次性 demo,还是一个能长期跑、能从崩溃里爬起来的运行时?想清楚这个,后面的设计才有方向。
Tool 不该是个 if-else,它得是一等公民
整套系统里最该认真对待的,是工具,也就是 Tool。
很多人图快,工具就是一串 if-else:是读文件就调读文件,是发请求就调发请求。前期飞快,后期失控。等你要接 Shell、浏览器、数据库、GitHub,这堆 if-else 会膨胀成没人敢动的一坨代码。
成熟的做法是把工具升级成一个完整的协议。换个大白话讲,每个工具不能只会干活,还得自己交代清楚一堆事。我是干啥的,参数合不合法,我会不会改文件、会不会联网、会不会花钱,做之前要不要先问用户一句,出错了怎么把错误说给模型听。能答清楚这些,它才算一等公民,而不是一个裸函数。
这条我有特别真切的体感。我那十几个 skill,拉资讯的、查重的、配图的、发公众号的,没有一个是写死的 if-else。每一个都是照着 Claude Code 读 skill、认 frontmatter、调 hook 的脾气,一点点磨出来的标准件 [素材库:Claude-Code.md]。frontmatter 说人话就是文件开头那段配置声明,告诉系统这工具叫什么、什么时候触发。它们都长在同一套机制上,我加一个新 skill,不用动主流程一行代码,系统自己就认得它。加能力像插积木,不是改电路。
权限不是上线前补的弹窗,得从第一天就内建
Agent 这东西天生危险。模型会用一种特别合理的语气,干出特别离谱的事。删文件、覆盖代码、跑 Shell、动生产库、调付费接口,它都干得出来,还理直气壮。
所以权限系统不能等产品快上线了再加个弹窗补救,得从第一天就进架构。我天天用 Claude Code 干正经活,对这点感受太深。它有几种权限模式:ask 是敏感操作先问你一声,auto 是判断安全就放行,plan 是先列计划、确认了再动手,bypass 是受控环境里跳过盘问直接跑。说真的,这几档刹车就是我敢把活交给它的底气。
我让 Opus 干活之前,心里都会先过一遍秤,掂量这活值不值得动用它 [素材库:Claude-Code.md]。这种「下手前先过一道关」的绷着感,恰恰让我踏实。真要它跑一条危险命令,它会先停下来问我,不会闷头执行。这里有个原则我觉得特别精辟:默认放心让模型去想,但要谨慎放行让模型去做。想是免费的,做是有后果的,刹车踩在「做」这一步。
上下文是工作记忆,不是把聊天记录全堆进去
这是 Agent 产品的生命线,也是最容易翻车的地方。
很多人的做法是把所有东西都往 messages 里塞,工具返回啥就堆啥,越长堆得越多。短期飞快,长期会被三样东西拖垮:窗口塞满了、token 越烧越多、噪声把模型的注意力冲散了。
我自己踩过最狠的一次,是让 Claude Code 把一个七千行的老项目从 SpringBoot 迁到 Kotlin。这种长任务,读进来的文件一个接一个,上下文很快就顶到天花板 [素材库:Claude-Code.md]。我得手动切着文件喂,读一块、改一块,不能一股脑全倒进去。那次我才真正搞懂,模型的上下文压根装不下整段聊天记录。它是经过挑选、压缩、投影之后的工作记忆。
打个比方你就懂了。上下文像你写代码时面前那块小白板,不是整个硬盘。白板就那么大,你得想清楚哪些信息现在必须写上去,哪些扔进文件夹存着、要用再翻。成熟的做法是:小结果直接进上下文,大结果落盘、只给模型摘要和路径;给工具结果设个预算,太长就截断;快塞满时自动压缩,也就是 compact,把前面的对话浓缩成几句要点。把这套想明白,你的 Agent 才扛得住长任务。
子 Agent 默认隔离,要共享得明说
干到多 Agent 这一步,最容易出的事是状态污染。
如果所有 Agent 共用一个全局状态,乱子就来了:子 Agent 改了主 Agent 的界面,后台任务把主对话搅浑,两个 Agent 同时写一个文件,一个取消信号误杀全部任务。听着抽象,但你只要让多个 AI 共享一块内存,迟早撞上。
这事我每天都在用,就是此刻这套流程本身。我写一篇文章,不会在主对话里埋头干到底,而是把它拆开,派给一个又一个隔离的子 Agent:一个搜资料,一个写稿,一个检测文风。每个子 Agent 有自己独立的上下文,干完把结果交回来。但它中间那堆杂活、读过的文件、绕的弯路,全留在它那边,不会涌进我的主对话 [立场]。
说人话就是,你给每个外包小组单独配一间会议室和一套白板,各干各的、互不串台,最后只把成品端到你桌上。子 Agent 就是这么个外包小组。这背后有一条很值钱的原则:隔离是默认,共享要声明。确实要共用的,比如工具定义、只读配置,再明明白白声明出来。一上来就让大家共享一切,复杂度会瞬间炸开。
普通程序员怎么一步步上手
讲了这么多原则,最关键的是别被吓住。你不用一上来就把成熟项目那套复杂度全复刻一遍。合理的路子是分阶段往上加。

最开始,先搭一个干干净净的最小内核:一个 Agent 主循环、一个工具接口和注册表、一个权限管理器、一个消息存储、一个上下文构建器。目标只有一个,让最核心那条链路清清楚楚跑通,别的先不管。
链路通了,再回头给每个工具补协议:参数校验、权限判断、读写标记、超时、能不能中断。这步做完,你的 Agent 就从 demo 变成可控的东西。
接着处理长任务:给工具结果设上限、大结果落盘、对话太长自动压缩、记一下 token 烧了多少、设个最大轮数。这是让 Agent 跑长活的地基。
再往上,引入后台任务,让长活别堵着对话,想查进度能查,想停能停。然后才轮到子 Agent,把隔离上下文搭起来。这里特别提醒一句:别太早做多 Agent,复杂度会被它瞬间放大。最后才去开放插件、MCP、技能这些扩展。MCP 说人话就是让外部工具接进来的通用插头,第三方能力能像内置工具一样被统一调度。
收个尾,挑几条最该带走的原则给你。Agent 是运行时,别拿它当一句 prompt。工具要当一等公民,别写成裸函数。还有最要紧的一条,先把边界划清楚,再去做复杂能力。这几句想透了,你写出来的就不再是跑给自己看的 demo。
你手里那个 Agent,是已经长成运行时系统了,还是停在「模型加几个工具」那一步?卡在四件事里的哪一件上,评论区跟我聊聊,我帮你看看下一步该补哪块。