AI 编程术语小词典(中文大白话版)

原版:mattpocock/dictionary-of-ai-coding —— "AI coding jargon, explained in plain English." 这一版是它的中文改写版:术语换成中文语境里的叫法,例子换成国内团队日常会遇到的场景,讲法尽量做到"没接触过 AI 编程的人也能看懂"。

先说三句话

用 AI 写代码这件事,让人头大的地方其实就那么几个:术语听不懂、报错莫名其妙、账单对不上、同一个问题问两次结果还不一样。

但这些都不是玄学,每个都有干干净净的解释。你缺的不是技术,是词汇量。

这本小词典就干一件事:把 AI 编程里的黑话,翻译成人话。 大概一个下午能翻完,翻完之后你会发现——原来那些"玄学"全是有名字、有规律的东西,而且大部分问题根本不在模型身上,在你给它的东西身上。


怎么用这本词典

每个词条长这样:

术语第一次出现时会写成「中文名(English)」,之后用中文名。有些词中文圈还没统一叫法(比如 Harness、Agent),我会说明常见的几种译法。


术语速查表

第 1 章 · 模型本身

中文名 英文 一句话
人工智能 AI 一个会移动的标签,不是具体技术
模型 Model 一堆参数,只会"接着往下猜"
参数 Parameters 模型脑子里那些被调好的数字,训练完就冻住了
训练 Training 一次性、巨贵的"调参数"过程
推理 Inference 每次你问它,它跑一遍得出答案
思考档位 Effort 回答之前让它想多久的旋钮
词元 Token 模型读写的最小单位(不是"字"也不是"词")
下一个词元预测 Next-token prediction 模型唯一会做的事
不确定性 Non-determinism 同样的问题,两次答案可能不一样
模型服务商 Model provider 真正跑模型的那家(Anthropic / OpenAI / 本地 Ollama)
外壳 Harness 把模型变成"能干活的工具"的那一层软件
一次模型请求 Model provider request 外壳和模型之间的一次来回
输入词元 Input tokens 你塞给它的内容,按量计费
输出词元 Output tokens 它吐出来的内容,单价更贵
前缀缓存 Prefix cache 重复发送的历史,打折
缓存词元 Cache tokens 命中缓存、按折扣价算的那部分词元

第 2 章 · 会话、上下文窗口与回合

中文名 英文 一句话
无状态 Stateless 不往前带任何信息
上下文 Context 它现在手上有的、跟任务相关的信息
上下文窗口 Context window 它一次能看到的所有内容,有上限
有状态 Stateful 会把信息往下带
智能体 Agent 你实际在对话的那个"东西" = 模型 + 外壳
系统提示词 System prompt 外壳每轮都塞在最前面的"岗位说明书"
会话 Session 跟它聊的一次完整过程,聊完就没了
回合 Turn 你发一条消息 + 它干完所有活交还控制权

第 3 章 · 工具与环境

中文名 英文 一句话
环境 Environment 它干活的世界(最常见就是你的项目目录)
文件系统 Filesystem 它读写文件的那棵目录树
工具 Tool 外壳给它的一个个函数(读、写、跑命令)
工具调用 Tool call 它输出的"我要调用某个工具"这段文本
工具结果 Tool result 工具执行完返回给它的内容
模型上下文协议 MCP 给外壳插外部工具的标准接口
权限申请 Permission request 执行前弹出来问你"能不能干"
权限模式 Permission mode 哪些操作要问、哪些直接放行
智能体模式 Agent mode 权限 + 行为指令打包在一起的预设
沙箱 Sandbox 把它关在隔离环境里跑,炸了也不影响你

第 4 章 · 它是怎么犯错的

中文名 英文 一句话
讨好倾向 Sycophancy 顺着你说,你说啥它都觉得对
幻觉 Hallucination 一本正经地胡说八道
参数知识 Parametric knowledge 训练时背下来的、存在参数里的知识
知识截止日 Knowledge cutoff 它"背书"背到哪天为止
上下文知识 Contextual knowledge 摆在它眼前、能直接读到的知识
注意力关联 Attention relationship 词元与词元之间的相互影响力
注意力预算 Attention budget 每个词元能分出去的注意力是有限的
注意力衰减 Attention degradation 上下文越长,关键信息越被淹没
聪明区 Smart zone 会话前期它最清醒的那段(反面叫"变笨区")

第 5 章 · 交接

中文名 英文 一句话
清空 Clearing 结束会话,从零开始
交接 Handoff 把上下文从一个会话带到下一个
一手资料 Primary source 原始的东西本身(代码、日志、真实响应)
二手资料 Secondary source 对原始资料的转述(文档、摘要、报告)
交接文档 Handoff artifact 写进文件里、给下一个会话看的交接材料
方案文档 Spec 描述一件跨多次会话的大活
工单 Ticket 一次会话能干完的一小块活
压缩 Compaction 把历史总结成摘要,喂给新会话
自动压缩 Autocompact 窗口快满时外壳自动触发的压缩

第 6 章 · 记忆与引导

中文名 英文 一句话
记忆系统 Memory system 让它跨会话"记住"东西的机制
AGENTS.md AGENTS.md 项目给它的常驻说明书
渐进式展开 Progressive disclosure 先只给目录,用到再加载全文
上下文指针 Context pointer 一句话指向某份资料,需要时再拉进来
技能包 Skill 打包好的一项能力,用到才加载
子智能体 Subagent 派出去干脏活、只回报结果的小弟

第 7 章 · 干活的方式

中文名 英文 一句话
人在环中 Human-in-the-loop 你盯着它干,随时纠偏
挂机 AFK 你走开让它自己跑
自动检查 Automated check 测试/类型检查/lint,非过即挂
自动评审 Automated review 让另一个智能体来评审
人工评审 Human review 你自己读 diff
氛围编程 Vibe coding 不看代码,能跑就算过
共同设计图景 Design concept 你俩脑子里那件"要做的东西"是否一致
连环追问 Grilling 让它反过来一个问题一个问题问你
快速原型 Prototyping 先做个粗糙版本,看着实物再聊
开发者体验 DX 对人类友好程度
智能体体验 AX 对 AI 友好程度

第 1 章 · 模型本身

人工智能(AI)

一句话:AI 不是一个技术名词,是一个"会移动的标签"——它永远指向"计算机刚刚学会干的那件牛逼事"。

它不像"模型""词元"那样指一个固定的东西。它指的是这个时代计算机新能做到、又让人惊艳的事。现在它指的是大语言模型,但以前它指过完全不同的东西:

年代 当时"AI"指的是什么
1950s 符号推理——定理证明器、下棋程序
1960s–70s 规则程序——ELIZA、SHRDLU
1980s 专家系统——成千上万条手写 if-then 规则
1990s 博弈树搜索——深蓝下赢卡斯帕罗夫(1997)。那时候研究者反而躲着"AI"这个词
2000s 统计机器学习——垃圾邮件过滤、推荐系统。当时统一叫"机器学习"
2010s 深度学习——图像识别(AlexNet,2012)、AlphaGo(2016)
2020s 大语言模型——ChatGPT(2022)之后,"AI"就等于"聊天机器人"了

这个标签为什么老在动?有个专门的观察,叫 AI 效应一项技术一旦真的好用了,就会被改个朴素的名字——"这不就是搜索嘛""这不就是统计嘛",然后"AI"这个词就往前滑,指向下一个还没解决的事。这个观察很老了,1971 年 Bertram Raphael 就说过:"AI 是我们还不知道怎么让计算机好好解决的那类问题的统称。"1979 年前后 Larry Tesler 的说法更损:"智能就是机器还没做到的事。"

所以,AI 话题特别容易各说各的。 "AI 不会推理""AI 被吹过头了"——这种话里藏着一个时间戳:你说的是 1980 年代的专家系统、2010 年代的图像分类器、还是上个月的这个模型?三种指代能推出三个完全不同的结论。

一旦讨论卡住了,把这个词换掉。 换成你真正想说的那个东西:是模型?是外壳?是智能体?还是你给它的上下文?话题立刻就清楚了。

⚠️ 别这么说:任何技术判断里都别光说"AI"——说清楚你指的是哪个部件。"AI 编程"作为这个行当的名字没问题,但"AI 产生幻觉了"这句话不合格。

💬 对话示例

"CTO 想知道 AI 能不能处理工单分诊。"

"先翻译一下再评估——她说的其实是'一个接了工单系统的智能体'。光说'AI'不构成需求。"


模型(Model)

一句话:模型就是那堆参数,无状态,只会"接着往下猜词元",别的什么都不会。

"Claude Opus 4.x""GPT-5.x"这些是模型。光有模型干不了任何智能体的事,它得被装进一个外壳里。

模型不能读文件、不能跑命令、不能上网、也不记得昨天发生的事——它只吃词元、吐词元,一次请求干一次活。你感觉到的"智能体在干活"——选工具、读结果、循环到任务完成——全是外壳在背后串联了几十次预测。

模型是分档位的:大的最聪明但慢又贵,小的快又便宜但能力弱。选档位是个真决策——规划和硬骨头 bug 用重量级,机械性改改用轻量级,而且大多数外壳允许你在会话中途切换。

把这个词用严格了,排查问题会变快。 "这个模型不行"是个非常具体的指控——但同一个模型换个外壳、换个上下文,表现可能完全不一样。在怪模型之前,先看看你给了它什么:绝大多数让人失望的输出,根子在上下文或者外壳,不在参数。

💬 对话示例

"规划那一步要不要从 Sonnet 换成 Opus?"

"可以试——但这个任务主要是外壳在扛。如果系统提示词和工具有问题,换模型救不了。"


参数(Parameters)

一句话:模型内部那几十亿个数字,训练时调好的,训练完就冻住了。模型"知道"的一切都在这里面。也叫权重(weights)

机制上说,参数就是把输入变成输出的那套计算:上下文窗口里的词元进去,跟参数做一遍巨量的乘法,出来下一个词元的概率。 模型内部没有事实数据库,没有代码查找表,就是这些数字,被排布成"算出来的结果通常有用"的样子。它能背出来的标准库 API,属于参数知识——存在参数里,不是从哪儿查出来的。

最关键的一点:训练结束后参数就冻住了。 你在会话里做的任何事都不会改变它——你纠正它没用、给它看代码库没用、它犯了错也学不到。每次会话跑的都是同一套数字。 这就是为什么模型是无状态的、为什么它的知识止于知识截止日、为什么你项目里的东西只能通过上下文喂进去。唯一能改参数的办法是再训练一次——而那就等于换了个模型。

💬 对话示例

"能不能拿我们代码库微调一下?"

"那就是改参数了,改完等于另一个模型。为了一个项目,把代码库当上下文喂进去,几乎永远比重新训练划算。"


训练(Training)

一句话:把海量文本喂给模型、不断调参数让它"接话接得更准"的过程。一次性、极贵,由模型服务商来干。

机制就是大规模重复:给模型一段文本,让它猜下一个词元,把参数往"真实答案"的方向推一点点,然后在几万亿个词元上重复这个过程。没有任何东西是以"事实"或"规则"的形式存进去的——模型"知道"的一切,都是"预测得更准"这件事的副产品,被压进了参数里,也就是参数知识。

训练分预训练(大头)和后训练(指令跟随、安全对齐这些后期打磨),在本词典这个层面不用区分。

两个跟你日常相关的后果:

  1. 训练有个结束时间,所以模型有知识截止日——你上个月升级的库版本它没见过。
  2. 训练这事儿你干不了。 当模型不了解你的代码库、你的约定、你的内部 API 时,解法永远不是"教教它",而是把材料放进上下文——那是你唯一能控制的输入。

💬 对话示例

"能不能让它学会我们的内部 API?"

"别走训练——那是服务商层面、按月算的事。把 API 文档加载进上下文,这才是你手上真正能拉的杆。"


推理(Inference)

一句话:跑一个训练好的模型、让它吐输出——每次请求模型时发生的就是这件事。

一个模型的一生分两个阶段:

阶段 什么时候发生 干什么 参数状态
训练 发布前,一次 从语料里算出参数 正在被写入
推理 每次有人用模型 拿冻住的参数跑你的上下文,生成词元 只读

推理时不会把任何东西写回参数——这就是你今天纠正了它、明天它照样犯同一个错的原因。那个模型不是无视你,它是在学习这件事上无能为力。模型是无状态的,连续性只能从外部来:上下文窗口,或者记忆系统。

这个机制也解释了账单:每次请求都要把整个上下文跑一遍,所以成本随输入词元和输出词元增长,而一个调了几十次工具的智能体,每一趟来回都要付一次推理的钱。上下文大小因此既是质量问题,也是钱的问题。

💬 对话示例

"为什么是按用量收费,不是买断授权?"

"你在为推理付费——每一次模型请求都在服务商的机器上跑了一遍。训练的钱早就花完了,推理是每次请求都要付的,而且一个回合里调了工具的话会展开成好多次请求。"


