
在 AI 开发时代,真的是跑得快更重要吗?有些人说不要过于深入技术细节,我理解,因为深入技术细节的话,就会丧失对于方向的敏感性嘛。而且很多细节过于繁琐,所以我的想法是:优先了解一些技术背后的原理,然后从第一性出发。
这个问题的核心,其实不是“速度”和“深度”二选一,而是什么样的速度真正有价值。
我的判断是,AI 时代更重要的不是单纯跑得快,而是认知迭代得快。传统软件开发里,执行成本很高,一个想法出来以后,要经历设计、写代码、测试、发布,谁工程能力强、执行得快,优势确实很明显。现在 AI 大幅降低了代码生产成本,执行越来越便宜以后,稀缺的反而变成了问题定义、方向判断、架构设计,以及理解技术本质的能力。
如果只是追求速度,很容易变成今天看到 Agent 就做 Agent,明天看到 RAG 就转 RAG,后天又去追多模态。看起来一直在跑,实际上更像随机游走。所以你说“先理解技术背后的原理,再从第一性出发”,方向是对的。
但第一性原理不等于把所有技术细节钻到底。比如学大模型,如果只是学 LangChain、某个 Agent 框架和几个 API,前期会很快,但这些东西变化也快,知识很容易折旧。更值得长期掌握的是一些相对稳定的问题,比如 Transformer 为什么有效,Token 是什么,Embedding 为什么能表示语义,Attention 解决什么问题,训练和推理有什么区别,Agent 本质是什么,Tool Use 为什么有效。
不过对于创业者、架构师或者产品负责人,也没必要为了“懂底层”去把 Transformer 每一个矩阵运算都推一遍。更实用的是知道技术能做什么,理解为什么能做,再搞清楚它的边界,最后知道怎么把这些能力组织成真实系统。
尤其是边界这件事很重要。AI 为什么会犯错,不只是因为“不够聪明”,还可能因为训练目标本来就不是事实验证,长上下文会丢失重点,模型未必知道自己的未知边界,工具调用还需要外部状态管理。知道这些边界,才知道系统应该怎么设计。
你现在做 Fleet、GhostFleet、业务世界模型和客服系统,核心早就不是“怎么调用 GPT API”,而是怎么让 AI 在真实环境里长期运行。这里涉及状态、权限、事件、人机协作和数据闭环,这些东西不会因为某个框架更新就失效。
所以 AI 时代真正有价值的速度,是快速理解一个新技术到底改变了什么,然后快速验证自己的判断。
当然,也不能走另一个极端,觉得必须把底层全部搞懂以后才能开始做。AI 发展太快,很多理解本身就需要靠实践校正。更合适的方式,是先理解到足以指导行动的程度,然后快速实验,看真实反馈,再修正原来的理解。也就是用原理指导探索,再用实践校正原理。
因此,真正需要避免的不是“跑得慢”,而是在错误方向上高速奔跑。AI 会把执行速度放大,也会把错误方向上的代码、流程和维护成本一起放大。
所以俺发现有时候追不上前沿技术,是因为所谓的前沿技术可能只是老技术的新组合,理解成本很高,细枝末节。不去到原理和基本技术,就像在追一棵还在生长的树的表面,从表面的一点到另外一点,要在外面绕很多路。而如果俺知道树干在哪儿,俺能走最短拓扑。
对,你这个“树干—树枝—最短拓扑”的比喻很准确。
很多时候让人觉得追不上前沿的,并不是新技术真的多到学不完,而是脑子里没有它们的技术谱系。如果只追表面,会看到 RAG、Agent、MCP、Computer Use、Browser Use、Multi-Agent、Memory、Skills、Harness、Coding Agent……每出现一个新词,都像一门全新的技术,于是不断横向跳跃,每次都要重新建立上下文。
但往下找到共同的基础以后,很多东西会迅速收敛。比如现在大量 Agent 技术,拆到底经常就是大模型、上下文、工具调用、状态、控制循环和外部环境。各种 Agent 框架,很大程度上只是重新组织这些组件:观察环境,推理或者规划,采取行动,获取结果,更新状态,再继续下一轮。
这样再看几十个框架,就不再是几十套完全陌生的知识,而是同一套结构的不同实现。
你说的“最短拓扑”也可以这么理解:如果不知道 A、B、C、D 几个新技术共享同一套基础,就只能从 A 学到 B,再从 B 学到 C,每次重新理解;但如果先找到它们共同依赖的基础 X,路径就会变成 A → X → B、C、D。摸到 X 以后,后面的理解成本会明显下降。
所以有时候往回学,反而是最快的往前学。
比如看到一个新的 AI Coding Agent,与其先研究配置文件、CLI、插件、Subagent 和各种参数,不如先问:它到底解决了什么基本问题?很多时候无非是给模型代码库上下文,允许它操作文件和 Shell,保存任务状态,再根据执行结果继续循环。
这样再看 Claude Code、Codex、OpenCode、Cursor Agent,重点就从“这个产品有哪些功能”变成了“这些基础组件分别怎么实现”。这时已经不是在学产品,而是在比较架构。
而且越靠近树干,知识半衰期通常越长。某个 Agent 框架的 API 可能半年就变,协议字段也可能调整,但 RPC 为什么存在、进程为什么需要 IPC、状态机解决什么问题、权限边界为什么重要、分布式系统为什么会遇到一致性问题,这些知识不会轻易过时。
不过找树干不等于无限往底层挖。研究 Agent,不需要先把 Transformer 的梯度推导完整;研究 Fleet,也不需要顺手研究 CPU 微架构。真正需要找到的,是跟当前问题有关的最低稳定抽象层。
比如做 Fleet、GhostFleet,真正值得深入的可能是身份、权限、RPC、状态、事件、网络、进程、容器和故障恢复。只有问题真的下沉到更底层,才继续往下挖。
所以更准确的学习方法不是“不断深入”,而是一直往下找到一个稳定、通用,而且足以解释当前问题的抽象层,然后停下来继续做事。
以后遇到陌生前沿技术,可以先问三个问题:它是哪个老问题的新解法?它由哪些已有技术组合而成?真正新增的东西到底是哪一部分?
这么拆以后,很多所谓全新的技术,最后可能只是大量已有树干,加上一小段真正的新枝条。真正值得花时间学的,就是那段新枝条。
所以你说“找到树干以后走最短拓扑”,本质上是在建立技术谱系。知道一个技术从哪里长出来、解决了什么旧问题、继承了什么,又真正增加了什么,往往比记住它现在有哪些功能更重要。
那俺稍微发散一下,政治学教俺们看待社会问题,有个简单的办法就反问:谁受益?你说的从哪里长出来、为什么长出来、它替代了什么、它继承了什么,人类在接触到新概念的时候并不知道这些,俺相信就算是专家也不可能都知道,除非他做个skill让AI帮忙分析下。换句话说你给的方法还不太适用于人类,简化下呢。
对,你这个批评成立。刚才那套“从哪里长出来、替代什么、继承什么”,更像研究者拿到线索后的分析框架,不是人第一次撞见陌生概念时最好用的入口。
如果压缩到像政治学里的“谁受益?”那么简单,我会给技术学习留一句:“它替谁省了什么麻烦?” 这一个问题其实能把很多东西顺藤摸瓜带出来。
比如第一次看到 MCP,你完全不知道它的历史,也不用先研究协议谱系,先问:MCP 替谁省了什么麻烦?很快会发现,以前模型、客户端和各种工具之间要分别做适配,每家自己接 API、写 adapter,麻烦就在重复适配和接口碎片化。MCP 做的事情,就是尝试抽出一个统一协议,减少这种 N×M 的重复集成。到这里也就很容易看出,真正新的未必是工具调用本身,而是把工具调用的连接层标准化。
你甚至不用预先知道“它继承了什么”,这个问题自己就会把你带到树干。
另一个特别好用的问题是:“没有它,以前怎么办?” 我觉得这句话甚至可以和“谁受益?”放在同一个级别。因为很多所谓前沿技术,一问这个问题,神秘感马上就消失了。
比如 Agent。没有 Agent 以前怎么办?其实就是人自己反复看结果、决定下一步、调用工具,再看结果。这样一问,一下就能看出 Agent 在自动化什么。
RAG 也是一样。没有 RAG 以前怎么办?可能是把信息直接塞进 Prompt、微调模型,或者人工查资料。这样再去理解 RAG,就很容易发现,它本质上是在模型推理之前增加外部检索。
容器也是。没有容器以前怎么办?裸机装环境、用虚拟机,或者手工解决依赖。这样理解以后,根本不用一上来就先背 Docker 的一堆术语。
所以我甚至会把我们前面的复杂方法进一步压缩成一个更适合人的“两问法”:第一问,不用它,以前怎么办? 这是找树干和前任;第二问,它到底省了什么麻烦? 这是找它真正的增量。这两个问题回答完,再继续研究细节,路径会清楚很多。
而且它还有一个很强的作用,就是过滤那些被营销语言包装得很复杂的概念。
假设某个东西号称“AI-native distributed agentic cognitive orchestration framework”,听起来很吓人。你直接问:不用它以前怎么办?答案可能只是“用 Python 调几个模型和工具”。再问:它省了什么麻烦?答案可能只是“帮你封装了几个调用流程”。
那这个东西在你脑子里马上就会降维成:哦,一个 orchestration framework。结束。根本没必要陪着营销语言在树冠上乱跑。
如果只能留下一句口令,我甚至建议以后看到任何新技术,先问:“不用这玩意儿,原来咋干?”
这个问题特别适合人脑,因为它不要求你一开始就知道答案,只要求你知道从哪里开始查。等答案出来以后,再继续问一句:“所以它真正改了哪一步?” 这时候技术树往往自己就露出来了。
所以前面我说的“技术谱系”,其实还可以继续简化:陌生技术不要先问“它是什么”,先问“没有它怎么办”。
“它是什么”很容易把你带进别人已经定义好的术语体系;“没有它怎么办”,反而会把你直接带回它原本要解决的现实问题。我觉得这一套,比上一轮那几个问题更适合真正的人类学习。
Got。那继续,如果俺遇到一堆堆项目,其中大量近似的,比如Docker、k8s、Podman这些,俺做技术选型的时候应该注意什么?是跟项目现有阶段最适配的那个吗,什么时候将就一下,什么时候可以破坏式安装或更新,就算风险高也要去强行做这步?什么时候可以把自己的问题也否定了,比如前面的那些都不合适,而是应该只吸取其思想,用OCI标准的containerd即可或是runc?
是,而且我会把“跟项目当前阶段最适配”再修正一下。真正更好用的原则不是“选最先进的”,也不是“选最轻的”,而是:默认使用最高层、最成熟、足以解决问题的抽象;只有它遮住了你必须掌控的东西,才往下一层钻。 换句话说,就是尽量少拥有复杂性,但关键控制权不能交出去。
这套方法正好能回答前面几个问题:什么时候应该将就,什么时候值得破坏式升级,什么时候研究到最后,应该干脆否定最初的选项。
首先,先别急着问“Docker、Podman、K8s 到底选哪个”,而应该先问:俺究竟需要控制到哪一层? 因为这些东西本来就不完全处在同一个层面。大致来看,最上面是你的业务、Agent 和服务,下面是 Kubernetes 这类编排与平台层,再往下是 Docker、Podman、containerd、CRI-O 这类容器引擎或运行时,下面还有 runc、crun、youki、Kata、gVisor 这类更低层的 OCI Runtime,最后才是 Linux namespaces、cgroups、文件系统、进程和 Kernel。
这并不是一条绝对严格的单链,例如 Kubernetes 通过 CRI 对接运行时,Docker Engine 自己使用 containerd 管理容器生命周期,containerd 又可以调用 runc,而 OCI Runtime Spec 规定的是 runc 这一层运行 OCI 容器时的基本接口和生命周期。但拿来建立脑图已经足够。
所以技术选型前一个很重要的能力,是先判断候选项目到底是不是在解决同一层的问题。否则很容易研究半天“Docker vs K8s”,其实相当于在研究“操作系统和机房管理系统哪个更好”。
那什么时候应该“将就一下”?我觉得判断可以很简单:这个缺点是不是局部的、可逆的、一次性的?
比如 Docker 有个地方你不喜欢,但它不破坏核心架构,不污染数据模型,不影响身份和权限边界,不迫使整个项目围着 Docker 的特性设计,而且哪天真要换掉,成本也不大,那就应该将就,甚至应该主动将就。
因为工程上有一种很大的隐性成本:为了消灭 5% 的不爽,自己接管剩下 95% 的复杂性。 比如只是嫌 Docker daemon 不够优雅,于是决定自己跑 containerd,接下来就会发现镜像、网络、Volume、CLI、日志、生命周期、升级、API 等一大堆本来别人替你承担的事情,现在全部归你自己。
这可以叫“抽象下沉税”。
Podman 会成为 Docker 的直接替代候选之一,也正是因为它仍然保留了比较完整的容器引擎层能力,同时采用 daemonless 设计,支持非 root 用户运行,CLI 也刻意保持与 Docker 接近。也就是说,它改变了一些你可能不喜欢的东西,却没有要求你立刻把整个容器引擎层自己接过来。
所以一个很好记的原则就是:能绕过去的小毛病,不值得为了它改变整个架构层级。
反过来,如果一个工具的问题开始侵入你的核心不变量,那就不能继续将就了。
比如你的系统要求身份必须由自己掌控,权限必须分层,状态必须由自己的 SSOT 管,控制面要跨 Linux、Windows、Android,而且运行时不能偷偷拥有第二份权威状态。结果某个平台开始要求用户必须按照它的方式定义,状态必须存在它那里,网络按它的模型走,权限进入它的体系,部署也围绕它的生命周期设计。
这时候已经不是“这个工具有几个缺点”,而是你的系统开始迁就工具。
这是一个非常好用的警报:工具开始规定你的世界模型,就该重新审视它。
当然,工具一定会有自己的抽象和约束,否则它什么问题也解决不了。但如果这些约束开始反过来改变你的核心数据模型、身份模型、权限模型和状态权威,那就不再是普通的使用成本,而是在改变系统边界。
那什么时候值得“破坏式升级”?这里我反而会比很多传统运维思路激进一点,尤其是在项目早期:基础抽象如果已经证明错了,越早砸掉通常越便宜。
因为错误基础会产生复利。今天为了兼容它写一个 adapter A,过两个月可能就有 compatibility B、migration C、legacy state D、special case E。半年以后不是你“不想升级”,而是已经升级不起了。
所以判断一次破坏式改造值不值得,真正应该比较的不是“风险大不大”。重大架构迁移风险本来就不会小,更应该比较的是:现在破坏一次的成本,和继续背着错误抽象走两年的累计成本,哪个更高。
如果只是新东西看起来更漂亮,没必要迁;当前方案偶尔不方便,也可以将就;如果 workaround 开始反复出现,就应该准备迁移;如果核心能力已经被现有抽象限制,或者错误抽象开始向其他模块扩散,就应该尽早迁。尤其当以后只会产生越来越多依赖时,拖得越久,迁移成本越高。
当然,激进迁移还有一个前提:恢复能力。如果数据不可恢复、没有回滚能力,那应该先补恢复能力;如果 Git 和 SSOT 足以重建,节点本身可以牺牲,那么基础设施层就可以激进得多。
所以“破坏式安装”不等于莽。最理想的状态其实是:生产状态很保守,但基础设施高度可重建,于是节点可以大胆破坏。 这也是我们一直强调 Git、SSOT、声明式状态和可重建节点的原因。真正让你敢升级的不是胆量,而是恢复能力。
更有意思的是最后一个问题:什么时候应该直接否定自己的问题?这个能力其实比“会选型”更高一级。
比如一开始问的是:“Docker、Podman、K8s 到底选哪个?”研究一圈以后,突然发现真正需要的根本不是一个完整的“容器平台”。实际需求可能只是拉取 OCI image、准备 rootfs、启动一个隔离进程、交给自己的 Agent 控制、读取状态,最后销毁。
那就应该把原来的问题扔掉,重新问:GhostFleet 真正需要什么 runtime primitive?
这时候候选自然会变成 containerd、CRI-O、runc、crun,甚至进一步下沉到 namespaces 和 cgroups。
这就是前面说的“找到树干以后走最短拓扑”。OCI Runtime Spec 定义的是低层容器运行时的配置、执行环境和生命周期,runc 是其中一种实现;containerd 则站得更高,负责更完整的容器生命周期,也可以作为 Kubernetes 的 CRI runtime。
但这里一定要加一道刹车:下沉不是天然高级。
假设一路从 Docker 下沉到 containerd,再下沉到 runc,每往下一层,你都会获得一些控制权,同时也会继承上一层原本替你解决的问题。到了 runc,你拿到的是一个非常纯粹的 OCI container execution primitive,但也基本等于在说:好,上面的世界俺自己造。
这只有在“上面的世界”本来就是你的产品时才合理。
比如你自己正在做一个舰队控制系统,那么“容器生命周期怎么控制”可能正好属于你的领域能力,继续往下钻就有价值。但如果只是部署一个 WordPress,还要自己围着 runc 做一套容器管理,那就不是第一性原理,而是在主动给自己找活干。
所以以后碰到十几个同类项目,不必一上来就看几十页 Feature Comparison。先问三个问题就够了:俺真正需要控制什么?剩下哪些麻烦,最好让别人替俺背?如果以后换掉它,俺留下来的东西还有多少?
这三个问题其实对应三个核心维度:控制权、复杂性所有权和可退出性。
我甚至会把“项目当前阶段适配度”放在这三个因素后面,因为阶段会变,而架构边界会不断积累。一个工具今天可能非常适合项目规模,但如果它要求你把核心身份、状态或数据模型逐渐迁进自己的体系,那么等项目阶段真的变化时,反而可能最难退出。
所以最后,如果要给现在这种 AI 原生开发方式留一个总原则,我会写成:默认站在成熟抽象上;碰到真正限制再向下钻;钻到能掌控关键变量就停,不以“更底层”为荣。
Docker 足够,就用 Docker;Docker 的模型真的开始妨碍你,再看 Podman 或 containerd;containerd 又替你做了不该替你做的决定,再研究 OCI 和 runc;如果 runc 仍然遮住真正需要控制的变量,再下沉到 namespaces、cgroups 或 Kernel。问题解决,就停。
所以工程上不是从底层往上造,而是从最高层往下剥。
这和前面“没有它以前怎么干”的学习方法正好形成两个方向:学习技术时向下找树干,搞清楚新东西建立在哪些旧东西之上;做工程时则尽量站在成熟的高层抽象上,只有高层抽象真的承受不了需求,才顺着树干往下走。
前者是在减少理解成本,后者是在减少自己拥有的复杂性。两者结合起来,其实就是一套很完整的 AI 时代技术学习和技术选型方法:该懂的底层要懂,但不该自己背的底层,不要主动背到身上。
好。那俺要反问了,抽象下沉税不爽的主要是在前AI世代,现在对系统底层的操作能力可能都内化到AI自带的原生能力当中去了,那有没有一种可能,让AI操作高度抽象的产品反而不如让它操作一些更偏底层但生来就会的东西?
对,而且我会修正上一轮的一条原则。在 AI 时代,“尽量站在最高层成熟抽象上”已经不一定成立。更准确的说法应该是:优先选择最低充分、稳定、机器可读的抽象层,而不是最高的人类友好抽象层。你说的这种“抽象倒置”不仅可能发生,我认为它已经开始发生了。
过去我们做软件,所谓“更高级的抽象”,通常是在给人省麻烦。比如从手写 namespace、cgroup,到 runc、containerd、Docker CLI,再到 Docker Desktop,最后变成点几个按钮就能启动服务。对普通人来说,通常越往上越轻松。但 Agent 的成本函数完全不同。AI 并不会觉得 systemctl status xxx、journalctl -u xxx、cat config.json、curl localhost:8080/api/status 有多麻烦,很多时候这些东西反而是它最舒服的工作环境,因为它们文本化、输入输出明确、语义相对稳定,可以搜索、组合、重复执行,也很容易检查结果,而且大量训练语料里本来就有。
OpenAI 给 Agent 提供 shell 工具,本质上也是让模型进入“命令 → 结果 → 继续判断”的循环,而不是要求它像人一样通过 GUI 完成所有操作。当然,shell 的风险并没有因为 AI 会用它就消失,所以仍然需要 sandbox、权限边界和人工确认来控制。于是就会出现一个过去很反直觉的现象:人觉得底层的接口,对 AI 反而可能是更高质量的接口。
举个很典型的例子。假设一个产品提供了漂亮的 Web 管理后台,人只需要点进“设置—高级设置—网络—新建规则”,填表、保存、确认,看起来当然很好用。但 Agent 面对的是另一套成本:先找到按钮,判断当前页面状态,理解 DOM,处理弹窗,等待异步加载,还要应对页面版本变化,最后再确认操作到底有没有成功。这其实是一个相当高熵的环境。反过来,如果接口只是 ip route add ...,或者一段明确的 JSON,例如 {"route":"...","gateway":"..."},AI 反而几乎不需要“理解界面”。
所以对 AI 来说,后者可能才是更好的抽象。但这绝不等于“越底层越好”。不能因为 AI 擅长命令行,就推出 Docker 不如 containerd、containerd 不如 runc、runc 又不如直接调 namespace。AI 真正喜欢的并不是“底层”,而是低歧义、可观察、可组合、可验证。
因此我觉得应该把“抽象高度”这根单轴直接扔掉,真正应该看的是一个接口的 Agent 可操作性。GUI 按钮的问题是语义经常隐含在界面里,状态也容易被隐藏,而且 UI 很容易漂移;自然语言界面虽然容易使用,但行为边界有时比较模糊。稳定 CLI、JSON/YAML 声明式配置、HTTP/gRPC API、typed tool、MCP 这类接口通常就非常适合 Agent。再继续往下,到稳定的系统 primitive,在特定场景里依然很好;但如果一路钻到未稳定的内部 API、syscall 或 raw kernel primitive,使用成本又会重新上升。
所以它其实更像一条 U 型曲线。一端是过于面向人的 GUI,隐藏状态太多;另一端是过于原始的系统接口,需要调用者自己承担大量语义和生命周期管理。AI 真正舒服的地方,通常在中间那个“机器接口甜点区”:CLI、API、schema、声明式配置和 typed tools。
containerd 本身就是一个很好的反例。你刚才设想,俺是不是干脆直接上 containerd,甚至 runc?有时候可以,但不能只是因为它们更底层。containerd 官方自己就明确说,ctr 主要用于调试和理解 containerd API,不是面向项目长期使用的主要用户界面,而且不承诺接口稳定,甚至小版本之间都可能出现兼容性变化。
这意味着 Docker CLI 虽然“更高级”,长期来看却可能比 ctr 更适合 Agent 自动化。原因不是 AI 不会用 ctr,而是接口不稳定。这揭示出一个很重要的原则:AI 熟不熟悉某个接口,不等于它适不适合作为系统边界。
containerd 还有另一个有意思的地方:它明确只负责一部分事情。执行、镜像、快照属于它的范围,而网络、构建、外部 Volume 管理、持久日志等很多能力,会留给更高层系统。所以如果 GhostFleet 将来真的下沉到 containerd,我们实际上是在做一个很明确的选择:GhostFleet 愿意自己拥有剩下那部分复杂性。如果这些复杂性本来就是我们的产品领域,那当然合理;如果不是,那很可能只是重复造一遍 Docker。
这一点也说明,“AI 生来会什么”应该成为新的选型维度。过去做技术选型,通常会考虑开发成本、学习成本、维护成本、人才市场、生态、性能和稳定性。现在应该再加上一个很重要的维度:模型先验能力。
当前大模型天然熟悉 shell、Git、HTTP、JSON、SQL、Python、文件系统、Linux 常见 CLI、Docker CLI、systemd 等大量通用工具和接口。这意味着过去一句“需要工程师学习两周才能安全操作”,现在可能变成“模型本来就知道怎么操作,人只需要把权限边界和验证机制搭好”。这是一个很大的经济学变化。
以前下沉一层,往往意味着增加大量工程师的认知负担;现在有些场景可能变成,模型已经拥有大量相关先验知识,只需要补少量项目上下文和验证机制。所以抽象下沉税确实正在下降,而且部分领域可能不是下降一点,而是下降一个数量级。当然,这并不意味着其他成本消失了。接口稳定性、状态一致性、权限风险、不可逆操作、故障恢复,这些物理约束不会因为模型知道命令怎么写就自动解决。
这也能解释为什么 MCP 这一类接口很重要。MCP 并不是单纯给 AI 增加一个“更高级 UI”,更重要的是把系统能力包装成工具名、输入 schema、输出 schema 和明确语义。也就是说,它尝试把一个复杂底层系统压缩成一个窄而明确的机器接口,再交给 Agent 使用。这可能才是 AI 时代更合适的抽象方式:复杂系统下面保持原样,上面提供窄而稳定的机器接口,再交给 Agent,而不是先做一个给人用的 GUI,再让 AI 模拟人去点 GUI。后者很多时候,其实是在让 AI 穿着人类的鞋走路。
这还能进一步推出一个对我们很重要的架构方向:以后自己设计系统时,我甚至倾向于从一开始就把 Human Interface 和 Agent Interface 分开。底层先维护同一套 canonical capability 和状态模型,然后向上分叉,一边给 Human UI,一边给 Agent tools、CLI、API 或 MCP。人需要的是看得懂、容易确认、降低操作负担;AI 需要的是状态明确、schema 稳定、结果可验证,而且容易组合。双方没有必要强迫自己走同一个界面。
这和你之前坚持“人要有浏览器管理面板,而 Agent 可以走 SSH/API”其实是同一个方向:双方共同操作同一个世界模型,但不必共用同一层交互界面。
甚至可以进一步重新定义什么叫“好的抽象”。传统意义上的抽象,通常意味着隐藏更多底层细节。但在 AI 时代,一个更有价值的衡量方式可能是:这个接口能不能把任务意图压缩成少量、确定、可验证的动作。
这样一来,一个 shell 命令完全可能比一个 SaaS 管理后台抽象得更好。比如 systemctl restart ghostfleet-agent,从实现层级看,它当然比一个图形后台更接近系统底层;但从 Agent 的认知角度看,这个动作已经非常高层了:Intent 是重启服务,Action 是一个确定命令,Observation 是退出码和服务状态。整个链条短、明确,而且容易验证。
所以以后做技术选型,我觉得不应该先问“它到底高层还是底层”,而应该问:“在哪一层,AI 能用最少的不确定性,控制俺真正关心的东西?”在满足这个条件以后,再选择尽可能稳定、成熟、可恢复的那一层。
我会把它叫做“最低充分控制层”。不是最低层,也不是最高层。继续往上,如果开始隐藏我们必须控制的东西,那就太高;继续往下,如果开始要求我们接管没有必要接管的复杂性,那就太低。应该停在两者之间。
所以我们上一轮“尽量使用成熟高层抽象”的原则,可以进一步修正为:默认寻找最低充分、稳定、机器可读的控制层。这一层至少要满足几个条件:没有隐藏我们必须控制的关键变量,也没有把无关复杂性大量转嫁给我们;接口足够稳定,状态可以观察,操作结果能够验证,出问题以后还能恢复。如果再往上一层开始遮住关键控制权,再往下一层开始承担额外复杂性,那现在这一层就是应该停下来的地方。
我觉得这比传统的“尽量使用成熟高层抽象”更适合 AI 原生工程。它也解释了为什么现在越来越多过去的工程经验需要重新估价。以前很多“千万不要自己碰底层”的经验,本质上并不只是底层本身危险,还因为让人理解、维护和操作这些东西非常昂贵。现在其中相当一部分人类认知成本,正在被模型已有的先验能力吞掉。
但这并不意味着那些风险消失了。真正剩下,而且仍然值得警惕的,是状态、权限、接口稳定性、不可逆操作和故障恢复这些不会因为 AI 变聪明就自动消失的约束。
所以最后真正改变的,不是一句简单的“AI 时代应该用更底层技术”。更准确地说,是过去我们主要按照人的操作成本选择抽象层,以后还要同时按照 Agent 的操作成本重新计算一次。而算完以后,最佳位置有时会比过去更低,有时反而会更高。关键不是抽象的高度,而是哪一层能用最少的不确定性,给我们刚好足够的控制权。