很多读者刚开始用 AI 编程工具,经常会有一个疑问:Cursor、Antigravity 这些编辑器里也能选 Claude 模型,为什么目前来看还是 Claude Code 配合 Claude 模型的编程效果最好?
为什么 Qwen、DeepSeek 等国产模型也能支持在 Claude Code 里使用?和使用官方的 Claude 模型有什么区别?
如果你有这些疑问,说明你还没搞清楚 LLM 和 Agent 之间的关系。
简单说,AI 干活的效果同时取决于两件事:LLM 模型本身的能力,以及围绕模型的 Agent 工程实现。
就好比一辆汽车,LLM 是汽车的引擎,剩下的部分都属于 Agent 工程。引擎强大,汽车的马力就大,但是性能只是最基本的一条要求,一辆好车还需要考虑安全性、易用性、操控性、舒适性等等。所有条件都挑不出毛病,才能开着爽。
回到 AI Agent 也是一样的,底层的 LLM 肯定越强越好,但是围绕 LLM 的 Agent 工程也必不可少,任何一方拉胯,使用体验都会打折扣。
我们说的 Qwen、Claude、DeepSeek 等模型属于 LLM,Cursor、Codex、Antigravity、Claude Code 等 AI 编程工具属于 Agent。
包括最近层出不穷的 AI 工具,比如 Openclaw(小龙虾)、Hermes Agent 等等,他们都是各具特色的 Agent 工具,不仅局限于编程。
这篇文章就来讲清楚 LLM 和 Agent 分别是什么,它们之间是什么关系,让你有一个具象化的理解。不涉及任何具体的 API 调用,只讲原理。
LLM 的本质:概率预测
大语言模型(LLM)的核心原理其实就一句话:根据已有的文本,预测下一个 token 出现的概率。
这里的 token 是模型处理文本的最小单位,通常一个英文单词算一个 token,一个汉字约等于 1-2 个 token。
后面我们会频繁提到 token 这个概念,你可以简单理解 token 就是输入和输出的文本。
比如你输入「今天天气」,模型会计算所有可能的下一个字的概率分布:「真」的概率 30%,「不」的概率 20%,「很」的概率 15%... 然后从中选一个输出。选完之后,把这个字拼到输入后面,继续预测下一个字,如此反复,就生成了一段完整的文本。
所以 LLM 本质上就是一个概率模型,一个字一个字地往外蹦。
你跟 ChatGPT 聊天时看到回答一个字一个字地出现,不是为了打字机效果,这就是它真实的工作方式。
你可能会问:这也太简单了,就靠猜下一个字,怎么能写出那么流畅、那么「有道理」的回答?
关键在于规模效应。当模型的参数量大到几百亿、上千亿,训练数据覆盖了海量文本,这个「概率预测」就变得惊人地准确。准确到让人觉得它真的「理解」了你在说什么。
但要注意,它并不真的理解,只是在做统计意义上的模式匹配。
这就好比一个人把所有棋谱都背下来了,他可能并不「理解」围棋的哲学,但下出的棋比大多数人都强。
在 LLM 往外输出文本时,还有一个参数叫温度(temperature),控制模型选字时的随机程度。
温度设置为 0 时(最低),模型每次都选概率最大的那个字,输出最确定,一般用于编程等精确性高的工作;温度调高,模型就更愿意选那些概率较低的字,输出更有创意但也更不可控,一般用于创意类工作。
另一个重要的概念是上下文(Context)。
模型在预测下一个 token 时,依据的就是当前上下文里的所有文本。你输入的问题、当前会话中的历史消息、系统给的背景设定,这些全部拼在一起就构成了上下文。
举个例子,你跟 ChatGPT 聊天,第一句说「我叫小明」,然后聊了很多别的话题,最后突然问「我叫什么名字」,它能正确回答「你叫小明」。
这不是因为它「记住」了你的名字,而是因为「我叫小明」这句话还在上下文窗口里。模型每次生成回答时,都是依据整个上下文的内容来预测下一个 token 的,所以看起来它好像是「记住」了你的名字。
但上下文的容量肯定是有限的,我们一般称这个容量为上下文窗口(Context Window)。
超出窗口的内容就需要被处理掉,常见的做法是压缩(Compaction):让模型把早期的对话总结成一段摘要,保留重要信息,丢掉细节,从而腾出空间。
所以如果你和 ChatGPT 聊了特别长的对话,再问最开头的问题,它可能就记不清楚了。因为早期的对话已经被挤出了上下文窗口,这就是我们常说的「失忆了」。
目前主流模型的上下文窗口在 200k 到 1M token 之间,大约相当于几万到几十万字。听起来很大,但后面你会看到,在 Agent 场景下这个空间消耗得非常快。
所以,最佳实践是一个会话(Session)只聚焦处理一个问题相关的对话,对于新的问题就重新开始一个新的会话,相当于开启了一个全新的上下文窗口。
我们会在 和 LLM 交互:messages 数组和 token 结合代码具体介绍上下文的概念,在 上下文压缩机制 里讲讲上下文压缩的工程实践。
从补全到对话:Instruct 模型
如果你关注过开源模型(比如 Llama、Qwen),会发现它们通常有两个版本:一个叫 Base,一个叫 Instruct。这两个版本的区别,恰好能帮你理解 LLM 是怎么从「补全引擎」变成「对话助手」的。
Base 模型就是我们上面说的纯概率预测模型。你输入「中国的首都是」,它会接着往下写「北京,位于华北平原……」。
这是在做文本补全,你输入半句话,它帮你把后半句续上。
但你想想,我们用 ChatGPT 的时候,输入「中国的首都是」,它会怎么回答?
它不会帮你续写,而是会回答「中国的首都是北京」。它把你的输入当作了一个问题来回答,而不是一段需要续写的文本。
这就是 Instruct 模型做的事情。在 Base 模型的基础上,用大量的「指令-回答」数据对进行微调(Fine-tuning),再通过 RLHF(人类反馈强化学习)进一步优化。
RLHF 就是让模型对同一个问题生成多个回答,由人类评审员打分排序,模型根据打分调整自己。
经过这两步,模型就明白了:用户输入的不是需要你续写的文本,而是需要你响应的指令。
所以我们平时用的 ChatGPT、Gemini 等 AI 助手全都是 Instruct 模型。Base 模型虽然也很强,但它只会「接话」,不会「回答问题」,直接拿来对话会很奇怪。
思维链:让模型「想清楚再说」
LLM 有一个有趣的特性:如果你让它直接给出答案,它可能会犯错;但如果让它先把推理过程写出来,再给答案,准确率会高很多。
这就是所谓的思维链(Chain of Thought,CoT)。
比如你问一道数学题:我有 3 个苹果,又买了 5 个,吃了 2 个,还剩几个?
模型如果直接蹦出一个数字,可能会出错。但如果它先写「3 + 5 = 8,8 - 2 = 6」,再回答「6 个」,就准确多了。
这其实和我们人类做题一样,做一道复杂的数学题,直接根据题意猜答案和在草稿纸上一步一步推演,正确率完全不同。
模型把思考过程「写出来」,等价于给自己打草稿,每一步的中间结果都成了后续推理的输入,自然就更靠谱。
后来的推理模型(比如 OpenAI 的 o1/o3 系列、DeepSeek R1、Claude 的 extended thinking)把这个思路进一步系统化了:模型不光会写推理过程,还会自我反思:先给出一个答案,再回头检查有没有问题,发现不对就修正。
这个就和我们做判断的逻辑是类似的,很多时候直觉不准确,需要仔细思考一下才能得出正确的结论。
所以你在用 ChatGPT 等 AI 助手时,有时候会看到模型在「思考」很久才回复。它就是在做这种多步推理和自我验证,本质上是用更多的计算量来换取更高的准确率。
早期的推理模型是以「独立模型」的形态出现的,各家厂商往往同时发布两个版本,一个是普通对话模型(如 gpt-4o、DeepSeek V3),一个是推理模型(如 gpt-o1、DeepSeek R1)。
开发者要根据任务类型选模型:简单问题用对话模型省钱,复杂问题用推理模型求解。
但这种二分法用起来很别扭,一个 Agent 任务里可能既有简单的文件读写,也有复杂的代码调试推理,你总不能中途换模型吧?
所以从 2025 年下半年开始,行业逐渐统一到了单一模型 + 思考强度参数的新范式。同一个模型既能快速回答,也能深度思考,开发者通过一个参数控制它「想多久」。
各家的参数名略有不同(reasoning_effort、effort、thinkingLevel 等等),但思路一致:都是通过一个参数控制模型的思考强度。
强度调高,模型多花点时间反复推演;强度调低,直接给答案省 token。
这个变化对 AI 应用的开发也比较友好,以前在代码里要维护两套模型的调用逻辑(对话模型 vs 推理模型),现在一套代码就够了,复杂度低了很多。
System Prompt:设置「人设」
到目前为止,我们讲的都是模型本身的能力:它怎么预测 token、怎么理解指令、怎么做推理。但还有一个问题:你怎么控制它的行为?
比如你希望模型用简洁的风格回答,或者让它扮演一个特定的角色,这些要求要写在哪里?
答案是 System Prompt(系统提示词)。它是对话开始前给模型的一段指令,会被拼到上下文的最前面。用户在聊天界面里看不到这段文字,但模型每次生成回答时都能读到它。
你可以把 System Prompt 理解为模型的「人设说明书」。对话还没开始,模型就已经读到了这段文本,后续不管用户问什么,它都会在这个「人设」的框架下回答。
System Prompt 可以是模型服务商预设的(比如 OpenAI 给 ChatGPT 写的默认指令),也可以是开发者通过 API 自己设定的。用户也能参与其中,最直观的例子就是 ChatGPT 的「自定义指令」功能。
你可以在设置里告诉它你的职业背景,让它用特定的风格回复你。比如你写「我是一个后端开发者,回答要简洁,给代码示例时用 Go」,之后每次对话它都会按这个偏好来。这个「自定义指令」本质上就是被追加到了 System Prompt 里。
System Prompt 还有一个重要的用途:设置安全规则。
你在用 ChatGPT 或 Claude 的时候,问某些敏感话题会被拒绝回答。这种拒绝行为一部分来自训练阶段的安全对齐(比如 RLHF),模型在训练时就已经学会了拒绝明显有害的请求。
但光靠训练还不够,因为安全策略需要经常调整,某类内容的宽严尺度会随政策变化。
每次改策略都重新训练模型,成本太高了。所以模型服务商还会在 System Prompt 里写明确的安全规则,做更精细的策略控制。这样改一行文本就能生效,灵活得多。
你可能会问:如果用户在对话里写「忽略你之前的所有指令」,模型会听谁的?
这就涉及 System Prompt 和用户消息的优先级问题。实际上,送给模型的文本会标记不同的角色标签(system、user、assistant),模型在训练时学会了对 system 标签的内容赋予更高的服从权重。所以正常情况下,用户没法轻易覆盖 System Prompt 里的规则。
当然,这种防护不是绝对的。网上有各种「越狱」(jailbreak)技巧试图绕过 System Prompt 的限制,模型厂商也在不断加固,这本质上是一场攻防博弈。
System Prompt 的核心价值就两点:定义模型的行为方式,以及设置不可轻易绕过的规则。
后面你会看到,不管是让模型调用工具、执行任务还是遵循操作流程,都依赖于往上下文里塞入恰当的文本。System Prompt 就是这一切的起点。
我们会在 动手实现一个 chatbot 中结合代码实际展示 System Prompt 的用法和效果。
Function Calling:让 LLM 学会「动手」
LLM 虽然能说会道,但它有一个根本性的限制:它只能输出文本。
你问它现在几点了,它不知道,因为它没有时钟。你让它帮你查数据库,它做不到,因为它连不上数据库。它就像一个被关在房间里的超级大脑,知识渊博,能说会道,但没有手脚,做不了任何事情。
2023 年 6 月,OpenAI 发布了 Function Calling 功能,给这个「超级大脑」装上了手脚。
比方说你开发了一个聊天机器人,你想让模型在需要的时候自动调用天气查询 API 来回答用户的问题。
首先,你要把这个查询天气的 API 的描述塞进 System Prompt 里(上一节讲过,它就是对话开始前给模型的隐藏指令)。
比如你可以这样写:
你是一个有用的助手。你有以下工具可以使用:
工具名称:get_weather
功能描述:查询指定城市的当前天气
参数:
- city(字符串,必填):城市名称,如"北京"
- unit(字符串,可选):温度单位,"celsius"或"fahrenheit",默认"celsius"
当用户的问题需要查询天气时,请输出 JSON 格式的工具调用。然后用户问了一个问题:「北京今天冷不冷?要不要穿外套?」
模型读到这个问题,发现上下文里有一个查天气的工具可以用。它自己并不知道北京今天多少度,但它知道可以调用工具来获取。于是模型不直接回答,而是输出:
{
"tool": "get_weather",
"arguments": { "city": "北京" }
}意思是:「我需要调用工具 get_weather,参数是 city: 北京」。
注意,模型本身并没有调用任何 API,它只是输出了这么一段 JSON 文本,表达一个「调用意图」。
你的程序看到这段 JSON 后,不要直接返回给用户,而是去调用天气查询 API,再把结果塞回模型的上下文:
工具 get_weather 的返回结果:
{"city": "北京", "temperature": 8, "unit": "celsius", "condition": "多云"}模型看到这个结果后,就能给用户一个有用的回答了:「北京今天 8°C,多云,还是挺凉的,建议穿个外套」。
你的程序将这个回复返回给用户,用户就能看到一个准确的天气回答了。我们会在 实现一个 chatbot 用代码实现这个过程。
整个过程中,模型的上下文里依次出现了这些内容:工具描述 → 用户提问 → 模型输出工具调用 → 工具返回结果 → 模型最终回答。
全部都是文本,全部在上下文窗口里,没有任何魔法。模型之所以知道该调用 get_weather,纯粹是因为它在上下文里读到了这个工具的描述。
这里面考验的是模型的指令遵从能力。你让它输出 JSON,它能不能老老实实只输出合法的 JSON,不夹带其他乱七八糟的文字?你告诉他函数的参数和类型,它是否输出正确的函数参数?
如果你尝试过 GPT-3.5 这种早期模型,会发现它们的指令遵从能力很差,输出 JSON 的同时还可能带一句「好的,下面是结果」之类的废话,这就会导致程序解析 json 失败。
到 2023 年底,OpenAI 把 functions 参数改名为 tools,Anthropic、Google 也跟进推出了自己的 Tool Use 方案。名字虽然变了,本质没变:模型输出结构化的工具调用请求,外围程序解析结构化的数据,执行后把结果喂回上下文。
随着模型的指令遵从能力越来越强,Tool Use 从勉强能用变成了非常可靠,这也为后面 Agent 的出现奠定了基础。
MCP:给工具定个标准
Function Calling / Tool Use 的原理搞清楚了,但还有一个实际问题。
前面说了,工具的描述需要塞进模型的上下文,而这件事是需要配合模型服务提供方的。你要按照它要求的格式来定义工具,它才能正确地把工具信息传给 LLM。
问题是,各家的格式不太一样,同样是定义我们前面那个查天气的工具,在 OpenAI 和 Anthropic 的 API 里,写法是不同的:
// OpenAI 的格式:嵌套在 function 里,参数字段叫 parameters
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市的当前天气",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "城市名称" }
},
"required": ["city"]
}
}
}
// Anthropic 的格式:扁平结构,参数字段叫 input_schema
{
"name": "get_weather",
"description": "查询指定城市的当前天气",
"input_schema": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "城市名称" }
},
"required": ["city"]
}
}描述的是同一个工具,但字段名和嵌套层级都不一样。你为 OpenAI 写好的工具定义,拿到 Anthropic 上就得改一遍格式,Google Gemini 又是另一套写法。
而且,在工作中大部分情况不会直接使用模型厂商的 API,而是使用 Claude Code、Cursor、Codex 这类 Agent 工具,那么如果我想给这些工具添加一些定制化的工具,岂不是还要适配每家模型厂商的 API?
这就和当年手机充电线的混乱局面一模一样,每家手机厂商都有一套自己的充电协议,自家手机只能用自家的充电线,从用户的角度来看就非常不方便。
2024 年 11 月,Anthropic 推出了 MCP(Model Context Protocol,模型上下文协议)。你可以把它理解为 AI 工具领域的「USB-C 标准」:按照 MCP 的规范写一个工具,所有支持 MCP 的 AI 工具都能直接接入,不用关心底层是哪家的模型。
用 MCP 写一个查天气的工具,用 Python 的 fastmcp 库十几行代码就搞定了:
from mcp.server.fastmcp import FastMCP
# 创建一个 MCP Server
mcp = FastMCP("weather-server")
# 用装饰器定义一个工具,函数签名就是工具的参数定义
@mcp.tool()
def get_weather(city: str) -> str:
"""查询指定城市的当前天气"""
# 这里调用真正的天气 API
return f"{city}:8°C,多云"
# 启动服务
mcp.run()就这么点代码,FastMCP 会自动根据函数签名和文档字符串生成标准的工具描述。
写完之后,Claude Code、Cursor 这些支持 MCP 的 AI 工具,只需要在配置文件里注册这个 Server,就能直接使用 get_weather 了,开发者不用操心每家平台的 API 差异。
目前 MCP 已经成了行业事实标准,但要注意 MCP 并没有引入什么新的 AI 能力,它只是把「怎么描述工具」「怎么调用工具」这些接口给标准化了,底层还是 Tool Use 那一套:把工具描述塞进上下文,模型决定是否需要调用,外围程序实际执行工具并把结果喂回上下文。
我们会在 动手开发 MCP 工具 中详细介绍 MCP 的用法和协议细节。
Agent:给 LLM 套上循环
有了 Tool Use,LLM 就能做事了。但如果只是「用户问一句 → 模型调一次工具 → 返回结果」这种一问一答的模式,能做的事情还是非常有限。
真实世界的任务往往需要多个步骤:先读一下文件看看代码结构,再定位到有 bug 的函数,然后修改代码,最后跑一下测试确认修复了。这不是一次工具调用能搞定的。
Agent 的核心思路很简单:把 LLM + Tool Use 放进一个循环里。
用伪代码表示:
while 任务未完成:
模型根据当前上下文思考下一步该做什么
if 模型认为需要使用某个工具:
执行工具,把结果追加到上下文
elif 模型认为任务完成了:
输出最终结果,退出循环就这么简单。Claude Code、Cursor、Codex 这些编程 Agent,本质上都是这个循环,配上一堆编程相关的工具:读文件、写文件、执行命令、搜索代码、运行测试。
下面用一个修 bug 的例子来可视化这个过程。点击「下一步」或「自动播放」,观察每一轮循环如何往上下文里追加内容:
模型在循环中不断地「思考 → 行动 → 观察结果 → 再思考」,这个模式在学术上叫 ReAct(Reasoning + Acting)。
它和人类解决问题的方式其实很像:你不会一上来就知道怎么做,而是先看看情况,试一下,看看结果,再决定下一步。
注意这个循环有一个副作用:每一轮的工具调用和返回结果都会追加到上下文里,所以上下文在不断增长。
所以上下文窗口的大小很重要,窗口太小的话 Agent 跑几轮就把上下文撑满了,前面的信息被截断,模型就「失忆」了。现在主流模型的上下文窗口几乎都到了 1M token,就是为了让 Agent 能跑更久。
同时,工具调用的准确性也是很重要的,你看目前新模型发布的时候都有工具调用相关的评估指标。如果工具调用的能力差,就可能把大量和目标无关的工具调用结果追加到上下文里,导致上下文被撑爆。
所以 Agent 并不神秘。它的「智能」来自两部分:模型本身的推理能力决定了它能不能想出正确的下一步,工具赋予了它把想法变成行动的能力。
LLM 是大脑,工具是手脚,循环是驱动力,结合起来就是 Agent。我们会在 动手实现一个 Coding Agent 中详细介绍 Agent 的代码实现。
Skills:可复用的工作流程
有了 LLM 和工具,Agent 知道自己「能做什么」。但在面对一个复杂任务时,它还需要知道「该怎么做」,也就是工作流程。
这就是 Skills 要解决的问题。
你可能会问:Agent 循环不是能自主解决问题吗,为什么还需要人来告诉它怎么做?
模型当然能自己摸索,但对于复杂任务,自由发挥的效果不如按预设流程来得稳。
这就像公司招了一个聪明的新员工,他什么都能想办法搞定,但公司已经有了一套成熟规范的工作流程,如果让他按照这套流程来办事,他能做得更快更稳。
Skills 就是把一套完整的操作流程写成文档,Agent 按文档一步一步执行。
或者说的更直白一些,Skills 就是把你常用的操作流程沉淀成文档,直接甩给 Agent,他就能部就班执行。就像你把重复的代码逻辑抽象成一个公共函数一样。
拿 Anthropic 官方开源的 PDF Skill 举个例子。它的文件结构是这样的:
skills/pdf/
├── SKILL.md # 核心文件:何时触发 + 操作指南
├── reference.md # 详细参考文档
├── forms.md # 表单填写专项指南
└── scripts/ # 预写好的 Python 脚本其中 SKILL.md 是核心,开头的 YAML 部分告诉 Agent「什么时候该用这个 Skill」:
---
name: pdf
description: Use this skill whenever the user wants to do
anything with PDF files. This includes reading or extracting
text/tables from PDFs, combining or merging multiple PDFs,
splitting PDFs apart, rotating pages, adding watermarks,
creating new PDFs, filling PDF forms...
---后面的 Markdown 正文就是具体的操作指南:每个脚本的用法、怎么读取 PDF、怎么合并、怎么提取表格,甚至连代码示例都写好了。而 scripts/ 目录里则放了一批预写好的 Python 脚本:
scripts/
├── extract_form_field_info.py # 提取表单字段信息
├── fill_fillable_fields.py # 填写表单字段
├── convert_pdf_to_images.py # PDF 转图片
|...Agent 读到 SKILL.md 之后就知道:要提取表单信息,跑 extract_form_field_info.py;填完之后想确认效果,跑 convert_pdf_to_images.py 转成图片看一眼。
它不需要自己去写这些脚本,也不需要把脚本代码加载到上下文里去「理解」。它只需要知道每个脚本的用途,然后直接执行就行了。
这样做的好处很明显:Agent 只需要读一份文档(占用少量上下文),就能借助预写好的工具完成复杂任务。
而且这些脚本是我们事先调试验证过的,比让 Agent 临时写一个可靠得多。
你看,这就是一个完整的工作流程文档:什么时候触发、具体怎么做、用什么工具,全部文档化了。Agent 不需要「聪明地发明」解决方案,只需要「认真地执行」文档里的流程。
Anthropic 在 Skills 的加载上有一个巧妙的设计叫渐进式披露(Progressive Disclosure)。上面那个 PDF Skill 的完整内容可能有十几万个 token,如果把所有 Skills 的完整内容一股脑塞进上下文很浪费 token。
所以实际做法是:启动时只告诉模型每个 Skill 的名字和一句话简介,几十个 Skill 加起来也占用不了多少上下文。等模型发现当前任务和某个 Skill 相关了,再加载更多的内容。
这就是一个典型的工程优化:核心原理没变(都是往上下文里塞文本),但通过按需加载,大幅降低了 token 消耗。我们会在 用 Skills 定制你的 AI 工作流 更详细介绍 Skills 的用法。
RAG:让 Agent 用上外部知识
到目前为止 Agent 有了 LLM、工具、循环、Skills,看起来什么都能做。但还差一样东西,就是你私有的知识。
模型只见过训练数据里的内容,如果你问它「我们公司的 XXX 产品怎么收费」,它一无所知,只能瞎编。
最朴素的想法是把整份文档塞进上下文,但企业知识库动辄上千页,再大的窗口也装不下,token 费用也吃不消。
用关键词搜索行不行?效果不好,因为自然语言中有大量同义词。比如用户问「忘记密码怎么办」,文档里写的是「账号找回流程」,意思相同但一个字都不重合,精确的文本匹配算法找不到。
要解决这个问题就得用 RAG(Retrieval-Augmented Generation,检索增强生成)。
核心是借助 Embedding 模型,这种模型能够把文本转化成一个语义向量(一组浮点数),而且神奇的地方在于,语义相近的文本计算出的向量之间的距离也很近。
那么对于大量的文档,我们可以事先将他们都编码成语义向量存储到数据库,然后用户提问时把问题也编码成向量,用问题向量去数据库搜索,距离最近的向量就是问题相关的文档片段。
你把这些文档片段塞进 Agent 的上下文,Agent 就能基于这些资料准确回答用户问题了。
我们会在 动手实现一个 RAG 问答 bot 里走一遍;在 RAG 原理与适用边界 里讲解 embedding 模型怎么训练出来的、什么场景下适合用 RAG。
自动记忆:跨会话的信息延续
前面讲过,一个会话最好只聚焦一个问题,遇到新问题就开新会话。新会话是一个全新的上下文窗口,既省 token,效果也更好。
但这样有个明显的代价:原会话里积累的上下文,开新会话就全部丢掉了。
大部分内容丢掉没关系,毕竟新会话和旧问题无关。但有些信息是跨会话有价值的,比如你的个人偏好、当前项目的开发规范,你不希望每开一个新会话都重新讲一遍。
这类跨会话有价值的信息大致分两类。
用户维度:使用 Agent 的人有什么偏好?比如希望代码注释写得详细一些,注释统一用中文;比如常用 Python + React 的技术栈;比如不喜欢过度抽象的代码。这些是关于「你」这个人的偏好,理想情况下不用每次都重新沟通。
项目维度:你当前开发的这个项目,本地环境怎么跑起来?怎么部署到测试环境?日志在哪里看?数据库连接怎么配?这些是关于「这个项目」的知识,理想情况下你只需要在项目里第一次跟 Agent 说一遍,之后新会话他默认就记住了,不用每次重新教。
最朴素的解决方案是你自己维护一份文档,把这些信息写进去,每次新开会话时先把文档甩进去。这相当于给 Agent 准备了一份「入职手册」,让他先读一遍再开工。
这种做法可行,但自己手动整理很麻烦啊。一般来说 Agent 重复掉进一个坑里,我不会想着去给他整理一份文档,而是直接开骂了。
所以现代的 Agent 工具一般会自动做这件事,这就是所谓的 Auto Memory。
原理跟手动维护文档差不多,只是过程自动化了:每次对话之后,Agent 会自己识别哪些信息是跨会话有价值的(比如你透露的个人偏好、项目的开发规范、踩过的坑),把它们整理到一个记忆文件里。下次新会话启动时,再把相关的记忆自动注入到上下文开头。
整个过程用户不用做什么,Claude Code、Codex 这些工具会在后台默默完成。从用户的角度看,就会觉得 Agent 越用越聪明,之前踩过的坑下次不会再踩,跟你合作的方式也越来越贴合你的工作风格。
各家工具对 Auto Memory 的实现方式不太一样,但本质都是同一件事:把跨会话有价值的文本沉淀下来,新会话启动时自动加载到上下文里。
我们会在 Claude Code 的 Auto Memory 实现 和 Codex 的 Auto Memory 实现 别拆解两个主流工具的具体做法。
Harness:让 agent 更可靠
讲到这里,Agent 已经什么都能做了,但还有一个绕不开的问题:LLM 本质是概率模型,再聪明的模型也有概率出错。
比如说,它可能在改代码时漏看了关键文件,给你引入新的 bug;它也可能根本没读文件,仅凭文件名就臆测内容,然后一顿乱改。
尤其是现在 Agent 都在拼长程任务能力(让 agent 一口气工作几个小时独立完成复杂任务),那么里这个问题尤其突出。
因为工作期间必然会经历多次上下文压缩,而每次压缩都伴随信息损失。早期定下来的约束、踩过的坑、改了一半的代码,都可能在某次压缩之后悄悄消失,模型就可能一错再错。
所以如何在信息必然损失的前提下依然让长程任务稳定推进,就非常考验 Agent 系统的可靠性了。
要让 agent 在真实工程里跑得住,靠的不是更聪明的模型,而是围绕模型搭一套兜底的工程机制。这套思路被称为 Harness Engineering。
社区里流行一句话:Agent = Model + Harness。Harness 原意是马具,模型像精力旺盛但容易跑偏的马,harness 是把它的能量约束在正确方向上的缰绳和马鞍。所以它不是某一项具体技术,而是一种贯穿 agent 方方面面的工程思想。
Harness 工程大致可以分为两类:
一种是事前约束。比如 Claude Code 给模型提供的 Edit/Write 工具,就在代码层面限制「没读过这个文件就不允许修改它」,如果模型尝试直接改文件就会报错。
一种是事后反馈。比如 agent 写完代码自动跑一遍测试,跑挂了就把错误信息甩回上下文,让他自己看自己修。这是 Hooks 机制 可以做的事情,在 agent 想停下来的时候触发你预设的脚本,强制跑验证。
这两类做法背后的共同原则是:能用确定性程序检测的事情,就不要依赖模型自己判断。因为模型的判断是概率性的,确定性的检查才是工程上的可靠保障。本站会有专门的文章拆解 Harness Engineering 的具体落地方式。
OpenClaw:全新的 Agent 交互体验
讲到这里 Agent 的核心能力链路就完整了。但还有一个知名的项目值得提一下,那就是 OpenClaw(小龙虾)。
OpenClaw 底层是一个 Agent 引擎,基于开源的 Pi Mono Agent 框架。从架构上看,它和 Claude Code、Codex 属于同一类东西,都是 LLM + 工具 + 循环。
要论编程能力,OpenClaw 肯定比不上 Claude Code、Codex。因为后两个是模型厂商针对编程场景反复打磨过的生产级 Coding Agent,从 prompt 到工具到上下文管理都做了大量优化,OpenClaw 这种轻量级开源 Agent 完全比不上。
那它为什么能火?我觉得创新点不在 Agent 本身,而在人和 Agent 的交互方式。
正常用 Claude Code 或 Codex,你得坐在电脑前敲键盘发号施令。这个工作模式很适合开发者,但门槛挺高,而且离开了电脑就用不了。
OpenClaw 做的事情是把 Agent 接到了主流的 IM 工具上,飞书、Telegram、WhatsApp、Slack 等几十个聊天平台都能直接对接。你不用打开终端,也不用守在电脑前,在任何聊天工具里发条消息就能让 Agent 干活。
这就像你雇了一个 24 小时待命的远程实习生。他不一定是顶尖高手,但你随时可以在手机上甩任务给他,他会自己跑去执行。
而且这个实习生自己能力不够强也没关系。OpenClaw 可以通过 ACP(Agent Client Protocol)协议或 CLI 工具,直接启动 Claude Code、Codex 这些专业编程 Agent 来干活,它自己只负责和你交互,做个传声筒。
所以 OpenClaw 的真正价值不是「又一个 Agent」,而是给 Agent 换了一套交互界面。它让普通人也能远程指挥数字员工,把 Agent 从开发者的专属工具变成了人人都能用上的远程助手。
在我看来这代表了 Agent 走向大众的一种形式:底层用 Claude Code、Codex 这种专业 Agent 干活,上层用 OpenClaw 这种轻量级 Agent 接到 IM 工具,隐藏底层的细节,只给用户暴露简单的聊天页面。
一切都是上下文
回头看我们讲的所有内容,你会发现一个贯穿始终的事实:不管是思维链、Tool Use、Agent 循环、MCP 工具描述、Skills 文档、RAG 还是记忆系统,最终都要塞进上下文窗口里,交给同一个概率模型去一个字一个字地往外蹦。
思维链是什么?是模型在上下文里写给自己看的草稿。
MCP 和 Tool Use 是什么?是在上下文里塞了工具描述,模型读到后输出调用请求,结果再追加回上下文。
Agent 循环是什么?是不断地往上下文里追加思考和工具结果。
Skills 是什么?是把操作手册的文本加载到上下文里。
RAG 是什么?是从外部知识库里检索相关文本片段,加载到上下文里。
记忆系统是什么?是把跨会话有价值的信息沉淀下来,新会话启动时自动加载到上下文里。
没有任何魔法,全部都是文本,全部都靠那个「预测下一个 token」的概率模型在驱动。
在 Claude Code 里运行 /context 命令,你能直接看到当前上下文里塞了哪些东西,每一类各占多少 token:

图里 System Prompt 是系统提示词,System tools、MCP tools、Custom agents 是可用工具的描述,Memory files 是记忆系统沉淀下来的跨会话记忆,Skills 是可用的技能文档,这些都被自动注入到了上下文开头。
Messages 部分就是你和 Agent 对话累积的内容,Free space 是还没用掉的上下文余量。每一项对应的概念前文都讲过,本质上都是塞进上下文窗口里的文本。
这就是为什么渐进式披露这些工程优化手段如此重要,因为模型本身的能力是固定的,上下文里塞什么、怎么塞、塞多少,直接决定了 Agent 的表现。
同样一个模型,给它一份写得好的 Skill 文档和一批预置脚本,它能高效完成复杂任务。给它一个塞满了无关信息的上下文,它可能连简单的问题都答不好。
所以整条演进路线的本质是:LLM 是基座,Agent 是围绕 LLM 的一套工程体系。
从 Function Calling 到 MCP 到 Skills 到渐进式披露,都是在解决同一个问题:如何在有限的上下文窗口里高效地组织信息,让概率模型发挥出最大的能力。
理解了这一点,你会发现 AI 时代的机会并不只属于搞大模型训练的人。模型能力的提升当然重要,但围绕模型的工程优化同样大有可为。
怎么设计工具让 Agent 用起来更顺畅?怎么写 Skill 文档让流程更可靠?怎么管理上下文让 token 花在刀刃上?这些都是实实在在的工程问题,也是你理解了这些原理之后可以着手的方向。
说到底,你不需要懂模型是怎么训练的,但你知道「一切都是上下文」,就能更聪明地使用这些 Agent 工具更好地完成任务。
而且,随着模型本身的能力的提升,你围绕模型构建的工程优化的价值也会水涨船高,这正是 AI 时代的机会所在。
回到开头的问题
你现在应该明白 Claude Code、Cursor 等工具是什么了吧?它们是 Agent 工程层面的工具。
即便底层都使用相同的 Claude 模型,它们的编程效果也会有差别,就是因为 Agent 的工程实现不一样。
就我的体验来说,同样都是用 Claude 模型,Claude Code 用起来最舒服,给人感觉最聪明;同样都用 GPT 模型,Codex 用起来最舒服,Cursor 等其他工具都略逊一筹。
我认为这里面主要有两个原因:
一是因为 Agent 工程做得好。Codex/Claude Code 是 OpenAI/Anthropic 原厂研发的,用户基数大,各方面打磨更到位。
二是因为成本制约少。OpenAI/Anthropic 自己就掌握 LLM 模型,就舍得给 Codex/Claude Code 塞上下文,让模型获取充分的信息后再开始执行任务。
Cursor 等其他工具,依靠模型厂商的 API 调用,肯定有成本的限制在里面,所以它们开发的 Agent 就倾向于塞更少的上下文,尽快给出答案。但这样做的代价就是,有些复杂问题可能得不到足够的信息,模型再强也没用,执行任务时还是可能欠考虑。
反过来,同一个 Agent 实现,使用不同的模型,效果也会有差别,这就是模型智力的差距,Agent 工程层面无法弥补的。你给 Claude Code 接入能力差的模型,那效果肯定不会好。