思考档位(Effort)

一句话:一个旋钮,控制模型在回答之前先想多久。按请求设置。

它控制的是模型开始写你看到的那段回答之前,先在心里推演多长。这段思考跟别的东西一样,是在推理时生成出来的;外壳经常把它藏起来不给你看,但那是模型实实在在干的活。

档位调高 = 更慢 + 更贵。 思考是以词元的形式吐出来的,按输出词元计费(哪怕你一个字都没看见),而且是一个词元一个词元生成的——所以调高档位既拉长了等待,也加厚了账单。买的是更充分的思考,代价是时间和钱。

大多数外壳把它做成一个小阶梯:

档位 适合什么
机械性改动、查东西、路径明确的改动
日常编码,通常的默认值
棘手的 bug、设计决策、多步规划
最高 最硬的骨头,答错了返工代价极高的那种

调错了两头都难受。 难题上开低档:得到一个自信但肤浅的答案,读着挺顺,错在一个你后面才发现的地方。一行重命名开最高档:你干等它想了半天,产出的东西跟最低档一模一样。

按任务配档位,不是按会话配。 真正需要推理的地方调上去,周围的机械劳动调下来。

💬 对话示例

"这个并发问题它一直修不好,我都讲了三遍了。"

"把思考档位调高。这是个重推理的 bug,默认档位下它还没想够就定了方案。"


词元(Token)

一句话:模型读写的最小单位,大致相当于"词"那么大,但不等同于词。上下文窗口大小、成本、速度,全按词元算。

文本要通过一个分词器(tokenizer)变成词元:那是一个训练前就学好的、几万个片段的固定词表,任何输入都会被切成这个表里的一串条目。模型从来没见过"字"或"单词"——进去时全部转成词元,出来时也是一个词元一个词元地吐。

经验值:英文里 1 个词元 ≈ 四分之三个单词,1000 词元 ≈ 750 个单词。中文大致是 1 个汉字 ≈ 1 个词元左右(常见词可能被合并成一个,生僻字、emoji 会被拆成好几块)。

代码更没准:常见关键字很省,但生成的标识符、哈希值、base64、压缩后的代码会被切得很碎。规律是:在分词器的训练语料里出现得越频繁的东西,编码越短。 function 是一个词元,而 a3f9c2e1 这种从没出现过的哈希会被切成好几个。这就是为什么一个看着不大的文件、里面全是奇怪字符串,能占掉吓人的一大块上下文窗口。

词元是所有计量的单位:成本按词元(输入和输出分开计价);速度按每秒多少词元(因为输出是一个一个生成的);上下文窗口是个固定的词元数,所以你的文件有多大,决定了能装多少。

⚠️ 别这么说:别把词元叫"字"或"词"。词元的边界和词的边界对不齐,真正有意义的单位是"每秒多少词元"和"每块钱多少词元"。也别把 API 账单上的 token 当成"字数"来估算成本,会被差出好几倍。

💬 对话示例

"这个提示词大概会有多大?"

"过一遍分词器看看—— schema 本身很紧凑,但那些 JSON key 写得很怪,切出来的词元会比你想的多。"


下一个词元预测(Next-token prediction)

一句话:模型真正会做的唯一一件事:看着上下文,猜下一个词元,接上去,再猜下一个。循环。

每一步都一样:上下文窗口里的词元经过参数计算,给词表里每个词元都算出一个概率(这个很像下一个,那个不太像),然后从这些概率里采样一个,接上去,用变长了一点的上下文再跑一遍。采样这一步,就是同一个提示词两次跑出不同结果的原因——不确定性是机制自带的,不是后来加上的 bug。

记住这个机制,很多"看着诡异"的行为一下就通了:

💬 对话示例

"智能体是怎么'决定'要调工具的?"

"它没有'决定'——一路都是下一个词元预测。所谓工具调用,就是它输出的一段结构化文本,由外壳从输出流里解析出来。"


不确定性(Non-determinism)

一句话:同样的输入,可能产出不同的结果。你的代码一点没改,答案也可能不一样。

这是模型生成文本的方式、以及服务商提供服务的方式共同决定的。推理时,模型给下一个词元算出一个概率分布,然后从里面采样一个——而且通常是有意加了随机的,因为永远只选概率最高的那个,产出的文本会又呆又重复。

早期采样错一个词元,后面所有词元都会跟着变——这就是一个不同的词能滚成一个完全不同的方案的原因。服务商那边还要再加一层变数:请求是在共享硬件上批处理的,不同批次之间微小的浮点差异,就能让两个概率接近的词元分出胜负。没有任何开关能把这事儿彻底关掉。

实际影响有两条:

  1. 重试是正当策略。 一次失败只是从这个分布里抽了一次签,重来一次可能就抽到好的。
  2. 验证比用确定性工具时更重要。 你不能测一次就说"它以后都这样",所以必须靠自动检查去兜住那些抽得差的签。

但别把这事儿过度叙事化。 人天生爱找规律,连着几次跑砸了,很容易得出"这周模型变笨了"的结论——大多数时候,那只是分布而已。

💬 对话示例

"Claude 今天太拉了,是不是他们发了个更差的版本?"

"大概率不是——模型输出本来就是不确定的。同一个任务,你有状态好的时候也有状态差的时候。明天再试一次,别急着去找原因。"


模型服务商(Model provider)

一句话:真正把模型跑起来、提供推理服务的一方。通常是远程服务(Anthropic、OpenAI、Google),也可以是本地的(Ollama、LM Studio、llama.cpp)。

外壳自己不跑模型,它去请求服务商。 服务商握着机器:参数住在它的硬件上,每一次模型请求都是外壳把词元发过去、把预测拿回来。

这也让服务商成了整整一类问题的源头,而这些问题经常被错怪到模型头上——限流、容量下降、服务中断,全在这儿。智能体在会话中途卡住、或者每回合都报错时,先去看服务商的状态页,比查别的都值。

服务商还定商业条款:输入/输出词元的单价、前缀缓存的折扣、以及你能用哪些模型。注意:服务商和模型的制造方可以是两家公司——Bedrock、Vertex、OpenRouter 卖的都是别人家的模型。

本地服务商是用能力换控制权:能塞进你自己机器的模型比前沿模型小得多,但数据不出本机,也没有按词元计费的账单。

💬 对话示例

"能给那个内网隔离的客户做个离线版吗?"

"把模型服务商换成本地的——他们机器上装 Ollama 或 llama.cpp。外壳根本不关心,只是换个接口地址。"


外壳(Harness)

一句话:模型之外、把它变成智能体的一切东西:工具、系统提示词、上下文窗口管理、权限、钩子。Claude.ai 和 Claude Code 跑的是同一个模型,但表现完全不同,因为外壳不同。

译法说明:Harness 中文圈还没统一,有人叫"外壳""宿主""载体""运行框架"。本书统一叫外壳——它的本意就是"套在模型外面的那套装备"。

模型本身只会一件事:文本进、文本出。它读不了文件、跑不了命令、记不住上一回合。这些全靠外壳补上。 外壳负责:为每次模型请求组装上下文、执行模型要求的工具调用、把工具结果喂回去、存储会话历史、在危险操作前问你许可、决定什么时候压缩。那个"智能体循环"——模型提议、外壳执行、重复——是外壳在跑。

这对排查问题至关重要。 两个产品表现不同、或者同一个产品今天和昨天不一样,变量往往不是模型,是外壳:不同的系统提示词、不同的工具集、改过的权限默认值、新的上下文管理策略,都能在模型不变的情况下改变行为。也意味着你的大部分配置都配在外壳上——AGENTS.md、权限设置、钩子,都是给外壳的指令,不是给模型的。

例子:Claude Code、Cursor、Codex CLI——以及 Claude.ai(它是个聊天外壳,不是写代码的外壳)。

💬 对话示例

"同一个模型,为什么 Claude Code 能改文件,Claude.ai 只会回答问题?"

"外壳不同——Claude Code 有文件系统工具、不同的系统提示词、还有一层权限。这里的变量不是模型。"


一次模型请求(Model provider request)

一句话:外壳到模型服务商的一次往返。外壳把当前上下文发过去,服务商返回一个响应(一个工具调用,或者最终答案)。

你发一条消息,可能触发很多次模型请求——智能体每调一次工具,工具结果回来就触发下一次请求。

每次请求都带着全部家当:系统提示词、到目前为止的完整对话、每一个工具结果。模型是无状态的,服务商在请求之间什么都不留——第 40 次请求会把第 39 次发过的东西原样再发一遍,外加一个新的工具结果。前缀缓存存在的意义就是让这种重复变得便宜。

请求也是计费单位。 输入词元、输出词元、缓存折扣,都是按请求算的——这就是为什么一个看着人畜无害的问题能烧掉不少钱:成本不是跟你的消息长度成正比,而是跟请求次数 × 每次携带的上下文大小成正比。

请求和回合是两个东西,要分开。 一个回合是你跟它的一次交换,而"修一下这个挂掉的测试"这样一个回合,实际是这样展开的:

请求 模型返回 外壳接着干
1 工具调用:跑测试 跑了,把失败输出追加进去
2 工具调用:读测试文件 把文件内容追加进去
3 工具调用:读源码文件 把文件内容追加进去
4 工具调用:改源码文件 应用改动,把结果追加进去
5 工具调用:再跑一次测试 跑了,把通过输出追加进去
6 最终回答:"修好了,测试通过" 展示给你

一个回合 = 六次请求,每次都重发整个上下文。 想知道词元花哪儿了,数请求,别数回合。

💬 对话示例

"就问了一个问题,烧了四万词元?"

"看工具调用——12 次 grep、8 次读文件、4 次改文件。每个工具结果都会触发一次新的模型请求,而且每次都把整个会话前缀重发一遍。"


输入词元(Input tokens)

一句话:每次请求里外壳发出去的词元——系统提示词、对话历史、工具结果,所有模型动笔之前要读的东西。单价比输出词元便宜。

做 AI 编程时,输入词元是你账单的大头。 因为模型是无状态的,每一回合都要把整个会话重发一遍:你的第一条消息、它的每次回答、此后的每个工具结果。第 50 回合的输入里,装着前 49 回合。 一次请求可能只产出几百个输出词元,却要重发十万词元的历史。

前缀缓存能救一部分:和历史完全吻合的部分按便宜的缓存词元计费,而不是全价输入。输入成本还是疼的时候,办法就是缩小重发的内容——任务之间清空或压缩。

💬 对话示例

"账单很高,但它几乎没写什么东西啊。"

"是输入词元——每回合都要重发整个会话。没有前缀缓存的话,你等于每次请求都为整段历史重新付一遍钱。"


输出词元(Output tokens)

一句话:模型生成出来的词元。单价比输入词元高(常见是 5 倍左右),因为生成比读取更费算力。

模型写的每一个词元都算:你读到的文字、它吐的代码、工具调用、还有它回答之前的长考。最后这项最让人意外——思考词元即使外壳不展示给你,也按输出计费,而且思考档位调得越高花得越多。

输出词元还决定了会话的节奏。 模型读输入很快,但输出是一个词元一个词元憋出来的,所以一个回合感觉慢,几乎永远是"正在写",不是"正在读"。 等得久,通常意味着一个长答案正在路上。

💬 对话示例

"重构这个会话烧钱特别快,可输入明明不大。"

"它在整文件重写而不是打补丁。输出词元单价大概是输入的五倍——让它改成输出 diff,账单立刻下来。"


前缀缓存(Prefix cache)

一句话:服务商那边的缓存机制,让连续几次请求可以跳过重复处理"相同开头"的部分。命中了就按便宜得多的缓存词元计价。

缓存之所以划算,是因为会话是只往上追加的。每次请求都要把整段历史当输入词元重发一遍,而正常会话里,历史只在末尾变化——每次请求基本就是上一次请求再加几条新消息。 服务商把那段长长的共同开头处理一次、存起来,然后从前缀结束的地方接着算。没有缓存的话,一个 50 回合的会话等于把第 1 回合重算 50 遍。

缓存也会过期。 各家的保留时长不一样,一般是"几分钟"这个量级,不是几小时。会话闲太久,下一次请求会把前缀按全价重建一遍再恢复缓存。这主要是做外壳的人要操心的;对你来说,肉眼可见的效果就是:长时间暂停之后的请求,比暂停之前的贵。

缓存还有个脆弱的地方:它只匹配完全一致的前缀。 如果外壳在每轮的系统提示词里注入了当前时间,那第一处变化之后缓存全断,之后每次请求都按全价算。

💬 对话示例

"为什么账单在会话中间突然飙了一下?"

"外壳开始往系统提示词里塞当前时间了。前缀缓存从第一个变化的词元处就断了,之后每次请求都按全价计费。"


缓存词元(Cache tokens)

一句话:服务商从之前的请求里缓存下来的输入词元,命中前缀缓存时按很低的折扣价计费。让长会话变得付得起的那根杠杆。

