2026-07-20 06:43:48
昨天,我去逛了一圈世界人工智能大会,也就是 WAIC。
今年的会场里,有一个词几乎无处不在:
Agent。
做大模型的在讲 Agent,做企业服务的在讲 Agent,做招聘、营销、医疗、金融、法律、教育的,也都在讲 Agent。
过去两年,大家还在说自己做的是“大模型应用”“AI 助手”“行业 Copilot”。到了今年,不在产品介绍里加上 Agent,好像都不好意思说自己是一家 AI 公司。
但我在现场和一些公司聊下来以后,产生了一个很强烈的感受:
很多人不只是没有做好 Agent,甚至连 Agent 到底是什么东西,都没有真正想明白。
他们会很兴奋地告诉我:
我们做了一个某某 Agent,可以帮你完成某某工作。
于是我接着问:
那我怎么用?
这个问题听起来很简单,但很多人的回答立刻开始变得含糊。
有的说:
我们有一个网页,你登录进去就可以用了。
有的说:
我们给你提供 API,你们系统接一下就行。
还有的说:
我们可以私有化部署,也可以嵌入你们现在的软件。
这些回答本身都没有错。
问题在于,他们经常把“Agent 是什么”和“Agent 怎么交付”混成了同一件事。
好像做了一个网页,网页里面放了一个聊天框,它就是 Agent。
或者在大模型外面包了一层 API,这个 API 就叫 Agent。
甚至有些人会产生一种很奇怪的想象:
我做好了一个 Agent,就像做好了一个 Excel 文件一样,可以直接把这个 Agent 发给你,你拿过去就能用。
但实际上,Agent 从来不是一种固定的软件形态。
它既不天然是一个 APP,也不天然是一个网站、API、函数或者软件模块。
这些都只是它可能呈现出来的外壳。
先说结论。
我认为,Agent 最准确的定义应该是:
Agent 是一种能够接收目标、观察当前状态、自主决定下一步行动、调用外部工具,并根据行动结果继续调整,直到完成任务或触发终止条件的软件系统。
这里最关键的,不是用了大模型,也不是接了几个工具。
而是四件事:
目标、决策、行动、反馈。
假设我给一个投资尽调 Agent 下达任务:
帮我调查一下这家公司是否值得投资。
一个真正的 Agent,不应该只是把这句话连同几份材料一起塞给大模型,然后生成一篇看起来像模像样的报告。
它应该能够自己推进任务。
比如先拆解问题:
然后,它可能去搜索公开资料,查询企业数据库,阅读财报,分析访谈记录,调用估值模型。
如果中途发现收入数据和新闻报道矛盾,它应该继续调查。
如果发现某个关键文件缺失,它应该知道自己暂时不能下结论。
如果某个工具调用失败,它应该更换参数、重新尝试,或者请求人工介入。
整个过程更像这样:
观察当前状态
判断下一步做什么
选择工具并执行
查看执行结果
更新当前状态
再决定下一步做什么
这个循环,才是 Agent 的核心。
因此,Agent 并不是一个神秘的新文件格式,也不是某种独立于现有软件体系之外的新物种。
它本质上仍然是一套软件系统。
只是这套系统过去由程序员提前规定每一步怎么走,现在其中一部分路径选择,开始交给模型动态决定。
既然 Agent 是一套系统的运行方式,那么它当然可以被包装成不同的产品形态。
最常见的是网页。
比如一家公司做了一个合同审查 Agent。
用户登录网站,上传合同,点击“开始审查”,过一会儿得到一份报告。
从用户的角度看,它就是一个网站。
但网站只是前端入口。
网页背后可能启动了一个任务队列,Agent 在服务器上读取合同、识别条款、查询法规、对比模板、发现风险,最后再生成结果。
它也可以被包装成一个 APP。
用户在手机里输入任务,后端启动同一套 Agent 系统。
它还可以被包装成 API。
B 公司向 A 公司发送一个请求:
帮我分析这家公司过去三年的经营风险。
A 公司返回一个任务编号。
过几分钟或者几小时后,B 公司再来查询任务状态,最终取得报告。
对 B 公司来说,它只是调用了一个 API。
但在这个 API 背后,可能发生了几十次模型调用、搜索、数据库查询和代码执行。
它也可以被包装成 SDK。
A 公司把代码库交给 B 公司,让 B 公司把 Agent 运行在自己的服务器里,连接自己的数据库,使用自己的模型和权限系统。
它还可以被做成一个 Docker 镜像,部署进企业内网。
甚至可以被包装成一个 MCP Tool,让另一个 Agent 来调用。
所以,当一家公司的产品负责人说:
我们做了一个 Agent。
这句话本身几乎没有提供任何有效信息。
因为我仍然不知道:
“我们做了一个 Agent”,就像一家餐厅告诉你:
我们做的是现代化餐饮系统。
听起来很高级,但你仍然不知道它到底卖什么菜,怎么点餐,多少钱,以及能不能吃。
现在行业里还有另一个非常普遍的问题:
把所有带大模型的自动化流程,都叫作 Agent。
例如:
读取文件
提取文字
调用大模型总结
把结果整理成表格
发送邮件
如果这五个步骤是程序员提前写死的,那么它本质上是一个 AI 工作流。
工作流没有任何问题。
事实上,在大量真实的企业场景里,工作流往往比 Agent 更稳定、更便宜,也更容易审计。
但它不是因为接了大模型,就自动变成了 Agent。
工作流的核心是:
程序员提前决定路径。
Agent 的核心则是:
程序员定义目标、工具和边界,模型在运行过程中动态决定路径。
两者并不是非黑即白,中间存在大量混合形态。
比如前半段使用固定流程,到了异常处理环节,再由 Agent 判断应该查询哪份资料、调用哪个工具。
这种混合架构在生产环境里反而可能更加合理。
问题不在于一个产品是不是“纯 Agent”。
问题在于,很多公司一边使用完全固定的流程,一边为了融资、宣传或者赶时髦,强行把工作流包装成 Agent。
最后导致这个词迅速失去意义。
我在 WAIC 现场遇到的另一个典型误区,是一些人默认:
只要我们把 Agent 做出来,其他公司就可以直接使用。
但企业软件从来没有这么简单。
假设 A 公司做了一个销售 Agent,B 公司想使用。
这时真正的问题不是:
你有没有 Agent?
而是:
这个 Agent 如何进入 B 公司的业务系统?
如果它要读取客户信息,就要连接 B 公司的 CRM。
如果它要发送邮件,就要获得邮箱权限。
如果它要判断客户是否值得跟进,就需要理解 B 公司的销售规则。
如果它要修改商机阶段,就要接入内部权限体系。
如果它要联系客户,还需要确定哪些动作可以自动执行,哪些必须经过人工批准。
这时,A 公司真正需要交付的,可能是:
Agent 只是其中负责“理解任务并动态决策”的一部分。
它不是整个产品,更不是整个交付过程。
一家企业真正购买的,也通常不是一个抽象的 Agent。
企业购买的是某种具体能力:
帮我审查合同。
帮我筛选客户。
帮我处理工单。
帮我调查公司。
帮我分析财务风险。
帮我生成销售线索。
至于这个能力背后用了一个 Agent、十个 Agent,还是一个普通工作流,客户其实并不关心。
客户关心的是:
如果这些问题回答不清楚,那么“Agent”三个字说得再多,也只是技术包装。
现在很多人在介绍 Agent 时,最喜欢先说:
我们底层使用了某某大模型。
我们用了多 Agent 架构。
我们支持 RAG、MCP 和长期记忆。
我们构建了行业知识库。
这些当然可以介绍。
但它们都不是最重要的问题。
真正判断一个 Agent 是否成立,我更关心下面几件事。
第一,它能接受什么完整任务?
不是“它能回答什么问题”,而是用户可以把什么工作完整地交给它。
第二,它能采取什么行动?
只能生成一段文字,和能够查询数据库、修改 CRM、运行代码、发送邮件,是完全不同的产品。
第三,执行路径是谁决定的?
如果所有步骤都已经被开发者写死,那它更接近工作流。
如果模型会根据中间结果决定继续搜索、切换工具、调整策略,它才更接近 Agent。
第四,它有没有状态?
它是否知道任务已经做到哪里,哪些信息已经验证,哪些问题还没有解决,哪些工具曾经失败。
第五,失败以后怎么办?
一个演示版系统往往遇到错误就结束。
一个生产级 Agent 必须知道什么时候重试、什么时候换工具、什么时候暂停、什么时候交给人。
第六,权限怎么控制?
如果 Agent 可以发邮件,它可以发给谁?
如果它可以修改数据库,它可以修改哪些字段?
如果它可以付款,付款上限是多少?
如果没有权限、审批、审计和回滚,那么所谓的“自动执行”,很可能只是把风险藏了起来。
第七,别人到底怎么接入?
网页、API、SDK、私有部署、MCP,还是别的形式?
如果一家公司只能反复告诉你“我们做了一个 Agent”,却始终说不清楚别人如何把它接入现有业务,那么这个 Agent 很可能还只是一个 Demo。
我并不是说 Agent 没有价值。
恰恰相反,我认为 Agent 很可能会成为未来软件系统里非常重要的一层。
过去的软件要求用户自己理解功能。
用户要知道点击哪个按钮,填写哪张表格,选择哪个菜单,才能让软件完成某件事。
Agent 带来的变化,是用户可以直接描述目标:
帮我把最近一个月流失的高价值客户找出来,分析流失原因,再分别制定召回方案。
系统再自己决定需要查哪些数据、运行哪些分析、生成什么内容。
从这个角度看,Agent 确实有可能改变软件的交互方式。
但 Agent 不是产品答案。
它只是实现产品能力的一种手段。
就像数据库不是产品答案,云计算不是产品答案,微服务也不是产品答案。
一家创业公司不会因为用了 PostgreSQL,就自动变成一家优秀公司。
也不会因为把单体系统拆成微服务,就突然获得商业价值。
同样,做了 Agent,也不意味着自动拥有产品、客户和商业模式。
今年大家一窝蜂创业做 Agent,让我想起过去很多技术浪潮。
每当一个新的技术概念出现,行业最先做的往往不是认真理解它,而是先把自己原来的东西重新命名一遍。
聊天机器人改名叫 Agent。
自动化脚本改名叫 Agent。
工作流改名叫 Agent。
搜索加总结也改名叫 Agent。
最后,所有东西都是 Agent,也就等于没有东西是 Agent。
从 WAIC 回来以后,我越来越觉得,今天行业里最缺的并不是更多 Agent。
而是先把几个最基本的问题想明白:
你到底在帮谁完成什么任务?
为什么这个任务需要 Agent,而不是普通工作流?
Agent 能够采取什么行动?
它如何接入客户现有系统?
客户最终购买的究竟是什么能力?
Agent 不是一个 APP,不是一个网站,不是一个 API,也不是一个函数。
它是一套软件系统内部,围绕目标自主判断、调用工具、根据反馈持续执行的机制。
APP、网站、API、SDK、MCP 和私有化部署,只是别人接触这套能力的不同方式。
所以,下一次再有公司告诉你:
我们做了一个 Agent。
先别急着问它用了哪个模型。
你只需要问一句:
那我到底怎么用?
这个问题,通常比任何技术架构图都更能检验,它做出来的到底是一个真正的产品,还是又一个披着 Agent 外衣的演示项目。
2026-07-15 03:38:00