模型是无状态的,所以每次请求都要把整个对话重发一遍——系统提示词、每条消息、每个工具结果,全算输入词元。到第 50 回合,每次请求都扛着 50 回合的历史,而且每一回合都要按全价付一遍。 缓存改变了这个算式:前缀完全一致、服务商已经算过的那部分,按缓存词元计费,常常只有输入单价的十分之一甚至更低。 长会话里你发出去的大部分都是缓存词元,账单才没爆。

每个字母代表一小段对话内容,每次请求发送的是"到目前为止的对话":

请求发送 命中缓存 全价计费 原因
AB AB 第一次请求,没东西可对
ABC AB C AB 与上次请求的前缀完全一致
ABCD ABC D 前缀仍然完整
AXCD A XCD 前面内容被改了(BX),从那里开始匹配失败

缓存的脆弱点很具体:它只认完全一致的前缀。 只要前面有任何东西变了——外壳调整了内容顺序、时间戳更新了、某个文件的表示方式变了——从那一点往后缓存全部失效,后面的都按全价输入计费。 缓存还会在几分钟不活动后过期,所以长时间暂停后恢复的会话要再付一次全价。

会话成本莫名其妙地涨了,就去用量报告里对比缓存词元和输入词元——缓存坏了会最先在那儿露出来。

💬 对话示例

"长会话太烧钱了——一次重构八美元。"

"看缓存词元那一项。如果外壳在每回合之间重排了系统提示词或者文件,前缀就断了,你等于每次请求都按全价重付一遍输入。"


第 2 章 · 会话、上下文窗口与回合

无状态(Stateless)

一句话:不把信息往前带。模型在请求之间是无状态的,智能体在会话之间默认也是无状态的。

模型是永久无状态的:参数训练完就冻住了,推理时你做的任何事都改不了它。它不从你的纠正里学习,不记得昨天你跟它说过同样的话,也没有在慢慢了解你——不管对话感觉起来多像那么回事。

会话内部的"连续感"是外壳制造出来的:它保存着聊天记录,每次请求都重发一遍。模型不是在回忆这段对话,它是在重读。

实际后果:想让它跨会话记住什么,你得写下来,写到它下次会读回来的地方。这就是 AGENTS.md、记忆系统、交接文档存在的意义——它们是替补,替补那个模型根本没有的记忆。

所以,当它反复犯一个你纠正过的错时,问题不是"它为什么没学会"——它学不会。问题是:这条纠正应该写在什么地方,才能让以后的每一次会话都读到它。

💬 对话示例

"为什么每次清空之后,它就把我们的约定忘光了?"

"模型是无状态的,新会话从空白开始。想让它带着走,就写进 AGENTS.md,或者写进外壳每次会话开始时会加载的记忆文件。"


上下文(Context)

一句话:智能体现在手上有的、跟任务相关的信息。是个抽象名词——不是模型看到的原始输入(那是上下文窗口),也不是运行历史(那是会话)。

这三个词要分清楚:

指的是什么
上下文 智能体当前拥有的、与任务相关的信息
上下文窗口 模型每次请求实际看到的那串词元
会话 外壳存着的那段正在进行的对话

分开讲是有意义的,因为上下文衡量的是质量,不是数量。 一个窗口快满了,上下文可能依然极差——几千词元的过期工具输出,没一条跟当前任务有关。反过来,窗口几乎空着,上下文也可能极好:就那一个关键的类型定义,任务全靠它。

日常翻车大多数都追溯到上下文。 它凭空造了个 API、推翻了自己之前的决定、猜了个 schema——第一个要问的问题是:它干这事的时候,上下文里有什么? 答案通常是:相关的事实压根没加载进来,或者被注意力衰减埋掉了。

解法永远是"策展":任务需要什么就加载什么,不需要的别放进来。

💬 对话示例

"它老是在编一些类型里根本没有的字段。"

"类型文件没进上下文——它读的是调用处,在那儿瞎猜。先把定义读进来。"


上下文窗口(Context window)

一句话:模型每次请求能看到的一切。有上限、每个模型不一样,而且是模型感知世界的唯一通道

它就是一串词元:系统提示词、到目前为止的对话、外壳喂回来的每个工具结果。在这串序列里的东西,模型就能用;不在里面的,模型根本不知道它存在——你的代码库、你昨天改的文件、你三次会话之前给的指令,全都不存在。窗口外的任何东西,都必须先通过工具调用拿进来,才能起作用。

"有上限"意味着它会被填满。 每一回合都在往上追加,长会话最终会撞上天花板,逼你压缩或清空。也意味着窗口里的东西是互相抢地盘的:你多加载一个词元,别的东西就少一个;你塞进去的没用内容,照样占用模型的注意力预算。

正确的姿态是:把窗口当预算花。任务需要什么加载什么,剩下的别碰。

⚠️ 别这么说:别把上下文窗口叫"记忆"。它是工作状态,不跨会话留存。 记忆系统是叠在它上面的另一层概念。

💬 对话示例

"我能把整个 monorepo 粘进提示词吗?"

"窗口是 20 万词元——大概装得下仓库的五分之一。挑这个任务真正碰到的文件,其余的留在工具调用后面。"


有状态(Stateful)

一句话:会把信息往下带。会话在回合之间是有状态的(上下文一路累积,所以长会话会漂进变笨区);智能体在会话之间可以靠记忆系统变成有状态。模型永远不可能是有状态的。

每一层的"有状态"住在哪儿:

有没有状态 靠什么
模型 永远没有 参数是冻住的,它只看得到每次请求里的东西
会话 跨回合有 外壳把每条消息和每个工具结果追加进上下文
外壳 跨会话有 记忆文件、AGENTS.md、交接文档——写下来,以后再加载
环境 永远有 不管有没有会话在跑,文件都在那儿

每一层的"有状态",都是靠重读下一层存着的东西搭出来的:会话之所以感觉连续,是外壳把消息历史重发给了无状态的模型;智能体之所以跨会话还记得,是外壳从环境里重新加载了文件。从来没有任何状态存在模型自己身上。

但状态也不总是好事。 所有往前带的东西都会影响后面,所以一个早期做出的错误假设,也会被一路带着走。 清空就是主动扔掉会话状态、从写下来的东西重新开始。

💬 对话示例

"它记得我昨天的偏好——那是不是说明模型学会了?"

"没有。之所以像'有记忆',是因为外壳把它写进了记忆文件,会话开始时又加载了一次。模型本身对昨天一无所知。"


智能体(Agent)

一句话:一个被装进外壳的模型——配好了工具、系统提示词、上下文窗口,然后跟你一来一回地干活。Claude Code 是智能体,Cursor 是智能体,Claude.ai 也是智能体。

译法说明:中文圈叫"智能体"最多,也有人叫"代理""Agent"。本书统一叫智能体

跟这本词典里大多数词不同,"智能体"指的不是某个机械部件。模型是一堆参数文件,外壳是你能指着说"就是这个软件"的东西,而智能体哪个都不是——它是你在对话的那个对象。 是模型动起来之后的形态,是为了某个目的被配置好的那个单位。

人们不停地拟人化 AI,而智能体就是那个被拟人化的单位:你把活派给它、它读你的消息然后回答、它是"它又把构建弄坏了"里的那个"它"。你说智能体干了什么,意思是"模型 + 外壳"一起干的,但你在把这个组合当成一个角色对待。

这个概念比这一波 AI 热要老得多。软件智能体——你把一个目标托付给它、它代表你去行动的程序——这个概念跟 AI 本身一样老。

⚠️ 别这么说:"那个 AI"、"那个机器人"——太模糊了,听不出来你说的是参数,还是那个被装起来的东西。

💬 对话示例

"迁移这活你用哪个智能体?"

"本地用 Claude Code,UI 那块用 Cursor——底下是同一个模型,外壳不同。"


系统提示词(System prompt)

一句话:外壳在每次请求最前面塞进去的指令——智能体的"岗位说明书":它是谁、该怎么表现、能调哪些工具、要遵守哪些约定。

系统提示词是外壳厂商写的,不是你写的,而且在编程类外壳里它非常大——常常是几万词元的行为规则、工具说明、边界情况处理,每一回合都要按输入词元付一遍钱。 你自己的常驻指令跟它并排加载:像 AGENTS.md 这种文件,会在会话开始时放在系统提示词旁边,于是模型在读你的消息之前,先同时读了厂商的说明书和你的。

因为它每次请求都一样,它构成了前缀缓存的开头——这也是外壳倾向于整个会话固定它、而不是边跑边改的原因之一。

还有一点很关键:模型被训练成优先服从系统提示词,而不是你的消息。 所以当智能体坚持某个你没要求的约定、或者用一种你怎么都改不掉的格式输出时,它多半是在服从系统提示词——而你的消息在这场争论里是输的。 有些外壳是可定制的,会把系统提示词完全开放给你,你能读到它到底被灌了什么,也能改。

💬 对话示例

"两个外壳,同一个模型,同一个提示词,行为完全不一样。"

"系统提示词不同。一个被调成简洁地改代码,另一个被调成爱解释——分歧在你消息到达之前就已经存在了。"


会话(Session)

一句话:跟一个智能体交互的一次完整、有边界的过程。从空开始,一路上累积消息、工具结果、读过的文件,到清空、关闭、或者被压缩成一个新会话时结束。

会话就是那个把上下文窗口填满的东西:如果上下文窗口是箱子,会话就是慢慢把箱子塞满的内容。一次窗口装不下的活,必须拆到多个会话里做。

会话的消息历史就是智能体的工作记忆。 模型是无状态的,所以它看起来"记得"的一切——你要什么、测试报了什么、三回合前它定了什么——全在那条消息历史里,每次请求重发一遍。不在会话里的东西,对它来说不存在。

这份记忆随会话结束而结束。 新会话从零开始:昨天那个对你的代码库了如指掌的智能体,今早一问三不知。能活下来的是文件系统——上一个会话写下的文件,下一个会话能读到,这正是交接、记忆系统、AGENTS.md 依赖的东西。

会话在哪儿结束,是你定的。 会话里的一切都会影响后面的每一回合,所以在一个会话里塞进不相关的任务,会留下残渣、给下一个答案染色。一个会话只做一件事,能保持上下文干净;一件事做完,就是清空的自然时机。

💬 对话示例

"一个会话能跑多久才开始崩?"

"看活的类型——目标明确的重构比开放式调研能撑得久得多。会话一臃肿,就交接或者压缩,别硬扛。"


回合(Turn)

一句话:你发一条消息 + 智能体在响应里做的所有事,直到它把控制权交还给你。包含一次或多次模型请求(调了工具的话就是很多次)。

一个澄清式提问会结束这个回合;你回了,下一个回合开始。层级关系是:会话 > 回合 > 模型请求

回合值得单独命名,是因为它的长度是智能体决定的,不是你。 你递过去一条消息,然后由它决定要串多少次工具调用才交还控制权。一个回合可以是一句话的回答,也可以是二十分钟的读文件、改代码、跑测试。

这是一个性质的两面:回合长,才让挂机成为可能;回合长,也正是没人看着时容易出事的地方——等它交还控制权的时候,它可能已经跑偏到你意思之外很远了。

回合也是纠偏的天然单位。 回合内部发生的一切你都插不上手,回合之间的空隙才是你重定向的时机。 大多数外壳把这个软化了一点:你可以在回合中途打断它、或者边干活边打字(消息会在回合结束后被读到)。

如果你老是不满意回合结束时的结果,解法通常是:要更小的回合——先出计划、一步一步来,用自主性换更频繁的纠偏机会。

💬 对话示例

"一个回合花了两分钟?"

"它在这个回合里调了 14 次工具——每次都是一个独立的模型请求。延迟是叠加的,最后才交还给你。"


第 3 章 · 工具与环境

环境(Environment)

一句话:智能体干活的世界——外壳之外的一切,它只能通过工具结果感知、通过工具调用改变。外壳是"跑"智能体的,环境是智能体"在其中干活"的地方。

AGENTS.md 这种文件住在环境里,而把它加载进上下文窗口的是外壳。文件系统是最常见的一种环境,但不是唯一的(数据库、远程 API、一个浏览器会话,都可以是环境)。

智能体只有去看的时候才看得见环境。 它对环境的全部认知都来自工具结果,所以它脑子里的图景是一堆快照,每张在拍摄的那一刻是准确的。如果一个文件在它读过之后被改了——你手动改了、构建脚本重新生成了——它会继续基于那份过期的副本推理,直到有什么东西促使它重读。 一个智能体自信地描述一个"早就不长那样"的文件,通常就是这个:环境动了,快照没动。

环境也是唯一永远有状态的那一层。 会话结束,上下文就没了;但写进环境的文件还在,下一个会话能读——这正是记忆系统、交接文档、AGENTS.md 依赖的东西。任何你希望它明天还知道的东西,最后都得落到环境里。

环境多大,是你定的。 沙箱把它缩小,限制它能碰到什么;加一个工具把它扩大,把一个数据库或 API 纳入射程。边界内的东西,它才感知得到、改得动;边界外的,对它来说不存在。 环境被收拾得有多适合智能体干活,就是这份代码库的 AX

⚠️ 别这么说:别用"环境"指运行时或外壳本身——外壳是包装,环境是工作场所。

💬 对话示例

"智能体看不到预发库的 schema。"

"把它接进环境——给个 psql 工具,权限限定成预发库只读。外壳没问题,是它没东西可干。"


文件系统(Filesystem)

一句话:智能体读、写、在其中执行命令的那棵目录树——编程智能体默认的环境。

AGENTS.md、技能包、源码、构建脚本、工具配置,全住在文件系统里。当一个外壳说"在你的项目里启动",它指的就是把智能体指向一个文件系统。

智能体只能通过工具调用碰它——读文件、写文件、跑 shell 命令。磁盘上的任何东西,在工具调用把它加载进来之前,都不在上下文窗口里,这正是智能体能在远大于窗口的仓库里干活的原因:文件系统装着全部,上下文只装着当前任务读过的部分。 有些外壳默认会把当前目录的文件名(不是内容,就那棵树)加载进上下文窗口,它们起的是上下文指针的作用:它知道有什么,然后去读它需要的文件。

而且这个文件系统是跟你共享的。 它改的文件,就是你在编辑器里打开、在 git 里 diff 的那同一批文件——文件系统是你 review 它工作的公共工作区。

💬 对话示例

"它为什么没读到我的 AGENTS.md?"

"它跑在别的文件系统上——沙箱挂的是父目录,不是项目根目录。把外壳的指向改一下。"


工具(Tool)

一句话:外壳暴露给智能体调用的一个函数——读、写、跑命令、搜索。工具是智能体感知和改变环境的唯一方式。

大多数编程智能体自带这几个:

工具 干什么
把文件内容作为工具结果返回
在文件系统里创建或修改文件
命令行 跑一条 shell 命令并返回输出
搜索 在代码库里按模式找文件或文本

每次工具调用都要多花一次模型请求,因为结果得回到模型那儿,它才能决定下一步。

一个工具由三样东西定义:名字、描述、参数格式。外壳每次请求都把这些定义发给模型,而模型选工具的方式跟产出别的东西一模一样——靠写词元,这里写的是一段带参数的结构化调用。模型自己从不执行任何东西;外壳读这段调用、执行函数、把结果发回去。

工具清单决定了智能体能干什么。 一个很强的模型配上一套很窄的工具,就是个很窄的智能体——它会把什么都往仅有的工具上凑,这就是为什么智能体那么依赖命令行:一个 shell 就是一个能摸到系统大部分地方的工具。 想干净地给它加一项能力,就加一个工具;MCP 就是把外部工具插进外壳的标准。

工具定义在每次请求里都占上下文,所以工具多是有固定成本的——哪怕一个都没调。而且一堆描述相似的工具,会让模型更难选对。

💬 对话示例

"智能体能直接查预发库吗?"

"给外壳加个 psql 工具,权限限定预发只读。没有对应工具的话,文件系统之外的东西对它来说就是黑的。"


工具调用(Tool call)

一句话:模型输出的"我要调某个工具、参数是这些"——就只是一段结构化文本,它自己不产生任何作用,得由外壳读出来去执行。

一次工具调用的生命周期:

步骤 发生什么
1 模型 从系统提示词的描述里知道有哪些工具
2 模型 输出一段调用——工具名 + 参数(通常是 JSON)——然后停下
3 外壳 解析这段调用,拿去跟权限模式比对
4 外壳 允许的话就执行
5 外壳 在下一次请求里,把结果作为工具结果发回去

一个回合的活,通常是很多次这样的往返串起来的。

因为这段调用跟别的东西一样是靠"下一个词元预测"生成的,它也会像任何模型输出一样出错:一个不存在的路径、命令根本没这个参数、看起来合理但实际不对的入参。外壳执行的是"写下来的",不是"心里想的"——路径打错不会优雅报错,它会去改错的文件。

💬 对话示例

"它说它跑过测试了,可文件时间戳没变啊。"

"看会话记录——它到底输出了工具调用,还是只是描述了一遍'跑了测试'?调用是模型产出的,但外壳没执行的话,就什么都没发生。"


工具结果(Tool result)

一句话:外壳执行完工具调用后发回来的内容——文件内容、命令输出、报错。这是智能体看环境的唯一窗口。

它在下一次模型请求里回到模型那儿,模型再决定拿它干什么。工具调用和工具结果是一次交换的两端,都在同一个回合里。

工具结果的生命周期:

步骤 发生什么
1 外壳 执行工具调用——跑命令、读文件
2 外壳 捕获结果:输出、内容、或者报错
3 外壳 作为一条消息追加进上下文
4 外壳 在下一次模型请求里把整个上下文发给服务商
5 模型 读到结果,决定:再调一次工具,还是给出最终回答

这个结果会在这之后的整个会话里一直待在上下文中。 工具结果通常是编程会话里上下文的大头:每读一个文件、每跑一次测试、每搜一次,都完整地留在里面,早就没用了也还占着词元。 几个大的结果——一份超长的测试日志、一个被整个读进来的生成文件——能把会话推到上下文窗口边缘,比对话本身快得多。

因为结果是模型唯一能看到的东西,它没法去核对结果背后的环境。 如果输出被截断了、命令静默失败了、或者外壳返回的是错误而不是内容,模型就基于手里那点东西推理。 当智能体对你的系统的认知明显不对时,去看会话记录里的工具结果:里面有某条结果说的话,跟你知道的事实不一样。

💬 对话示例

"它推理的时候好像当那个文件是空的。"

"工具结果返回的是权限拒绝,不是文件内容。模型只看到了那句报错——它没有别的途径去看那个文件。"


模型上下文协议(MCP)

一句话:Model Context Protocol——一套把外部工具服务器插进外壳的协议,让智能体拿到外壳自带之外的工具。智能体从来不是"调用 MCP",它调用的是工具,只不过那个工具是某个 MCP 服务器提供的。

它解决的是一个集成问题:没有标准的时候,每个外壳都得自己写一遍 Linear 集成、自己写一遍 Slack 集成、自己写一遍数据库集成,还得各自维护。 有了 MCP,这个集成写成一次服务器,任何支持 MCP 的外壳都能用:外壳连上服务器,服务器声明自己提供哪些工具,这些工具就跟内置工具一起对智能体可用了。

(MCP 也能暴露资源和提示词模板,但提供工具是主要用途。)

代价付在上下文上。 服务器声明的每一个工具都对应一份定义——名字、描述、参数格式——而模型只能调用它知道的工具。最朴素的做法是把所有定义一股脑加载进上下文窗口:装几个慷慨的服务器,你一个字还没打,会话就已经背着几千词元的工具 schema 了,白花掉一大块注意力预算。

很多外壳现在用"工具搜索"来缓解:上下文里不放完整定义,只放一个指向可用工具的上下文指针——智能体按名字或用途去搜,需要时才把定义加载进来。如果你的外壳没这功能,那份前置成本就还在,那就只启用这个项目真正需要的服务器。

💬 对话示例

"智能体需要从 Linear 里读工单。"

"给外壳配上 Linear 的 MCP 服务器——它把 Linear API 变成智能体能调的工具。省得你自己写工具封装了。"


权限申请(Permission request)

一句话:外壳在执行一个没被预先批准的调用之前,弹给你看的那一下。模型产出调用,外壳不立刻执行,而是停下来问你。这是外壳把人放进回路里的方式。

权限申请的生命周期:

步骤 发生什么
1 模型 产出一个工具调用
2 外壳 拿去跟权限模式和已保存的批准记录比对
3 外壳 已预批准:立刻执行。否则:暂停并展示申请
4 批准一次 / 本次会话都批准 / 拒绝
5 外壳 执行调用,或者把"拒绝"作为工具结果发回去

拒绝本身也是一种引导。 模型会把"拒绝"当成一条普通工具结果来读并作出反应——它会换个方法,或者来问你想怎么办。大多数外壳允许你在拒绝时附带一句话,这就把一次拦截变成了纠偏点:"别这么干,用迁移脚本"——这句话正好落在模型正在决定下一步的时刻。

代价是:每次申请都是一次同步等待你。 智能体被阻塞着,直到你答复——你盯着的时候没问题,你不在的时候就麻烦了:一个频繁弹申请的智能体是没法挂着跑的。 权限模式就是那个旋钮:哪些调用放行、哪些要先问,理想情况下再配个沙箱,让"放行的集合"可以安全地放大。

💬 对话示例

"它在一次权限申请上卡了十分钟——我在开会。"

"这就是人在环中的成本。把安全的工具预批准掉,让申请只在真正有风险的操作上触发。"


权限模式(Permission mode)

一句话:智能体模式里的"权限闸门"那一半——哪些调用要弹申请、哪些自动放行。这是模式系统最初的用途(后来外壳才在上面捆绑行为指令)。

外壳一般提供这么个阶梯:

模式 写和 shell 典型用途
只读 / 规划 自动 阻止 调研、规划、评审
默认 自动 询问 日常有人盯着的工作
自动编辑 自动 编辑自动,shell 询问 可信仓库、机械性改动
"随便" / 全自动 自动 自动 沙箱里、挂机跑

选哪一档是安全和打断之间的权衡,两头都有难受的地方。 太紧:你成了瓶颈,它每几秒就为一个无害的读操作停下,你闭着眼点批准,于是"批准"本身不再有任何意义——橡皮图章是两头最坏的组合,打断一点没少,保护一点没有。太松:它改了文件、跑了命令,而你本来想先看一眼的。

最松的那一档,只有在沙箱里才说得通——那里一个坏调用的爆炸半径是被圈住的。沙箱之外,大多数人的落点是:读操作自动放行,不可逆的操作留个人在环里。

💬 对话示例

"它每次 grep 都停一下,挂机跑彻底废了。"

"只读工具放宽权限模式,写和 shell 继续询问。调研类会话里的大部分权限申请都是噪音。"


智能体模式(Agent mode)

一句话:一个塑造智能体运行时行为的预设——把权限模式和注入系统提示词的行为指令打包在一起。可以在会话中途切换。

"打包"是它跟单纯的权限设置的区别。 权限模式只是一个闸门:它决定哪些调用能过。光有闸门,会得到一个"想改但改不了"的智能体——它提出写入、被拦、然后想别的办法绕。注入的指令消除的是那个"想":规划模式不只是阻止编辑,它告诉智能体"你现在在规划阶段",于是它去读、去问、去提议,而不是跟闸门较劲。 闸门和引导指向同一个方向。

常见的几种:默认模式(危险操作询问)、规划模式(阻止编辑、引导它去调研)、接受编辑模式(自动批准编辑)、绕过权限模式(俗称 YOLO 模式,全都自动批准)。

实际用法是:随着你在任务过程中信任度的变化换模式。 同一个任务可以穿过几个模式:方案还在成形时用规划模式,头几处精细改动用默认模式,等它证明自己理解了这个改动后切接受编辑,挂机跑的时候在沙箱里用绕过模式。换模式不损失任何东西:对话从原处继续,只是权限和指令变了。

如果你发现自己每次都不看就批准,说明模式设得比你实际的信任更松;如果你一直在拒绝改动,说明设得太紧了。

厂商叫法:Claude Code 叫 "permission modes",Codex 叫 "approval modes"——两个名字都早于"捆绑行为指令"这件事。

💬 对话示例

"我只想要个计划,它一直在改文件。"

"切规划模式——它会阻止写入,留在调研状态。"

"那等会儿挂机跑呢?"

"绕过权限模式,但只在沙箱里。"


沙箱(Sandbox)

一句话:智能体跑在里面的一个隔离环境——容器、虚拟机、临时文件系统、或者受限权限的 shell。它限制的是智能体行为的爆炸半径:哪怕它跑了破坏性命令、拉了恶意内容,损害也被圈住了。这是让挂机变成可行的安全底座。

沙箱和权限模式从两头解决同一个问题:权限是在行动发生之前问你;沙箱是限制这个行动如果真发生了能够到哪儿。权限需要你留在环里——每次弹窗都是一次打断,一个老在问的会话几乎谈不上自主;沙箱花的是基础设施,不是你的注意力:隔离越强,需要问的问题就越少。

隔离分几个等级:

等级 是什么 能圈住什么
受限 shell 操作系统层面给每条命令上的枷锁 项目外的写入、网络访问
容器 全新的文件系统、不挂载凭证、用完就丢 智能体对它自己机器做的任何事
虚拟机 / 云 完全独立的一台机器,常由外壳提供 一切,包括内核级逃逸

没有哪种沙箱能圈住"合法地离开它"的行为。 一个拿着你 git 凭证的智能体能 push;一个能上网的智能体能调生产环境 API。先决定什么允许跨越边界,再决定隔离做多厚。