摄影:产品经理
左庭右院蔬菜自助
最近我在看一篇关于电子表格理解的论文。
论文里有一个算法,核心流程其实非常简单:先让一个 Agent 从电子表格中抽取结构,再让视觉 Agent 和 LaTeX Agent 分别验证;如果两边都通过,就返回结果;如果没有通过,就把错误反馈回去,重新抽取,直到成功或者达到最大重试次数。
任何一个写过程序的人,看到这里,大概已经知道代码该怎么写了:
1 |
for _ in range(max_iterations): |
事情就是这么简单。
但论文当然不能这么写。
它非要把这段代码重新包装成一种半数学、半代码、半自然语言的东西:
1 |
C ← {S, Prompt, Tool interfaces} |
再配上各种花体字母、上下标、希腊字母、集合符号和箭头,最后排成一张看起来非常“学术”的算法图。

我盯着这张图看了半天,脑子里只有一个问题:
这到底是在帮助读者理解算法,还是在阻止读者理解算法?
这类伪代码最让人难受的地方,并不是它真的有多难,而是它明明可以很简单,却偏偏要写得很难。
比如:
1 |
Δv |
它无非就是视觉验证产生的修改意见。
正常程序员会写:
1 |
vision_feedback |
作者却偏要写一个希腊字母 Δ,再加一个下标 v。
读者看到 vision_feedback,根本不需要思考,直接就知道这是什么。
但看到 Δv,你得先在脑子里完成一轮解码:
Δ 是差异,还是梯度,还是增量,还是修正?
v 是 vision,还是 verification,还是 value?
这个变量是一个字符串、一组错误、一个修改集合,还是某种数值?
一个本来不需要解释的东西,被符号压缩之后,反而需要读者额外解释。
再比如:
1 |
C ← {S, Prompt, Tool interfaces} |
看起来很数学,实际上无非是在构造一个上下文:
1 |
context = [ |
可问题是,数学里的 {} 通常表示集合,而集合没有顺序。后面作者却又写:
1 |
C[-1] |
也就是取最后一个元素。
如果 C 真的是集合,那就不存在所谓的最后一个元素;如果 C 实际上是一个消息列表,就不应该用集合符号。
也就是说,这种写法甚至没有因为数学化而变得更加严谨。
它只是获得了一个更加严谨的外观。
这正是我最反感的地方。
有些论文里的数学符号,不是在表达严格性,而是在表演严格性。
每次批评这种现象,总会有人跳出来说:
“你觉得公式难看,是因为你数学基础不好。”
这句话当然很方便,因为它可以直接把表达者的问题,变成读者的能力问题。
但我并不反对数学公式。
很多问题离开数学符号,确实很难表达。
比如概率分布、损失函数、梯度、矩阵变换、优化目标、复杂度分析,这些东西如果全部改写成自然语言或者超长变量名,只会更加混乱。
数学符号最大的价值,就是压缩。
一行公式可以描述一整套稳定的数量关系,而且可以方便地进行推导、代换和证明。在这些场景里,符号不但必要,而且优美。
问题在于,并不是所有东西都值得被压缩成数学符号。
一个算法中“先调用 A,再调用 B,如果都成功就返回,否则重试”,本质上是控制流。
控制流最适合用代码表达。
一个系统中“数据从哪里来,经过哪些模块,最后流向哪里”,本质上是架构关系。
架构关系最适合用图表达。
一个方法为什么这样设计、解决了什么问题,本质上是概念解释。
概念解释最适合用自然语言表达。
但现在很多技术论文有一种奇怪的冲动:无论内容本来属于什么表达形式,都要尽可能往公式里塞。
能用一个正常变量名写清楚的,改成希腊字母。
能用一行 Python 写清楚的,改成 LaTeX 伪代码。
能用一段自然语言说清楚的,定义三个集合、两个映射和四个下标。
最后原本很直观的问题,被写成了一份密码本。
这种不适感,让我想起以前看周志华的《机器学习》。
这本书非常有名,因为封面上有很多西瓜,大家通常叫它“西瓜书”。
我相信它在机器学习教育史上有它的地位,也相信很多数学基础很好的人,确实能从中获得系统性的知识。
但我第一次翻开它的时候,最直接的感受就是:
满眼都是公式,一行代码都没有。
一个算法究竟接收什么输入,中间数据怎样变化,循环在哪里,分支在哪里,最后返回什么,书里经常不是先通过流程把它讲清楚,而是直接定义一堆符号,然后开始推导。
比如一个决策树为什么要选择某个特征,程序员真正想看的可能是:
1 |
def choose_best_feature(dataset, features): |
看完这段代码,即使读者还不知道信息增益是怎么算的,也已经明白算法在做什么:
它遍历每一个特征,用这个特征切分数据,计算切分后不确定性下降了多少,然后选择效果最好的那个。
接下来再解释熵,再解释信息增益,再解释公式,读者会知道每一个符号对应程序中的哪一步。
但很多数学教材的顺序正好相反。
它们先告诉你:

接着再告诉你:

然后默认你看到这些符号以后,算法流程就已经自动出现在脑子里了。
对于已经掌握这套知识的人,这样写当然简洁。
但对于正在学习的人,这种表达经常形成一个死循环:
因为不知道算法在干什么,所以看不懂公式为什么这样定义;因为看不懂公式,所以更不知道算法在干什么。
最后读者没有在理解机器学习,而是在逐个解析字符。
大写字母是什么意思,小写字母是什么意思,粗体字母是什么意思,右上角是什么意思,右下角是什么意思,花体字母又是什么意思。
等你好不容易把符号表翻译成人话,早就忘了这一节原本想讲什么。
数学公式本质上是一种高度压缩的信息。
但压缩有一个前提:你得先拥有可以被压缩的东西。
一个熟悉线性回归的人,看到一个损失函数,能够立刻展开出背后的数据、模型、预测误差和优化过程。
因为这些概念已经存在于他的脑子里,公式只是一个索引。
但初学者脑子里还没有这些东西。
你给他一个公式,并不是帮他压缩知识,而是给了他一个压缩包,却没有提供解压软件。
这也是很多所谓“经典教材”的问题。
它们往往是由已经高度熟悉一个领域的人写给另一个熟悉这个领域的人看的,但在出版时却被包装成了初学者教材。
作者自己已经看不见符号门槛了。
他看到的是模型结构,读者看到的是英文字母。
他看到的是概率关系,读者看到的是上下标。
他觉得一个公式非常直观,读者却要花十分钟确认某个 i 到底是样本编号、迭代次数,还是矩阵下标。
于是学习过程变成了符号考古。
理论工作需要公式,这是毫无疑问的。
但现在很多论文中的公式,已经不只是表达工具,也逐渐变成了一种身份标识。
一个方法如果只用自然语言和代码说明,似乎显得不够高级;给模块起正常名字,似乎显得不够抽象;于是必须定义几个集合,增加几个映射,引入几个希腊字母,再给它们配上上下标。
哪怕公式所描述的内容只是:
“从候选答案中选择得分最高的一个。”
也要写成:

这类公式本身没有错,而且在某些上下文中很合适。
但当整篇论文不断把普通流程翻译成数学符号时,它传达的不再只是信息,还有一种隐含态度:
我的工作足够复杂,所以必须用你看不懂的方式来描述。
符号在这里形成了一道门槛。
越是简单的东西,越需要复杂地写,才能让它看起来像研究成果。
一个普通的循环,如果直接写成 Python,读者一眼就看懂了。一旦读者一眼看懂,就容易发现这个方法可能根本没有那么复杂。
可如果把它写成花体集合、希腊字母、上标、下标和箭头,读者首先感受到的是权威感。
至于内容究竟有没有那么深,反而被掩盖了。
这有点像过去某些人写文章,明明一句“分析用户需求”就能讲清楚,非要写成“基于多维异构信息场的用户意图感知与需求表征”。
不是内容变高级了,只是表达变肿了。
很多人潜意识里觉得,代码不够学术,公式才足够严谨。
这其实是一种非常陈旧的偏见。
现代编程语言本身就是严格的形式系统。
一个变量是什么类型,一个函数接收什么参数,一个循环什么时候停止,一个异常如何处理,一个对象怎样改变状态,代码都可以明确表达。
甚至在描述算法执行过程时,代码往往比论文伪代码更加严谨。
还是以前面那篇论文为例。
原文写:
1 |
until verification succeeds or max-iterations reached |
但它没有明确说明,如果最大迭代次数到了,验证仍然没有成功,应该怎么办。
而真正的代码必须处理:
1 |
for _ in range(max_iterations): |
或者至少返回最后一次结果以及失败原因:
1 |
return { |
代码无法靠排版营造一种“差不多说清楚了”的感觉。
它最终必须执行。
正因为必须执行,很多含糊的地方才会被迫暴露出来。
谁负责判断 Agent 是否继续调用工具?
工具失败以后是否重试?
两个验证器是否并行执行?
反馈冲突时如何处理?
最大重试次数是多少?
最后一次失败结果是否保留?
这些才是真正决定算法行为的问题。
而不是把 vision_feedback 写成 Δv。
我一直认为,技术表达最重要的评价标准,不是看起来多么专业,而是它是否让一个本来复杂的问题变得更容易理解。
好的公式,可以把一页文字压缩成一行关系。
好的代码,可以把抽象算法变成可执行流程。
好的图,可以让模块和数据流一目了然。
好的自然语言,可以解释为什么要这样做,以及这样做解决了什么问题。
它们之间并不存在高低贵贱。
真正成熟的表达,应该根据内容选择工具,而不是无论什么内容,都强迫它穿上一件数学外套。
最理想的技术教材,通常应该按照这样的顺序展开:
先用自然语言建立直觉,让读者知道问题是什么;再用图或者代码展示流程,让读者知道系统怎样运行;最后用数学公式精确定义关键关系,让读者知道为什么成立。
自然语言回答“是什么”。
代码回答“怎么做”。
公式回答“为什么”。
但很多论文和教材把这三件事全部扔给了公式。
然后把读不懂的责任留给读者。
我并不期待所有论文都改成 Python 教程,也不认为机器学习可以完全绕开线性代数、概率论和微积分。
真正想深入理解算法,数学永远绕不过去。
但数学应该是一座桥,而不是一堵墙。
公式应该出现在它真正能够减少歧义、压缩关系、支持推导的地方,而不是用来装饰每一个普通流程。
希腊字母也不是越多越高级。
下标也不是越复杂越严谨。
花体集合更不会自动让一个普通想法变成理论贡献。
当一个公式帮助读者更快地理解问题时,它是工具。
当一个公式只是把正常变量名替换成希腊字母,把简单流程重新编码一遍时,它就是障碍。
当一篇文章必须依靠大量符号,才能维持自身的深奥感时,我们甚至应该反过来怀疑:
它究竟是在压缩复杂思想,还是在掩盖思想并不复杂?
我反感的从来不是数学。
我反感的是有人把数学当成知识的防盗门。
仿佛只有穿过一大片希腊字母,才有资格接触后面的内容;仿佛表达得越难懂,工作就越有价值;仿佛读者花在解码符号上的时间,也能算作作者思想的深度。
真正高级的表达,不是把简单的事情写复杂。
而是把复杂的事情讲简单。
公式应该是思想的压缩器,而不是学术的遮羞布。
END

未闻 Code·知识星球开放啦!
一对一答疑爬虫相关问题
职业生涯咨询
面试经验分享
每周直播分享
……
未闻 Code·知识星球期待与你相见~

2026-04-20 20:00:00
在大模型出来之前,计算机领域一直流行着这样一句名言:计算机领域的任何问题,都可以通过拆分问题+给系统增加若干个层来解决。 实际上,这句话在现在的 AI 时代,依然是绝对的真理。
例如以前面试经常问的一个老掉牙的系统设计问题:如何设计一个短网址系统?标准答案是,使用内存+Redis+数据库做多级存储架构。读取最频繁的短网址放到内存,其次的放到 Redis,不频繁的放到数据库。通过增加分层,完美解决高并发和存储成本的矛盾。
现在有了大模型,大家都在玩 Vibe Coding(用自然语言指挥 AI 写代码),很多人觉得以前的工程经验没用了,反正大模型什么都能干。但我认为恰恰相反,在用 AI 写代码时,大家更应该把“拆分与分层”这句话牢牢记在心里。
举个现实的例子,你想做一个招聘聚合网站,需要从各个公司的官网抓取他们的招聘信息,获得工作详情。
如果你没有任何工程经验,是个纯小白,你可能直接就甩给 AI 这样一段提示词:
帮我设计一个爬虫系统,我输入某公司的官网,你需要进入官网,找到里面的招聘页面,然后进入每一个工作,抓取工作的名字,工作地点,薪资和工作要求,并储存到数据库。
我相信现在很多人就是这样写的。并且不得不承认,现在的模型确实太聪明了——如果你用例如 Claude Opus 4.6 或者 Opus 4.7,再加上 Claude Code 这种工具,写出来的基于 Browser Use 的智能爬虫确实能运行,甚至效果可能还不错。它会自己打开浏览器,截图,识别哪里是下一页,哪里是详情。
有同学可能会说,既然能跑通,而且不用我写一行代码,那这不就足够了吗?
但如果你真的把它扔到服务器上跑,你会发现这样设计的系统有两个致命缺陷:
作为一个软件工程师,我想说的是,如果你把大模型当成一个无需思考的“黑盒”,你一定会被它的成本反噬。实际上,如果有工程经验和系统设计经验,即使我们现在不手写代码了,在使用 Claude Code 进行 Vibe Coding 时,也一定会给系统多增加一些限制。
既然单靠大模型硬干太蠢且太贵,我们可以通过增加分层,设计一个三级火箭式的爬虫架构:
现在的现代网站,极大比例都是前后端分离的,通过 Ajax 异步加载数据。前端渲染得再花哨,本质上也是接收了后端返回的 JSON 数据。
在使用 Vibe Coding 时,我不会让 AI 直接去“看”网页,而是会给它这样下指令:
先不要去解析 HTML。请先写一段代码尝试抓包或者分析该网站的网络请求(Network),重点寻找返回 JSON 格式工作信息的 API 接口。如果找到了 API,直接提取关键字段储存。
只要第一层走通了,我们就拿到了最原始、最干净的数据。拿到以后改一下字段名马上就能入库,不需要任何 HTML 解析和浏览器渲染。速度拉满,而且运行时完全不消耗大模型 Token,成本为零。
当然,并不是所有网站都有现成的 JSON 接口可以抓,遇到那些传统的服务端渲染(SSR)页面怎么办?直接上 Browser Use 吗?错。
大模型在第一次运行时,可以完整走完网页分析流程。但请注意,它这次的目的并不是直接提取数据,而是去生成“提取规则”。
这个时候我的 Prompt 会变成这样:
这是一个服务端渲染的 HTML 网页。请你分析这个网页的 DOM 结构,帮我写出提取工作名字、地点、薪资的 XPath 规则或者 BeautifulSoup/正则表达式的提取代码。将这套代码封装成一个 Python 函数。
大模型只在写代码、定规则的“第一次”参与工作。接下来从第二次抓取开始,我们就可以像跑传统爬虫一样,发送 HTTP 请求,拿着大模型写好的规则去提取数据。在这个日常运行的过程中,完全不再需要依赖浏览器,也不需要向大模型发请求。大并发跑起来毫无压力。
只有在前两步都彻底搞不定——例如遇到了极其恶心的动态混淆、页面数据被 Canvas 加密、或者极其严格的反爬机制,传统的 HTTP 请求和规则提取都失效了,这时候,我们才祭出最后的杀招:使用真实的浏览器环境 + 大模型视觉识别来兜底。
明确告诉 AI:
如果前面的静态抓取和 API 接口都失效了,请回退到使用 Playwright/Browser Use 控制真实浏览器,通过截图和大模型视觉能力,点击对应元素来获取数据。
既然这是少数极其难啃的硬骨头,那这部分高昂的时间和金钱成本就是我们可以接受的。
通过把系统拆分成“API拦截 -> 规则生成 -> 智能视觉兜底”这三个层,大量常规请求被第一层和第二层拦截,极大地降低了系统对昂贵大模型 API 的调用频次。我们可以显著降低 90% 以上的 API 成本,并极大提高爬虫的运行效率。
大模型确实能帮你敲代码,极大降低了编程的门槛。但如何设计一个优雅、省钱、可扩展且高效的系统,依然需要你脑子里的工程智慧。在 Vibe Coding 时代,AI 替代的是你的手,而不是你的脑子。
2026-04-16 23:46:00
最近在各种AI编程社区里面逛,发现一个很有意思的现象——大家都在疯狂地折腾怎么省Token。
有人搞Prompt缓存,有人换便宜模型,甚至还有人专门写了一个省Token.skill,让大模型在回复的时候尽量精简。更夸张的是,有人为了省钱,把Claude换成了各种开源小模型,然后抱怨说效果变差了。
这些操作,怎么说呢,就像你家水龙头在哗哗漏水,你不去修水龙头,反而跑去超市买打折的矿泉水。
其实真正吃掉你Token的大头,不是大模型的回复太长,也不是你的Prompt写多了。是Skill本身。
先给不太熟悉的同学解释一下。Skill就是一段预定义的指令,告诉大模型应该怎么一步一步完成一个任务。比如你可以写一个Skill,让大模型帮你操作浏览器,上某个网站搜东西,然后把结果整理出来。
听起来很方便对吧?问题出在哪呢?
我们来看一个具体的例子。假设我要让AI帮我做这么一件事:
打开浏览器,访问Amazon,搜索”牛仔裤”,从第一页的搜索结果里找到最便宜的那条,把商品名称和链接返回给我。
这个需求很简单,对人来说,打开网页点几下就搞定了。我们用Skill来实现它。
我写了一个Skill,核心逻辑大概是这样的:
1 |
## Steps |
看起来清晰明了。我直接在Claude Code里面运行这个Skill,模型用的是Opus 4.6——没办法,要驱动浏览器工具做这种多步骤操作,小模型根本搞不定。
运行这个Skill,我足足等了12分钟。
跑完以后我去OpenRouter后台看了一下这次任务的消耗:

看到没有?几十次API调用,每次都携带将近10万tokens的上下文。最后一算总账,这个看似简单的任务消耗了我将近10美元。
我仔细看了一下每次API调用的内容,发现了一个非常离谱的事情:
大模型在用”智力”做不需要智力的事情。
举几个例子:
你看出问题了吗?
打开一个URL,在搜索框里输入文字,点击按钮——这些操作需要大模型来”思考”吗?这就好比你请了一个数学教授来帮你按计算器,教授每按一个键之前都要在脑子里推演一遍偏微分方程。
几十次API调用里面,真正需要大模型”智力”的,其实只有一步:从搜索结果中判断哪个商品最便宜。 其他全是确定性的操作——打开网页、输入文字、点击按钮、提取文本——这些操作写几行Python就能搞定,根本不需要大模型参与。
想明白了这一点,我让Claude Code把这个Skill改造成Python脚本。原则很简单:
所有确定性的、不需要智力判断的环节,用代码实现。只有需要智力判断的环节,才调用大模型。
改造后的代码核心逻辑是这样的:
1 |
from playwright.sync_api import sync_playwright |
注意看代码的结构——我用注释把它分成了两部分。第一部分是纯代码操作:打开浏览器、输入搜索词、提取商品信息。这些操作100%确定性,不需要大模型参与。第二部分才是调用大模型:让它从一堆商品里面判断哪个最便宜。
你可能会问,比较价格为什么还需要大模型?直接用代码排序不就行了?
因为Amazon的价格格式乱七八糟。有的商品显示$29.99,有的显示$29.99 - $45.99(价格区间),有的写See price in cart,还有的价格旁边带一个with coupon。要把这些情况全部用代码处理,你光写正则表达式就得写半天。但对大模型来说,理解这些格式是它的强项。
运行改造后的代码,17秒跑完,结果直接打印在终端里。
去OpenRouter后台一看——API调用次数:1次。Token消耗:约2.1K tokens。费用:$0.004。
我把两次运行的数据放在一起对比:
| 指标 | 纯Skill | 代码+大模型 | 节省比例 |
|---|---|---|---|
| 运行时间 | 12分钟 | 17秒 | 97% |
| API调用次数 | 几十次 | 1次 | >97% |
| 费用 | ~$10 | $0.004 | >99% |
没有看错,费用从10美元降到了不到半美分,降了99%以上。运行时间从12分钟降到17秒,快了40多倍。
很多人没有意识到一个问题:大模型每做一次工具调用,都需要携带完整的上下文。
第一次调用,大模型需要接收系统提示词+工具定义+用户消息。光Claude Code的系统提示词和工具定义就有好几万tokens,加上Skill的内容,第一轮就将近10万tokens了。它返回一个工具调用,然后你把工具执行结果发回去。第二次调用,大模型需要接收之前所有的内容+第一次的助手消息+第一次的工具结果+……
看出来了吗?每多一轮工具调用,上下文就膨胀一次。 几十轮下来,累积的tokens量是天文数字。而这些历史消息里面,绝大部分是浏览器页面快照——那些密密麻麻的HTML元素和ref ID。
这就是为什么工具调用密集型的Skill特别费Token。不是大模型话多,是它每次说话之前,都要把之前所有的对话重新”读”一遍。
而改造成代码以后,浏览器操作全部由Playwright完成,大模型只需要在最后被调用一次。它接收到的输入就是一个简单的商品列表文本,2K tokens搞定。
上面的例子我用的是OpenRouter + Opus 4.6。但如果你有Claude Pro或Team订阅,还有一个更狠的玩法。
先说一个现实:Claude的官方API价格确实不便宜。Sonnet 4每百万输入Token 3美元,输出15美元。Opus就更不用说了。如果你用API来跑上面这种工具调用密集型任务,几十轮对话下来,光API费用就够你心疼的。
但订阅用户有一个巨大的优势——Anthropic提供了一个叫Claude Agent SDK的东西。这个SDK可以直接调用你本地的Claude Code,走的是你的订阅额度,不需要额外提供任何大模型API Key。
什么意思呢?就是说你每个月付的那20美元订阅费,本来就包含了5小时的Claude Code使用时间。现在你可以通过Agent SDK,在自己的Python脚本里直接调用Claude Code来完成那个”需要智力判断”的环节。不需要OpenRouter,不需要API Key,不需要额外花一分钱。
我们来看看改造后的代码:
1 |
import anyio |
核心变化就一个——把OpenRouter的API调用换成了claude_agent_sdk的query函数。安装也很简单:
1 |
pip install claude-agent-sdk |
这个SDK会自动调用你本地装好的Claude Code。只要你登录了Claude订阅账号,它就直接走你的订阅额度,不走API计费。
这意味着什么?上面那个”需要智力判断”的步骤,从花钱变成了花$0。对,零额外费用。你唯一消耗的,是5小时额度里面的几秒钟而已。
而且还有一个隐藏的好处——既然大模型调用的部分已经不花钱了,你甚至可以在脚本里多调几次Claude。比如让它先判断哪些搜索结果是真正的牛仔裤(排除广告和配件),再从里面找最便宜的。之前用API的时候,多调一次就多花一次钱,你会下意识地省着用。现在走订阅额度,心理负担一下就没了。
所以最终的方案就是:Playwright负责干活,Claude负责动脑,订阅负责买单。 三者各司其职,效率拉满,额外开销为零。
这里我要特别强调一点,因为我知道肯定有同学会搞混。
我说的”把Skill改成代码”,不是让你在Skill的Markdown里面嵌入代码片段。类似这样:
1 |
## Steps |
这种写法,本质上还是Skill。大模型读到这段Skill以后,它还是会一步一步地调用工具——调用终端执行你写的代码片段,然后读取输出,然后”思考”下一步该干什么。每一步照样携带完整上下文,该膨胀的Token一个都不会少。你只是把浏览器操作从browser工具调用换成了terminal工具调用,换汤不换药。
我说的是,把整个任务逻辑写成一个真正的.py文件。比如find_cheapest_jeans.py,保存在你的电脑上。这个脚本从头到尾自己跑,中间需要大模型判断的地方,通过Agent SDK自己调用Claude,最后把结果打印出来。
下次你想用的时候,在Claude Code里面说一句:
帮我运行 find_cheapest_jeans.py
就完事了。Claude Code收到这句话,调用一次终端执行python find_cheapest_jeans.py,脚本自己跑完,结果直接打印出来。整个过程对Claude Code来说,就是一次工具调用——执行一个命令,返回输出。
对比一下:
看到没有?连之前那2.1K tokens都省了。因为脚本内部调用Agent SDK时,走的是一次独立的Claude会话,不会叠加到Claude Code的主对话上下文里。
所以记住:Skill是给大模型看的说明书,.py文件是给Python解释器跑的程序。 一个要烧Token,一个不用。别搞混了。
我上面举的这个例子可能不是特别好,有人可能会说,如果我不仅仅要爬亚马逊,还要爬虾皮,淘宝,小红书这些呢?每一个网站都手动写代码吗?
其实你可以第一次运行的时候让大模型操作浏览器走完全程,并生成playwright的代码,后面从第二次开始,所有操作都通过代码进行。
除此之外,你日常使用的很多Skill,是完全固定的,毫无变化的流程,例如自动发送小红书帖子。就一个网站,同一个流程,这种就非常适合写代码。
其实道理很简单,你日常用的很多Skill,仔细想想就会发现——大部分步骤都是确定性的操作。
比如:
真正需要大模型的,往往只有中间那一小步”判断”或”理解”的环节。
所以下次当你觉得Token花得太多的时候,不要急着去折腾缓存、换模型、写省Token.skill。先看看你的Skill,问自己一个问题:
这个Skill里面,有多少步骤其实不需要大模型?
然后让大模型帮你把那些确定性的步骤改写成Python代码。保留需要智力的部分给大模型,把不需要智力的部分还给代码。
这才是真正的降本增效——不是逼大模型少说话,而是别让大模型做不该它做的事。
2026-03-05 02:30:00
你一定经历过这个循环:
你的记忆力没有问题。 问题出在每个网站的密码规则都不一样:Chase 银行要求 8-32 位、必须有大小写+数字+特殊字符、特殊字符还只能用 ! @ # $ % ^ & * ( );GitHub 要求至少 8 位或者 15 位以上(两套规则);Apple 要求不能有超过 3 个连续相同字符;PayPal 的上限是 20 位……
你根本不是忘了密码,你是忘了这个网站的密码规则是什么。
仔细想想,这件事非常荒谬:
每个网站都知道自己的密码规则是什么,但它们只在你注册或重置密码时才告诉你。
你平时登录的时候,密码框旁边什么提示都没有。你输入记忆中的密码 → 错了 → 再试一个 → 还是错 → 你已经不记得当初注册的时候被哪条奇葩规则逼着改了什么。只有当你放弃登录、点了”重置密码”之后,网站才在设置新密码的页面上列出所有规则。
但问题是:如果你在登录的时候就能看到这些规则,你大概率能一次就想起来正确的密码。 因为你的密码库通常就那么几套模板,区别只是有没有大写、有没有特殊字符、长度是多少。知道了规则,你自然就能回忆起当初用的是哪一套。
基于这个想法,我做了一个 Chrome 扩展:Don’t Reset Password。
它做的事情非常简单:
就这样。没有其他功能了。
我知道你在想什么——“一个读取密码框的插件?”
所以我要把这件事说清楚:
代码完全开源,你可以自己审计。
一个人不可能覆盖所有网站的密码规则。所以这个规则数据库是社区众包的——任何人都可以贡献自己知道的网站规则,所有人都受益。
目前已经覆盖了 30 多个常见网站(Google、GitHub、Apple、Chase、PayPal、Steam、淘宝等),但显然还远远不够。如果你在使用中发现某个网站的规则缺失,点一下就可以贡献。
说实话,这个工具的技术含量不高。它没有用到什么高深的算法,没有 AI,甚至连后端都很简单。
但我觉得它解决了一个真实的、每天都在发生的、所有人都遇到过的问题。而且解决方案如此简单,简单到让人奇怪为什么之前没有人做。
最好的工具不是最复杂的工具,而是让你觉得”这不是理所应当的吗?”的工具。
2026-03-05 01:00:00
最近 OpenAI 发了一篇文章叫 Harness Engineering,讲的是他们内部团队如何用 Codex(基于 GPT-5 的编码 Agent)从零构建一个真实产品的经验。
我读完以后觉得很有启发,不是因为它讲了什么高深的理论,而是因为它非常诚实地记录了一个团队在”让 AI 写全部代码”这条路上踩过的坑和总结出的经验。以下是对我触动最大的几个点。
这个实验的硬约束非常极端——工程师不直接写代码。从 2025 年 8 月一个空仓库开始,3 个工程师(后来扩到 7 个)花了 5 个月,全部通过 prompt 驱动 Codex 来产出代码,最终合并了大约 1,500 个 PR,产出了约 100 万行代码,构建了一个有真实用户的内部产品。
这个设定本身就很有意思。当 Agent 搞不定某个任务的时候,团队的规则不是”算了我来写”,而是去问:”缺了什么工具、文档或能力?”然后让 Codex 自己去补。
这让我想到我自己使用 AI 编程的习惯——很多时候遇到 Agent 搞不定的地方,我的第一反应就是自己上手改。但如果换一个思路,把”为什么 Agent 搞不定”这个问题本身当成一个需要解决的工程问题,长期来看收益是更大的。
这是全文对我触动最大的一个点。
他们一开始也是搞了一个巨大的 AGENTS.md 文件,把所有规则、约束、规范全塞进去。结果发现效果很差,原因有四个:
他们的解法叫渐进式披露(Progressive Disclosure):把 AGENTS.md 精简到约 100 行,只充当目录和地图,指向仓库内结构化的 docs/ 目录。
这个思路跟我自己的经验完全对得上。我在用 OpenClaw 和 Claude Code 的时候,也发现 AGENTS.md 越长效果越差,Agent 经常顾此失彼。”给 Agent 一张地图,而不是一本百科全书”——这句话值得反复品味。
文章里有一句话很直白:
Agent 在上下文中访问不到的东西,对它来说就不存在。
Slack 讨论、Google Docs、你脑子里的想法——如果没有落到仓库里,对 Agent 来说这些信息就是零。Agent 就像一个三个月后入职的新人,只能看到仓库里有什么。
这个观点推导出来的结论很有趣:
p-limit 包做并发控制,而是自己实现了一个——与内部的 OpenTelemetry 紧密集成,100% 测试覆盖,行为完全可预测。因为对 Agent 来说,透明的内部代码比不透明的外部依赖有更高的”杠杆”。这一点跟传统的软件工程观念有冲突。我们通常说”不要重复造轮子”,但在 Agent 时代,外部依赖的”不透明性”反而成了负担。Agent 不能像人一样去翻 npm 文档或者 Stack Overflow,它只能看到仓库里的代码。如果一个库的行为不可预测,Agent 就会在上面反复碰壁。
这又是一个反直觉的结论。
他们从第一天就建立了非常严格的架构约束——每个业务域内,代码只能沿固定方向依赖:
Types → Config → Repo → Service → Runtime → UI
违反方向的依赖直接被 linter 拦住。而且这些 linter 的报错信息被刻意设计成可以直接注入 Agent 上下文的修复指令——Agent 看到报错就知道怎么改。
更巧妙的是执行方式:确定性 linter + LLM 审计 Agent 双管齐下。 确定性的规则用工具强制(不可协商),需要判断的约束用另一个 Agent 来审计。
他们的哲学是:中央强制边界,局部允许自治。 在边界内,Agent 可以自由发挥。输出不一定符合人类的审美偏好——“只要正确、可维护、对未来 Agent 可读,就算达标。”
想想也合理。人类写代码追求”优雅”,很多时候是主观偏好。但 Agent 不在乎代码好不好看,它只在乎规则是否清晰、边界是否明确。约束越严格,解空间越小,Agent 反而越不容易跑偏。
当 Agent 的产出速度远超人类审查能力的时候,很多传统的工程最佳实践反而成了反生产力的东西:
他们提出了一个原则:**”纠错成本低,等待成本高。”** 在低吞吐的人类团队中,这种做法是不负责任的。但在 Agent 高吞吐的环境下,让一个 PR 排队等人审查的成本远大于合并后发现问题再修复的成本。
这让我联想到制造业的区别——手工作坊追求”一次做对”,因为返工成本高;但流水线追求”快速检测、快速修复”,因为产量大到返工的边际成本很低。Agent 编程正在把软件开发从”手工作坊”推向”流水线”。
Agent 会复制仓库中已有的模式——包括坏的模式。时间一长,代码质量会漂移。
他们最初的做法是每周五花 20% 的时间手动清理”AI slop”(AI 生成的低质量代码)。毫不意外,这种做法不可持续。
最终方案是把”黄金原则”编码进仓库,然后定期运行后台 Codex 任务:扫描偏差 → 更新质量评分 → 开针对性重构 PR。大部分清理 PR 一分钟内可审完,自动合并。
文章里有一句话我很喜欢:
技术债像高息贷款:持续小额偿还,远好过让它复利积累后痛苦地一次性解决。
而更妙的是后面那句:人类品味只需捕获一次,然后在每一行代码上持续强制执行。
这才是 Harness Engineering 的精髓——把人类的判断标准”固化”进系统,让机器去执行,而不是每次都依赖人类肉眼去 Review。
读完这篇文章,我最大的感受是:未来的软件工程师核心竞争力不是写代码的能力,而是设计”驾具”的能力。 定义约束、构建反馈循环、管理文档结构——这些以前被视为”辅助工作”的事情,正在变成主要工作。
而那些我们曾经认为最不起眼的东西——AGENTS.md、linter 配置、CI 流程、目录结构——恰恰是决定 Agent 产出质量的关键。
模型是马,驾具是缰绳。马越强壮,缰绳越重要。
本文基于 OpenAI 官方博客文章 Harness engineering: leveraging Codex in an agent-first world 整理而成。