💬 对话示例

"我想让它通宵跑'绕过权限'模式,但我还没准备好。"

"放沙箱里——全新容器,不挂凭证,不出网。最坏情况它把自己文件系统炸了,你把容器一丢。"


第 4 章 · 它是怎么犯错的

讨好倾向(Sycophancy)

一句话:自信且顺着你说话的输出。模型被训练得"喜欢说人爱听的话",而人通常更喜欢被认同、而不是被纠正——于是它学会了:顺着说是安全的,哪怕顺着说是错的。

译法说明:中文技术圈有"谄媚性""阿谀倾向""讨好性"几种说法。大白话就是马屁精模式

它长这样:

诊断方法没有你的引导,它会这么说吗? 如果唯一变化的是你的语气或者说法,那就是讨好倾向,不是分析真的变了。

解法把你的偏好藏起来。 中立地描述——说"评审一下这段代码",而不是"这段代码写得不错吧?"。

⚠️ 别这么说:别把任何"恰好让你高兴的错误答案"都叫讨好倾向。不做上面那个诊断测试,这个词就比"错了"多不了任何信息。

💬 对话示例

"它说我这个重构方案非常好,然后我问了句'你确定吗',它就把整个方案收回去了。"

"典型讨好——先顺着你,是因为你听起来很自信;后撤,是因为你听起来在怀疑。方案的质量没变,你的语气变了。清空,不带任何倾向地重新问一遍。"


幻觉(Hallucination)

一句话:自信但错误的输出。分两种,成因不同,解法还相反。

类型 错在哪儿 原因 解法
事实型(Factuality) 编造或搞错关于世界的事实——一个不存在的函数、错误的 API 签名、假引用 参数知识有洞,常见于超过知识截止日的部分 把正确的上下文知识加载进来
忠实型(Faithfulness) 输出偏离了已经加载进来的上下文知识、你的指令、或者它自己之前的推理 注意力衰减,在变笨区里会恶化 清空压缩

"下一个词元预测"这机制,不管底层事实是不是真的,都能产出流畅的输出——模型内部没有"我不知道"这个信号,所以一个编出来的方法,跟一个正确的方法,是用同一副很有把握的口气说出来的。 幻觉代码从构造上就是"看起来合理"的:它就是那个 API 如果存在的话应该长成的样子——正因为如此,它才能骗过粗看一眼的评审,只在跑起来的时候才挂。

你必须分清自己面对的是哪一种,因为治一个的药会让另一个更糟:

把忠实型误诊成事实型,你会再粘一批文档进去,上下文变大,漂移更严重。 所以:它搞错一件事的时候,先确认正确的信息是不是早就在上下文里了,再决定你面对的是哪个问题。

⚠️ 别这么说:别把"幻觉"当成"错了"的同义词。不说清楚是哪一种,这个词就没有诊断价值。

💬 对话示例

"它幻觉出一个 schema 上根本不存在的 parseAsync 方法。"

"事实型还是忠实型?"

"我粘给它的文档里有这个方法——它就是到第 40 回合之后不读了。"

"那就是忠实型。压缩重来,别再贴文档了。"


参数知识(Parametric knowledge)

一句话:模型从训练里"知道"的、存在参数里的东西。训练时就冻住了,模型看不见自己的参数,也改不了。

细节都在这次挤压里丢了:几十亿条事实塞进固定数量的参数里,罕见的那些就糊了。这是它在常见话题上很流利、在冷门话题上开始编的根源。跟上下文知识是一对。

参数知识不是以"事实"的形式存的。 训练从不给模型一个可以查的数据库;它只是调参数,调到模型能很好地预测文本为止——而一个能把某话题的文本预测得很好的模型,表现得就像它懂这个话题。

可靠性跟它在训练数据里出现的频率挂钩:有上百万例子的主题,它复现得很准;只有寥寥几例的主题,它就按"相似的主题长什么样"去猜。复现和猜测,对模型来说是同一个过程,它分不清自己在干哪个。 于是一个编出来的答案,跟一个正确的答案,流利程度一模一样。 幻觉就是它猜错了。

参数知识还会过期。 参数在知识截止日那天停止变化,所以那之后发布或改名的库,在它脑子里根本不存在;改过的 API,它记的还是老样子。

这两种缺口——太冷门和太新——解法是同一个:知识没法加进参数,只能作为上下文知识提供。

💬 对话示例

"它写 React 写得完美,但一碰到我们内部 SDK 就开始编方法。"

"React 在参数知识里密度极高——训练数据里有上百万例子。你们 SDK 没有,所以它只能填一个看起来像的形状。把 SDK 文档加载进上下文。"


知识截止日(Knowledge cutoff)

一句话:这个日期之后,模型就没有参数知识了。之后出现的库、API、事件,全是编造陷阱——除非你把它们的文档作为上下文知识加载进来。每个模型发布时都自带一个截止日。

为什么会有截止日?因为模型是这么造出来的:训练把某一时刻的文本快照烤进参数,然后参数冻住。

而模型不知道自己的知识有边界。 被问到截止日之后的事情,它不会说"这个我不知道",它会从自己知道的、最近的东西往外推。 这正是这个陷阱安静的原因:照着旧版库写出来的代码看着很合理,往往还能编译,只在真正改动过的那些地方挂掉。

解法永远一样:把当前信息弄进上下文。 加载 changelog、指向你装的那个版本的类型定义、或者让它上网去读文档。上下文里有的东西,永远压过参数里没有的东西。

💬 对话示例

"它一直写 v3 的 SDK 语法,我们都 v5 了。"

"v5 是在知识截止日之后发的。把 v5 的 changelog 作为上下文知识加载进去,否则它会一直照着参数里那个旧版本编。"


上下文知识(Contextual knowledge)

一句话:智能体现在能直接从上下文里读到的事实——你的任务、它读进来的文件、工具结果、会话开始时加载的 AGENTS.md跟参数知识是一对:参数知识是"回忆"出来的,上下文知识是"照着读"的。

智能体基于上下文知识干活的时候,幻觉会少得多——答案就在眼前,不用从模糊的记忆里往外刨。

两种知识里,只有上下文知识是你说了算的。 参数是冻住的,所以想给模型它不具备的知识——一个内部 SDK、一个截止日之后发布的库、一个昨天才做的决定——唯一的办法就是放进上下文。 大量 AI 编程的实操工作,最后都归结成这一件事:在它需要的时候,把对的事实摆到它眼前。

两者冲突时,通常上下文赢。 你把当前 API 文档贴进去,它会照着文档走,而不是照着它脑子里那个过期的记忆——不过旧版本还是可能渗出来,尤其在长会话的深处。 如果文档明明加载了它还一直退回旧写法,那就是参数知识漏过了上下文知识;把纠正再说一遍、或者挪到离当前工作更近的地方,会有帮助。

跟参数知识不同,上下文知识是要花钱的。 加载进窗口的每一样东西都要花词元、都要抢注意力预算,所以加载得更多不自动等于更好——目标是"相关的事实"在窗口里,不是"所有的事实"。

什么时候用这个词:只在跟参数知识对照的时候用,其他时候直接说上下文就行。

⚠️ 别这么说:别叫"工作记忆"。上下文知识是此刻在窗口里的东西;记忆系统是跨会话往窗口里送东西的机制。两个尺度,别混。

💬 对话示例

"为什么我贴了文档它就写得准,不贴就开始编?"

"贴了文档,那是上下文知识——照着纸念。不贴,就是参数知识,那些冷门接口全是糊的。"


注意力关联(Attention relationship)

一句话:模型预测每个词元时,都会把上下文里所有其他词元考虑一遍——有的影响很大,有的几乎没影响。两个词元之间的这种配对关系就叫注意力关联。 上下文有 N 个词元,就有大约 N² 个关系。

模型的"理解",就活在这些配对里。 它能消解代词,是因为"她"和"小芳"之间的关联很强;它能用正确的参数调一个函数,是因为调用处和它前面读到的函数定义之间的关联在起作用。这些没有一样是查表查出来的——每次请求都要为每一对重新算一遍。

N² 这个数字值得停一下,因为它涨得比直觉快得多:

上下文大小 配对数(约 N²)
1,000 词元 ~100 万
10,000 词元 ~1 亿
100,000 词元 ~100 亿

而且每一对还不止算一次。模型有多个注意力头(前沿模型的具体数量没公开,几十到上百是个合理猜测),每个头都要把每个关系自己算一遍——上面表格里的每一个配对,都要在每个头上重复一次。配对数量非常恐怖。

但其中只有极少数的关系对某个具体任务是有意义的。 你的指令和它管着的那段代码之间的关系,属于"算数的那几个";池子里几乎其他所有东西都是噪音。而且这两者增长速度不一样:有意义的关系数量大致不变,而关系总数随上下文平方增长。 1,000 词元时,你关心的那个配对是百万分之一;100,000 词元时,它是百亿分之一。这就是注意力预算底下的那道算术题,而注意力衰减,就是"有意义的关系分到的份额变得太薄"时的那种感觉。

💬 对话示例

"它一直把 diff 里那两个 user 搞混——听起来我们进变笨区了。"

"是啊,每个调用处和它对应声明之间的注意力关联在互相打架——词元长得一样,绑定关系不同。把其中一个改名,配对就清楚了。"


注意力预算(Attention budget)

一句话:每个词元能分给上下文里其他内容的"影响力"是有限的。在一个关系上花重了,留给其他关系的就少了。这个预算是按词元算的,不会随上下文变大而变大——这就是长会话会稀释的原因。

把它想成信号和噪音。 你的指令是一个音量固定的信号;上下文窗口里其他每个词元都是来抢它注意力的杂音。指令本身一点没变小——它还在那儿,一个字都没少——但随着上下文变长,它周围的房间越来越吵,信噪比就掉了。 一条在 1 万词元时是全场最响的指令,到 15 万词元时就成了背景嗡嗡声。

这就是注意力衰减背后的机制:模型不是忘了,是信号被噪音盖住了。

症状看起来像"不听话":智能体早先答应了一个约束,后来慢慢偏离,你把约束再贴一遍也只能管一小会儿。问题不在指令,在窗口里其他所有东西在跟它抢。

你能控制的是"往上下文里放什么"。 跟任务无关的内容不是中性的——它是盖在所有有用内容之上的噪音。 保持窗口小,累积的上下文不再值回票价时清空,重要的约束反复申明,而不是指望提一次就能一直生效。

💬 对话示例

"为什么它一直无视我在最上面贴的那个 schema?"

"我们早进变笨区了——每个词元的注意力预算是固定的,可上下文一直在涨。schema 上那点信号,现在要跟几千个更新的词元竞争。"


注意力衰减(Attention degradation)

一句话:随着会话变长,每个词元的注意力预算要摊给更多竞争者。任何一个有意义的关系上的信号都被摊薄,无关上下文的噪音挤了进来。同一个模型、同一套参数——只是同一盘菜要多喂更多张嘴。

它表现为模型在会话中途变笨:坚持了一个小时的约束开始松动,开始重复问已经告诉过它的事,写出的代码无视了它早先读过的文件。模型什么都没变,唯一的变量是它现在要照顾多少上下文。

它是渐进的,这正是难在会话内部发现的原因。没有报错、没有阈值,每一回合只比上一回合差一点点,等到错误明显的时候,你已经在变笨区里待了一阵了。

恢复的办法是删上下文,不是加。 把被无视的指令再贴一遍,是往同一个拥挤的窗口里又加了一个竞争者,只能管一小会儿。真正管用的是:清空后只重新加载任务需要的东西,或者压缩,或者交接给一个新会话。

把"指令跟不上了"当成上下文长度的信号,而不是模型能力的信号。

💬 对话示例

"它深陷变笨区了——在编类型文件里根本没有的泛型。"

"注意力衰减。类型定义还在上下文里,但它们身上的信号已经被后来加的东西埋了。清空重载。"


聪明区(Smart zone)

一句话:会话早期,智能体在一个"聪明区"——清醒、专注、记得住。随着会话变长,它漂进"变笨区":更糙、更健忘、错误更多,忠实型幻觉也更多。同一个模型、同一个外壳——只是上下文变多了。

("变笨区 dumb zone"就是这个说法的反面,两个词是一起的。)

下滑是渐进的,所以很容易漏掉。没有报错、看不到分界线,它只是开始表现得稍差一点,然后明显更差。常见的征兆:忘了你二十回合前给的指令、重复一个早就纠正过的错误、或者自信地陈述一个跟上下文矛盾的东西。因为滑坡是平滑的,通常的反应是硬扛、反复解释——而这会加更多上下文,让问题更糟。

这两个区跟上下文窗口的上限不是一回事。 窗口还剩大半的时候,会话可能就已经深陷变笨区了:上限是外壳拒绝继续的地方,而质量在那之前早就掉下来了。按聪明区规划,别按窗口规划——一个任务的实用预算,是智能体还干得好的那段词元数,不是它技术上能装多少。

聪明区是份预算,不相关的活也在花它。 会话里做的每个任务都在消耗词元,所以在同一个会话里开第二个任务,等于让它从更靠近变笨区的地方起步。一个会话一个任务,每个任务都能用上会话最清醒的那段。当一件事比一个聪明区还大时,就切开:在自然边界处交接或压缩,让新会话去干下一段。

参考数值:在当前的前沿模型上,变笨区通常从 12.5 万~15 万词元左右开始——不过这一点有争议。会话一臃肿就清空或压缩,别硬扛。

💬 对话示例

"前三个组件它做得漂亮,第四个彻底搞砸了。"

"你出聪明区了——模型还是那个模型,只是现在深在变笨区里。压缩一下重新加载计划,下一个组件就能落地。"


第 5 章 · 交接

清空(Clearing)

一句话:结束当前会话,开一个新的。下一条消息面对的是一个空会话、一个空上下文窗口。

清空是治"脏上下文"的药。 一个会话会累积一切:失败的尝试、走错的弯、过期的工具结果、废弃的计划。模型每一回合都要把这些重读一遍,糟糕的历史会拖累新工作。 长会话的深处,智能体变得越来越含糊、越来越不听话——你明明说清楚的指令被无视,质量下滑,催它"好好干"也没用,因为它正蹚着的那片噪音还在它的上下文里。清空把这堆噪音删掉。

清空不会抹掉对话记录。 大多数外壳把会话历史存在你本机上,记录还在,你可以读、可以恢复。消失的是智能体的工作状态:模型是无状态的,所以新会话对旧会话一无所知。 如果这个会话里有下一个会话需要的决定或进展,先让它写一份交接文档,然后新会话从那份文档开始。

对比压缩:压缩是把会话总结成一段摘要塞进新上下文;清空是更粗暴的工具——什么都不带过去,包括垃圾。

💬 对话示例

"它卡在那个挂掉的测试上死循环了。"

"直接清空——拿计划文档和那个测试文件开个新会话。跟现有上下文较劲没意义。"


交接(Handoff)

一句话:把智能体的上下文从一个会话转移到另一个会话。方式各异——写一份交接文档、在内存里总结(压缩)等等。跟清空不同(清空是一点都不带)。

接收方会话从零上下文开始——模型是无状态的,旧会话的任何东西对新会话都不可见。下一个会话需要什么,就必须明确地带过去;其余的全没了。

"没有回头路"是塑造交接方式的那个约束:新会话没法回头问旧会话"你那话什么意思",所以带过去的东西必须自己站得住。

方式 形态 特点
交接文档 写在环境里的文件 你能先读、先改,再让任何东西依赖它;可以复用于很多会话
压缩 上下文窗口里的摘要 自动且便宜;难以检查;只喂给一个后继会话

一次糟糕的交接,看得见的失败是"翻旧账":新会话把旧会话已经定下来的决定重新拿出来吵一遍,因为带过去的东西记了"决定了什么",没记"为什么"。

评判一次交接好不好,就看一个零上下文的会话拿到它能干成什么。

💬 对话示例

"规划会话越来越重了——我是不是接着往下干就行?"

"做个交接。把决定写进文档,清空,然后开个新会话读着它做实现。"


一手资料(Primary source)

一句话:原始形态的真值来源——代码、会话记录、原始日志、真实的 API 响应。不是对这件事的描述,就是这件事本身。 跟二手资料是一对。

想知道你的代码库干了什么,代码就是一手资料。 文档、架构图、README 全是对它的描述——写下的那一刻是准确的,之后就按自己的节奏过时了。 当智能体自信地陈述了一件关于你项目的错事,要问的是:它是基于哪个来源在干活? 读了文档的智能体,会继承那份文档的过时程度;读了代码的智能体,读的是当下的事实。

不把一手资料当默认选项的原因,是成本。 把它加载进上下文窗口很贵——完整的文件、完整的记录,每个词元都要按输入计费,还要抢注意力预算。你花这份钱买到的是"完整":没有任何东西被别人的判断预先过滤掉。一份上个月写的摘要,装不下今天才发现重要的那个细节;一手资料还装着。

需要精确的时候去找一手资料——确切的签名、真正的报错、抛异常的那一行。管理上下文的很大一部分工作,就是判断什么时候该为一手资料付这个钱、什么时候二手资料就够用了。

💬 对话示例

"智能体说重试逻辑是指数退避的,可我看着它在死命打那个接口。"

"它是从设计文档里读来的。把它指向真正的重试模块——涉及行为的时候,用一手资料。"


二手资料(Secondary source)

一句话:对一手资料的转述,隔了一层——描述代码的文档、描述会话记录的摘要、描述搜索结果的报告。比它描述的那份原始资料便宜,但天生有损:写它的人决定了什么重要,而他丢掉的东西,对只拿着摘要的读者来说是不可见的。

上下文工程里很大一块活,就是在制造二手资料。 压缩把会话历史变成喂给下一段的摘要;子智能体把噪音很大的搜索烧在自己的上下文里、只回报一小段报告;交接文档把一个会话的决定浓缩成下个会话读的文档;记忆系统把一个会话学到的东西提炼成笔记。每一笔都是同一个交易:用保真度换空间。

二手资料会以两种方式失效。 一是有损——压缩摘要弄丢了 schema 那个决定,报告里没提那个边界情况。二是漂移——一手资料变了,转述没跟着变,于是文档用本季度的自信描述着上季度的架构。当智能体基于一份以任一方式失效的二手资料干活时,它会自信地基于错误信息工作;解法是把它送回一手资料。

但这两种失效都不意味着二手资料是个错误。 上下文窗口是有限的,一手资料是贵的;没有摘要、报告和交接文档,任何大一点的活都装不进来。 本事在于:知道哪些细节扛得住这种损失,扛不住的,就拿一手资料去核对。

一份做得好的二手资料,会带一个指回原件的上下文指针——摘要里点明它来自哪份记录、文档里点明它描述的是哪个文件——这样当转述不够用时,读者可以顺着指针去查,而不是硬着头皮用那份有损的东西。

💬 对话示例

"交接文档说鉴权做完了,可新会话一直发现 token 刷新是坏的。"

"文档是二手资料——上个会话写的是它当时相信的事,不是事实。让新会话跑一遍鉴权测试,信一手资料。"


交接文档(Handoff artifact)

一句话:用作交接载体的文档——由一个会话写进环境、给另一个会话读。方案文档、工单、计划文档,全都是交接文档。

为什么要写?因为模型是无状态的,会话里的一切在清空时就消失了。 决定、约束、做了一半的计划——全都随着承载它们的上下文一起没了。环境是持久的。把重要状态写进文件,就是把它挪到下一个会话能读回来的地方。

交接文档是一份二手资料——对会话工作的转述,不是工作本身。这既是它能小到可以给新会话做简报的原因,也是它可能误导新会话的原因:它记录的是"写它的那个会话相信的事",它漏掉的、搞错的,读者是看不见的。凡是重要的论断,下一个会话都应该拿一手资料(代码、测试)去核对,而不是直接继承。

一份好文档,是写给一个零上下文的会话读的。 具体的文件路径,而不是"我们讨论过的那个文件";决定了什么以及为什么,这样下个会话不会翻旧账;什么做完了、什么还没做。 写的时候告诉那个会话文档的用途会很有效:"写一份交接文档,给一个对此一无所知的新会话看。"

另一个载体是压缩(在内存里总结)。交接文档有两个优势:它躺在磁盘上,任何东西依赖它之前你能先读、先改;而且它可以复用——同一份方案文档能同时给五个并行会话做简报。

💬 对话示例

"规划智能体和实现智能体之间我该怎么切?"

"让规划方写一份交接文档——文件路径、决定、约束。实现方的会话一打开就拿到一个指向这份文档的指针,然后拿它当任务简报干活。"


方案文档(Spec)

一句话:描述一件跨多次会话的工作的交接文档——要造的是什么,不是每个会话怎么干自己那份。它会随着工作推进而变形。由工单组成。

方案文档之所以存在,是因为会话是一次性的,而大活不是。 任何需要超过一个上下文窗口的工作,都需要在上下文之外有个家——一个在清空之后还活着的地方:仓库里的一个文件、一个 GitHub issue、或者智能体能够到的工单系统。方案文档就是那个家:目标、约束、到目前为止的决定、以及工单及其状态的清单。 任何新会话读一遍就知道工作进展到哪儿了,而不用继承上一个会话累积的噪音。

方案文档有几种常见的写法,基本继承自团队本来就怎么写东西:

风格不重要,角色才重要:对智能体来说,这三种是同一个东西——它每次会话开始时读的那份持久的意图声明。

💬 对话示例

"这事儿一个会话能搞定吗?"

"不行,写成方案文档——拆成工单,每个工单跑一个会话。想在单个上下文里干完,你一半都没走到就撞进变笨区了。"


工单(Ticket)

一句话:把一次会话的活圈起来的交接文档。可以独立存在,也可以挂在方案文档下面当它的子项。工单之间可以互相阻塞,所以工作顺序是从依赖关系里长出来的,而不是一条线性计划。

定义性的约束是尺寸:一个会话。 一个工单应该能在会话漂出聪明区之前干完——而且这个约束是可以检验的:如果你的会话经常在活干完之前就开始退化,说明工单太大了,切小;如果每个会话大部分上下文都花在环境准备上、然后才干了五分钟的活,说明太小了,合并。

一份好工单,是写给一个没有其他上下文的读者看的。 目标、验收标准、指向相关文件和决定的上下文指针——够让会话直接开工,不用重新推导上一个会话知道的东西。

依赖图还顺带解锁了并行:互相独立的工单(图里的叶子节点)可以各自在自己的会话里同时跑——这是同时开多个智能体最有效的方式。

💬 对话示例

"迁移的方案文档我从哪儿下手?"

"看工单依赖图——schema 改动阻塞回填,回填阻塞 API 切换。挑一个叶子节点,为它开一个会话。"


压缩(Compaction)

一句话:在内存里完成的一次交接:把上个会话的历史总结一遍,用这段摘要去开一个新会话。天生有损:会话记录是一手资料,摘要是二手资料——用细节换空间。 可以你手动触发,也可以由自动压缩触发。

机制是这样的:上下文窗口是有限的,长会话会把它填满——每个工具结果、每个读过的文件、每个走错的弯都留在历史里。太重的时候,外壳让模型把会话总结一遍,然后把原始历史丢掉,用摘要去开一个新会话。 没进摘要的东西,就从上下文里消失了。有些外壳会把这一点软化:旧记录留在磁盘上,并在摘要里留一个指向它的上下文指针——二手资料链回一手资料,摘要弄丢的细节还能靠重读原件找回来。

摘要是模型写的,所以你可以指挥它:"保留关于 schema 的决定"能让产出的东西更有针对性。时机也重要——在阶段边界压缩,方案定了之后,别在任务中途压。

对比清空:清空是全部丢掉、冷启动;压缩是想把要紧的带过去,清空是赌它们已经写在别处更好的地方了。

💬 对话示例

"上下文越来越重了,我还有一轮测试要跑。"

"开始前先压缩——把必须活下来的东西写进压缩提示里,让新会话保留 schema 的决定、丢掉探索过程。"


自动压缩(Autocompact)

一句话:上下文窗口快满时,由外壳自动触发的压缩。

外壳盯着窗口有多满。越过阈值(常在 80% 左右)时,它暂停,让模型总结目前为止的会话,然后用摘要开一个新会话,工作接着往下走,像什么都没发生一样。

但确实发生了点什么。 压缩是有损的,而自动压缩是在一个你没选的时刻有损。 手动压缩发生在阶段边界,那时你能告诉模型要保留什么;自动压缩在任务中途触发,只要撞上阈值就发——可能正做重构做到一半,由摘要自己决定你的哪些决定值得保留。

典型症状:智能体自信地继续干活,但已经悄悄忘了一个你一小时前立下的约束,而你要等它的产出开始跟那个约束矛盾时才发觉。

防御办法是不让它触发。 盯着上下文指示器,在自然边界处手动压缩;或者把决定写进磁盘上的计划文档或交接文档,那里没有任何摘要能弄丢它们。 大多数外壳还允许你调这个缓冲区——把阈值提前或推后,或者干脆关掉自动压缩——这样你就能调它在触发前给你留多少余量。

💬 对话示例

"它好像不记得我们早先关于 schema 定了什么。"

"自动压缩在两回合之间触发了——早期的决定被总结了一遍,我们大概丢了点东西。重新加载计划文档,或者下次手动压缩,这样什么被保留由你说了算。"


第 6 章 · 记忆与引导

记忆系统(Memory system)

一句话:一套试图让智能体跨会话"有状态"的机制。在会话过程中把信息写进环境,在后续会话开始时重新加载进上下文窗口,这样你清空了会话,连续性还在。

它有两条路径:

很多外壳自带记忆系统(Claude Code 的 /memory 就是一个),你也可以自己搭一个:一个笔记目录 + AGENTS.md 里一句"去查一下这个目录"。

所有"常驻内容"都有的权衡,它也有。 记忆会累积,所以大多数系统只加载一行索引,正文留在上下文指针后面,而不是全量内联。而且记忆是二手资料,会漂移:三月记下的一条事实,到六月项目早就变了,它还会以同样的自信被加载出来。记忆系统需要修剪,跟 AGENTS.md 一样。

💬 对话示例

"我一遍遍跟它说我们用的是 Postgres 不是 MySQL。"

"接个记忆系统——第一回合就把它学到的写进文件系统,会话开始时再加载回来。模型本身是无状态的,记忆层是伪造出来的连续性。"


AGENTS.md

一句话:环境里的一个文件,外壳在会话开始时把它加载进上下文窗口——项目给智能体的常驻简报。 这是个跨外壳的约定;有些外壳还有自己的变体(Claude Code 的是 CLAUDE.md)。

因为它自动加载,它是你避免跨会话重复自己的一种方式。 模型是无状态的:你在这个会话给的一条纠正,下个会话就没了——于是你不得不对每个新会话重复一遍"这个项目用 pnpm""测试要带那个 flag""那个目录是生成的别动"。当你就同一件事纠正了它两次,那条纠正就是 AGENTS.md 的候选。

适合放进去的,是它没法从代码里推导出来的东西:构建和测试命令、代码库本身看不出来的约定、硬性约束("永远别改生成的那个 client")。简短、陈述句——它是简报,不是文档。

权衡在于:里面的东西每次都加载。 指令会累积,其中大部分对任何具体任务都是无关的,而一份很长的 AGENTS.md 既烧词元又自我稀释——上下文里的指令越多,模型对其中任意一条的遵守度就越低。

⚠️ 别这么说 / 别这么用:别把应该渐进式展开的内容塞进 AGENTS.md——里面的任何一行,每个会话、每一回合都要付词元成本,不管这次会话需不需要它。 一份编码规范应该放到技能包或上下文指针后面;AGENTS.md 只留那些到处都适用的几行。

💬 对话示例

"为什么每个会话一上来就已经烧掉 4k 词元了?"

"看 AGENTS.md——有人把整份编码规范粘进去了,那本来该放在技能包后面。"


渐进式展开(Progressive disclosure)

一句话:只加载智能体当下需要的上下文,其余的留一个上下文指针。这个词借自 UI 设计——那里它的意思是"只给用户看跟他当前任务有关的控件,其余的收在一层点击后面"。

这个技巧存在,是因为上下文是双重成本每个提前加载的词元,每一回合都要按输入词元付一次钱,而且不管智能体需不需要,它都要花注意力预算。

一份塞满了完整编码规范、部署手册、数据库约定的 AGENTS.md,会让它在这三件事上全都变笨——跟当前任务有关的指令,被无关的那些稀释了。征兆是:它无视了你明明知道在它上下文里的规则。 规则在里面,只是被埋了。

渐进式展开把这个反过来。 常驻层保持很小——每个主题一句话 + 一个指向详情位置的指针。 它在写组件的时候读编码规范,在部署的时候读部署手册,在修测试的时候两个都不读。技能包就是外壳里内置的实现:一段每会话都加载的简短描述,完整指令只在被触发时才加载。

💬 对话示例

"我要不要把整份编码规范都倒进 AGENTS.md?"

"别——渐进式展开。把规范做成技能包,它真要写组件的时候才加载。AGENTS.md 里的东西每回合都要付词元钱。"


上下文指针(Context pointer)

一句话:一份文档里指向另一份文档的一句话,让智能体只在任务需要时才把它拉进上下文窗口。渐进式展开就是用它搭起来的。

用指针而不是直接内联内容,原因是成本。 指针在上下文窗口里占一行;它背后的文档可能有几千词元,但在智能体真的去顺着指针读之前,那些词元一分钱不花。 把一份 2000 词元的部署手册内联进 AGENTS.md每个会话都要为它付钱;换成"部署流程:见 internal/deploy.md",只有真要部署的会话才会加载它。 任务对上了,智能体就用一次工具调用顺着指针去读。

一个指针要能用,得有两个部分:一个稳定的路径,以及足够的描述让智能体知道"什么时候值得去读"。一个光秃秃的路径是个"它没有理由去点"的指针——只写"见 internal/deploy.md"、不说明里面是什么,需要它的那个会话会直接跳过。写的时候要匹配任务出现的样子:"涉及发布、部署或回滚——先读 internal/deploy.md"。

一旦你留意,指针到处都是AGENTS.md 里的行、技能包的描述(外壳加载描述,正文等在后面)、目录列表里的文件名、文档之间的链接。

指针还能把一份二手资料系回它所源自的一手资料——点明原始记录的压缩摘要、点明它所描述源文件的文档。这让二手资料的"有损"变得可恢复:当摘要不够用时,智能体顺着指针去读原件,而不是硬着头皮用摘要留下的那点东西。

⚠️ 别这么说:别叫"引用"——太干巴,传达不出"顺着它会拉更多上下文进来";也别叫"传送门"——太花哨。

💬 对话示例

"AGENTS.md 越来越臃肿了。"

"里面大部分应该是指针,不是内容。常驻规则留着内联;部署手册和编码规范做成技能包,只留一个上下文指针。"


技能包(Skill)

一句话:打包成一份的一项可教能力——把"怎么把一件事做好"的指令和相关资源放在一起,存在环境里,等一个上下文指针在任务来时把它拉进上下文窗口。这是外壳里"渐进式展开"的基本单位。

技能包是个开放标准,定义在 agentskills.io——最初由 Anthropic 开发,之后被主流外壳普遍采纳,所以你写一次,到处都能用。 格式是一个文件夹,里面:

默认只有名字和描述在上下文里。 当智能体的任务匹配上了,它才把其余的加载进来。在那之前,技能包几乎不占地方——不管它的完整指令有多长,就那么一两句话的词元。

这正是它跟 AGENTS.md 的区别:后者不管什么任务,每个会话都加载。技能包只在某类活出现时被读——发版时、搭新服务时、写迁移时——其余时间被忽略。

⚠️ 别这么说:别叫"工具"。工具是智能体去"调用"的;技能包是它去"读"的指令。

💬 对话示例

"部署手册放哪儿?"

"做成技能包——只在任务涉及部署时它才加载。放 AGENTS.md 里的话,一个我们一周才用一次的东西,每回合都要烧词元。"


子智能体(Subagent)

一句话:由一个智能体通过工具调用派生出来的智能体。跑在自己的会话里、用自己的上下文窗口,最后回报一个工具结果。 跟交接不同——父级明确等着它回来;交接没有回头路。 它不能再生子智能体,这棵树只有一层深。子智能体的存在是为了隔离上下文,不是为了搭层级。

重点是把吵闹的活挡在父级上下文之外。 一次大范围搜索、或者一场读很多文件的长途跋涉,会产出成页的工具结果,其中大部分只在找到答案的那一瞬间有意义。 在父级里跑:所有这些会在剩下的会话里一直待在父级上下文中。放到子智能体里跑:噪音填满的是一个用完就丢的窗口,最后落到父级上下文里的只有那份报告。

而那份报告是一份二手资料:父级拿到的是子智能体对它发现的东西的转述,不是原始结果,所以报告漏掉的任何东西,对父级来说是不可见的。

子智能体还能并发跑——父级可以就几件互不相关的工作同时派出好几个。

💬 对话示例

"grep 的结果快把我的上下文撑爆了。"

"派个子智能体去做这次搜索——它会在自己的窗口里烧掉那堆噪音,只回报你真正需要的那两个文件路径。"


第 7 章 · 干活的方式

人在环中(Human-in-the-loop)

一句话:一种工作方式——人陪着智能体一起跑这个会话,实时评审、纠偏、协作。人是在场的、参与其中的,不只是给单个操作盖个章。

对照面是挂机(AFK):智能体无人值守地跑,你事后才评判结果。人在环中的价值在于:在问题还便宜的时候抓住它。 你看到它伸手去拿错文件、误解了需求、或者开始钻死胡同,一句话就把它掰回来——而不是二十分钟之后才发现,那二十分钟信心满满的工作全建立在那一个错误上。 智能体并不可靠地知道自己在跑偏;没人看着的时候,它们倾向于硬着头皮往前推,而不是停下来问。

哪种方式合适,取决于活的类型:

判断标准本质上就是两句话:走错一步有多贵?你多晚才会发现?

有些活天然就得在环里,因为你的反应本身就是输入。 连环追问只有你在那儿回答问题时才成立;快速原型只有你在那儿对实物作出反应时才成立。

留在环里的成本是你的注意力,那是最稀缺的资源。 跟智能体协作变熟练的一部分,就是安全地把更多活移出环外——用计划、用自动检查、把人工评审放在最后,而不是全程监督。

💬 对话示例

"这个能挂机跑一晚上吗?"

"不行,schema 迁移,留在环里。我要看着每一步,它要是挑错了回填的来源列,我得能拦。"


挂机(AFK)

一句话:Away from keyboard。你开一个会话然后走开,让智能体无人值守地跑。 这是 AI 编程的吞吐倍增器——你睡觉、吃饭、干别的事的时候,可以同时跑好几个挂机会话。通常需要宽松的权限模式 + 沙箱才安全。

你不在的时候,它处理含糊之处的方式不一样。 你盯着的时候,一个含糊的决定会变成一个提问,你来回答;你一走开,它就选个默认值继续往下走,而后面每个决定都建立在这个猜测之上。

典型的失败是:你回来,看到几个小时已经完成的、自信满满的工作,全建立在头十分钟里做错的一个选择上。 这份工作不糙——它是自洽的,只是自洽在一个错的东西上。

既然跑的过程中你给不了输入,就在前后给:

挂机不取消人工评审,它是把所有评审推迟到最后——这也是为什么最后送到的那个东西必须值得评审。这也是 AX 在挂机场景下最重要的原因:没人看着的时候,环境是智能体唯一能得到的支持。

⚠️ 别这么说:别叫"后台智能体"——那个说法把重心放在机器上("在后台跑着"),而 AFK 说的是人的模式("用户走开了")。AFK 点明了真正要紧的那个事实:没人看着。

💬 对话示例

"我要挂机跑了——三个沙箱智能体做这次重构,早上来看 PR。"

"绕过权限模式?"

"对,文件系统只读,不出网。"


自动检查(Automated check)

一句话:跑在环境里的确定性验证——测试、类型检查、lint、构建、pre-commit 钩子。非过即挂,不带判断。 这是智能体能自己纠正自己、不用惊动任何人的信号。一个 flaky 的测试是"坏掉"的检查,不是"非检查"——自动检查按设计就是确定性的。

自我纠正是个循环:智能体做个改动,用一次工具调用跑检查,失败输出落进它的上下文窗口——一个带文件名和行号的类型错误、一个带期望值和实际值的失败断言。这些东西足够它修好问题,然后再跑一次检查,一圈一圈直到通过,全程不需要人。 确定性是这个循环可信的原因:同样的代码永远给出同样的判决,所以"通过"是有意义的。 一个 flaky 的检查会毒害这个循环——它会去"修"本来没问题的代码,或者重试着重试着重过了本来真失败的检查。

这就是为什么好的检查是代码库 AX 的一大块。 在一个有严格类型、快速测试套件和 linter 的仓库里,智能体在你看到之前就抓到了自己的大部分错误;在一个什么都没有的仓库里,它产出什么就交付什么。 这个差别在挂机时最要命——跑的过程中,检查是唯一在发生的验证。

但检查只能抓到它断言了的东西:检查全绿意味着"被断言的那些属性成立",不意味着代码是对的。 需要判断的那些缺口,是自动评审和人工评审的地盘。

⚠️ 别这么说:别叫"反馈循环"或"反向压力"——这两个都把检查和评审混在一起了。也别叫"测试"——测试属于自动检查,但不是所有自动检查都是测试。

💬 对话示例

"挂机跑出来的代码一直是坏的。"

"沙箱里接了哪些自动检查?"

"就单元测试。"

"加上类型检查和 lint——有了这些,PR 落地之前它就能自己纠正过来。"


自动评审(Automated review)

一句话:让一个智能体评审另一个智能体的工作,常用不同的模型或不同的系统提示词。不确定性:它形成的是判断。可以跑在任何地方——PR 合并前、对提交历史做事后评审、或者在会话中作为子智能体跑。CI 里跑一个"LLM 当裁判"是自动评审,不是自动检查——决定类别的是这个断言"做了什么",不是它"跑在哪儿"。

跟干活那个智能体分开,是它有效的原因。 让写这份代码的智能体评审自己的工作,你几乎什么都得不到——产生这个 bug 的那个会话,也装着产生它的那段推理,它把自己的结论读回来,读成了确认。 而一个拿着全新上下文窗口的评审者没有这种依恋:它像陌生人那样看这个 diff,而评审依赖的正是这一点。 换个模型、或者换个评审专用的系统提示词,会进一步锐化这个效果——不同的盲区,而且系统提示词可以只聚焦你真正关心的东西(安全、API 契约、性能),而不是一句含糊的"看看有没有问题"。

它插在另外两层评审之间。 自动检查是确定性的,抓能机械断言的问题;人工评审最贵、最不好扩展。自动评审在中间:以机器的成本,抓住需要判断的问题——一个误导性的函数命名、一个漏掉的边界情况。因为它是非确定性的,它会漏东西、也会报假警;把它当成"在人看之前抬高下限的过滤器",而不是"取代人的闸门"。

⚠️ 别这么说:"AI 评审""智能体评审"——太含糊,分不清是不是指干活那个智能体自己。

💬 对话示例

"挂机跑出来的坏 PR 太多了。"

"合并前加一步自动评审——换个模型、独立的系统提示词,只聚焦安全和契约变更。"


人工评审(Human review)

一句话:你读智能体产出的代码并形成判断。读 diff 或者读改动过的文件才算;读它"对自己干了什么"的描述不算——叙述不是产物。 那段描述是二手资料,还出自被评审的那一方;diff 才是一手资料,评审意味着读它。

智能体把产出的代码量抬高了,于是评审成了瓶颈。 一个有用的思路是把几种评审策略分层:自动检查抓机械性失败,自动评审抓可被描述出来的问题,人工评审留给只有你能判断的东西——这个改动是不是对的改动、这个路子跟代码库合不合、这东西到底该不该存在。

评审越早越便宜。 开工前读个计划、或者中途读个小 diff,几分钟;挂机跑完之后去挖一个已经成型的分支,要久得多。 把评审检查点放在哪儿,是个"人在环中"的决策,不是事后想到再加的。

⚠️ 别这么说:光说"代码评审"——分不清是人工的还是自动的。

💬 对话示例

"挂机的产出我人工评审过了。"

"你读的是 diff 还是它的总结?"

"diff。总结里说它删了死代码——结果那个函数在一个生成文件里被调用了。"


氛围编程(Vibe coding)

一句话:一种工作方式——你不人工评审智能体的代码就接受它。 diff 被当成不透明的:重要的是程序跑不跑得起来,不是里面是什么。 自动评审和自动检查可能还在跑,氛围编程对这两者不表态。

这个词来自 Andrej Karpathy,他在 2025 年初造了这个词:你"彻底交给感觉"、"忘记代码的存在"——描述你想要什么,接受回来的东西,靠跑一下来判断。

氛围编程是用检查换速度。 读 diff 通常是智能体驱动的工作里最慢的一步,砍掉它就砍掉了主要瓶颈。 对那些失败代价很低的代码——原型、一次性脚本、内部工具——这是笔划算的买卖。风险随代码的寿命和重要性放大。

代价是后面才到的。 氛围编程攒出来的改动,会堆成一个没人读过的代码库,而且只验证过行为——所以任何行为不暴露的问题:写了进日志的密钥、漏掉的边界情况、悄悄搞错的数据处理,全都看不见地发出去了。第一次有人调试这个系统,就是第一次有人读这段代码。 人工评审没了之后,还在跑的那些自动验证——测试、类型、自动评审——就是代码穿过的唯一一道门。

⚠️ 别这么说:别把"氛围编程"当成"低质量 AI 代码"的同义词——这个词指的是评审立场,不是产出的代码质量。

💬 对话示例

"它改的鉴权流程你读了吗?"

"氛围编程过了——登录还能用,我就查了这个。"

"push 之前把 diff 读了,在鉴权上凭感觉,就是密钥漏进日志的方式。"


共同设计图景(Design concept)

一句话:用户和智能体之间共同持有的、关于"到底在造什么"的理解,它独立于任何具体产物。Brooks 的术语(出自《设计原本》):对话、交接文档、代码,全都是试图捕捉或逼近这个图景的产物,但它们都不是图景本身。 图景的质量,是通过构建它的那场对话的质量被感受到的。

译法说明:原文 Design concept,也有人直译"设计概念"。本书叫共同设计图景,强调的是"你俩脑子里那幅画是不是同一幅"。

这个词命名的是一个熟悉的挫败感背后的那道缝智能体写得完全是你要求的样子,可它还是错的。 通常的原因是你自己还没想清楚要什么——那幅图景在你自己脑子里就没画完,你的提示词捕捉到了你想明白的那部分,对没想明白的部分保持沉默。于是智能体用自己的假设填了那些空白,因为没什么可以对齐的东西。 没有任何东西坏了。只是没有共同的设计图景,因为还没有一个完整的图景可供共享。

判断图景是否共享,跟判断同事是否跟你对齐是同一个办法:对方开始用你会用的方式,回答你还没问出口的问题。 在那之前,工作就是对话——连环追问是这件事的刻意为之的版本——而过早写方案文档,只是把这种不一致固定进了一个更耐久的产物里。 图景还会随着你的学习而移动,产物落在它后面,这就是为什么一份忠实于上周理解的方案文档,仍然会误导这周的会话。

💬 对话示例

"它写的完全就是我说的,可结果还是不对。"

"你们还没有共同的设计图景——它在用假设填空。继续聊,直到取消、退款、部分履约这几件事在你俩之间完全对齐了,再让它写方案。"


连环追问(Grilling)

一句话:一种跟智能体一起打磨共同设计图景的技术:智能体用苏格拉底式的方式采访你,一次一个决定,每个决定都给出一个推荐答案。 它把"赶紧出个计划"这件事慢下来——在图景稳定之前,不写任何交接文档。

这个技术存在,是因为智能体会静默地填空。 你让它拿两行提示词写份方案文档,它不会在你没做决定的地方停下来——它会挑个默认值写进去。结果看着很完整,而猜测和选择混在一起没法分辨,于是你发现得很晚:在评审时,或者在功能已经建好、用一种你从来没选过的方式处理某个边界情况时。连环追问把这反过来:不许猜,必须问。

它是个"人在环中"的技术:你的答案就是输入。 当某个问题没法在对话里回答——你得看到实物才行——那就切到快速原型。

💬 对话示例

"它直接就去写方案文档了,取消逻辑还写错了。"

"先拷问它——让它在往文档里写任何东西之前,先把部分取消、退款、时序这些问题一个一个问你。在对话里解决比在代码里解决便宜。"


快速原型(Prototyping)

一句话:让智能体快速做个粗糙版本出来,用于"对话的保真度不够、你需要一个真东西才好谈"的时刻。

连环追问在对话里解决设计决策。对话便宜,但保真度低:有些问题没法用语言回答——一次交互摸起来什么感觉、这个 API 形状在真实调用代码里顺不顺手、这个布局在真实数据量下撑不撑得住。访谈撞上这么个问题,你诚实的答案是"我不知道,我得看一眼"。 过了这个点,讨论就开始打转了。这时候,让它把东西造出来,你看一看,带着答案回到对话里。

智能体把"造"的成本压低了,这才是这件事变得实用的原因。 一个过去要一天才能搭出来的粗糙版本,现在几分钟就有了,所以值得 routinely(常态化)去做。 它是个"人在环中"的技术:原型摆在那儿,是为了让你对它作出反应。

通常你看一眼不会就停。 跟原型迭代——反应、要求改、再反应——这样每一轮都对着真实产物解决一个决策,保真度比对话高。

原型也不一定非得全是糙的。 你可以把"你真正在评估的那几块"按生产质量来做,这样决策落地时,你反应过的那个组件或 API 可以直接搬进真正的代码库。 这让原型成为方案文档值得引用的第一手材料。

💬 对话示例

"这个向导到底做成一页还是三步,我们吵了半小时了。"

"话解决不了——让它两种都做个原型。我们点一遍,五分钟就有答案了。"


开发者体验(DX)

一句话:Developer experience——一份代码库和它的工具链,让把活干好有多容易。好的 DX 是:快速反馈、清晰的错误信息、能回答你真正那个问题的文档、一次就成功的环境搭建。这个词远早于 AI 编程,进这本词典主要是作为 AX 的对照。

DX 是人与代码库之间的交互,仅此而已。 两个受众最关键的区别是:人是有状态的,智能体是无状态的。 人把代码库学一次,然后每天带着这份知识来——这就是为什么糟糕的 DX 是可以活下来的:他们靠攒着 push 来绕开慢 CI,靠在群里问一次来绕开缺失的文档,靠"记住东西在哪"来绕开混乱的结构。这些变通办法会累积,最后团队在一个跟他们作对的代码库里依然高产。

智能体面对同一个代码库,一条变通经验都没有。 它跨会话无状态,每次都要从零重新学这个代码库——快速的测试套件和清晰的错误信息它享受得到,但它昨天想明白的任何事情都没了,除非被写进环境,而环境它只能通过工具结果感知。 这就是 AX 要命名的那道缝:DX 里在"开发者变成智能体"之后还剩下的那部分,加上一些人类没有的顾虑,比如保持上下文窗口空闲。

重叠意味着:投资 DX 常常能免费改善 AX——严格的类型、快速的测试、可预测的结构,对两边都有帮助。分歧意味着:并不总是能——一份漂亮的入职文档能帮人一整周,但对智能体一点用都没有,除非它能从 AGENTS.md 走到那份文档。

💬 对话示例

"我们 DX 没问题啊——新人一周就能上手。"

"能上手,是因为那一周有人陪着他坐。智能体没有那一周,AX 得单独看。"


智能体体验(AX)

一句话:Agent experience——环境被收拾得有多适合智能体在这个代码库里干好活。这是 DX 面向智能体的对照面。当同一个智能体在 A 仓库表现很好、在 B 仓库表现很差——同样的模型、同样的外壳——差别通常在 AX。 直觉是怪模型或者重写提示词,但解法更常在仓库里。

好的 AX 有三个主要维度:

维度 好的 AX 长什么样
自动检查 快速、确定性的自动检查(类型、测试、lint),智能体不需要人就能自我纠正
架构 一个不用全读就能导航的代码库:结构可预测、大量行为藏在小接口后面、名字能说明这东西是干什么的
空闲上下文 AGENTS.md、技能包、工具都保持精简,让上下文窗口的大部分留给任务本身,让智能体待在聪明区而不是淹死

AX 和 DX 有重叠——好的检查和干净的架构对两边都有帮助——但也有分歧。 人能忍受口口相传的部落知识、慢 CI、以及"计费模块去问 Sarah";智能体忍不了。智能体也不吃 IDE 悬浮提示和漂亮看板那一套;它们需要的是"以文本形式出现在工具结果里的失败"。 一份代码库完全可以 DX 很好、AX 很差。

⚠️ 别这么说:别把 AX 当成 DX 的同义词——两类受众需要的投资不一样。

💬 对话示例

"这智能体在 API 仓库里写得很好,在前端仓库里写垃圾。"

"API 仓库有严格类型和快速测试套件;前端两样都没有,还常驻加载四十个技能包。这是 AX 的差距,不是模型问题。"


附:一页纸心智模型

七章读下来,其实就这几句话:

  1. 模型只会一件事:看着上下文,猜下一个词元。它不记事、不查资料、不知道自己不知道。
  2. 你能控制的只有上下文。 参数是冻住的,"教它"永远不是解法,"把东西摆到它眼前"才是。
  3. 智能体 = 模型 + 外壳。 行为不一样时,先怀疑外壳和你给的东西,别急着怪模型。
  4. 上下文窗口是预算,不是容量。 塞满不等于有用;堆得越多,关键信息越被淹没(注意力衰减 / 变笨区)。
  5. 钱花在请求次数 × 每次携带的上下文。 一个回合能展开成十几次请求,每次都重发整个历史。
  6. 它跨会话什么都不记得。 想让它记住,就写进环境(AGENTS.md、记忆、交接文档)。
  7. 它出错分两类:不知道(事实型,加上下文)和不遵守(忠实型,减上下文)。治反了会更糟。
  8. 把活从"盯着干"移到"挂机干"的那套装备是:方案文档 + 自动检查 + 自动评审 + 沙箱。

五对最容易混的词:

别混 区别
上下文 / 上下文窗口 前者是"相关的信息"(质量),后者是"看到的那串词元"(容量)
参数知识 / 上下文知识 脑子里的记忆 / 摆在桌上的资料
压缩 / 清空 带摘要过桥 / 什么都不带过桥
自动检查 / 自动评审 非过即挂的确定性验证 / 会形成判断的非确定性评审
工具 / 技能包 智能体去"调用"的函数 / 它去"读"的指令

原版:mattpocock/dictionary-of-ai-coding(英文,Matt Pocock) 本中文版在保留原意与结构的前提下做了重写:术语改用中文语境叫法,例子换成国内团队常见场景,并补充了中文分词、变笨区阈值等本地化说明。