0%

Most best practices are based on one constraint: Claude’s context window fills up fast, and performance degrades as it fills.

如果你用 Claude Code 做过真实项目,大概率经历过这种事:

  • 前几次对话很聪明,调试几轮后开始犯蠢
  • 刚确认过的约束突然失效
  • 你开始反复解释纠正,但效果越来越差

问题不全在模型,真正出问题的是一个容易被忽视但很重要的:上下文(Context Window)

Claude Code 官方文档反复强调 context window,但很多人仍然把它当成“聊天长度限制”

实际上,它更像是一种会被污染、会老化、需要管理的工程资源。

重新理解 Context Window

Context Window 不只是聊天记录,在 Claude Code 中,Context Window 包含:

  • 整个对话历史
  • Claude 读过的所有文件
  • 每条命令的执行结果
  • 所有失败尝试、中间结论和被推翻的假设

这些内容不只是被动记忆,而是会作为持续参与后续推理使用的输入材料

它更像是一个「推理现场」,不是日志

为什么上下文会失控

如果你不做任何管理,上下文几乎一定会走向失控:

  • 调试是一个高噪声活动
  • 探索与实现混在同一个会话里
  • 错误假设不会自动失效
  • 一个会话承载了太多目标

官方建议背后的逻辑

subagents、@file、/clear、/compact、Explore → Plan → Implement……

这些看似零散的建议,其实都在解决同一个问题:如何让有限的上下文,长期保持可用

换句话说,Claude Code 的所有最佳实践,本质上都是在回答一个问题:如何延缓上下文退化的速度

上下文管理的四条原则

短 · 净 · 可控 · 可重置

  • :探索性工作不进入主上下文
  • :错误必须尽快失效
  • 可控:计划必须先于实现
  • 可重置:上下文重置是工程能力的一部分

这四条不是技巧清单,而是判断标准

短:探索性工作不进入主上下文

一句话理解:别把「还没想清楚的东西」长期留在主上下文里

探索性工作一旦进入主上下文,推理质量就会开始退化

主上下文应该只承载稳定的、可复用的决策信息

而以下内容,天然是高噪声的:

  • 文件扫描
  • 代码结构探索
  • 试探性 Debug
  • 不确定假设的验证过程

它们有价值,但不适合长期驻留

SubAgents 的真正价值

SubAgent 常被当作「并行能力」来使用,它的真正更重要的价值是上下文隔离:

  • 主 Agent:控制面 / 决策面
  • Subagent:一次性计算单元

探索发生在子上下文中,主上下文只接收结论

用「引用」代替「注入」

粘贴大段代码或命令输出,是最常见的上下文杀手

更好的方式是:

  • @file 引用文件
  • 使用工具调用,而不是贴原始输出
  • 让上下文知道「在哪里」,而不是「全部内容是什么」

净:错误必须尽快失效

一句话理解:错误一旦确认,就别再让它参与后续推理

错误假设在上下文中停留越久,修复成本越高

一个典型的错误路径:

  1. 错误假设进入上下文
  2. 实现基于错误前提展开
  3. 出现异常 → 局部修补
  4. 错误被反复引用和强化

最后你得到的不是「修复后的上下文」,而是一个被污染的上下文

为什么「在原地纠错」代价极高

在同一个会话里反复纠错,看似节省成本,实则相反:

  • 错误不会被删除
  • 纠错只是叠加更多 token
  • 模型更容易「合理地犯同一个错」

同类错误出现两次以上,继续修补往往不划算

什么时候应该 clear 或重来

判断信号:

  • Claude 开始忽略已确认的约束
  • 输出质量明显下降
  • 你需要反复强调同一前提

这通常不是你没讲清楚,而是:上下文已经不值得继续修补

可控:计划必须先于实现

一句话理解:先想清楚再让模型写,不要让上下文替你思考

没有显式计划的上下文,一定会失控

当你边想边写、边改边试时:

  • 推理是隐式的
  • 路径不断分叉
  • 上下文不可逆的增长

最终你甚至无法判断:是方向错了,还是实现错了

Explore → Plan → Implement 的核心价值

这个流程的核心价值不是「规范」,而是压缩上下文:

  • Explore:允许噪声和不确定
  • Plan:把推理压缩成稳定结构
  • Implement:在稳定约束下执行

好计划,本身就是上下文锚点

一个好的计划可以把上万 token 的探索,压缩成几百 token 的稳定约束

计划不是文档,而是上下文压缩器

可重置:上下文重置是工程能力的一部分

一句话理解:如果一个会话不能被丢弃,那它已经绑架你了

如果一个上下文不能被安全、低成本地重启,那它本身就是设计有问题的

为什么不敢重置反而是风险?

在真实使用中,很多人会下意识地「死扛」一个会话:

  • 已经投入了大量对话和探索
  • 担心重来会丢失进展
  • 希望再解释一次就能「救回来」

但在 LLM 系统中,这种行为往往会带来更大的风险:

  • 错误假设持续留在上下文中
  • 冗余推理不断堆积
  • 模型开始「看起来合理,但总是偏一点」

此时继续追加上下文,并不是在积累资产,而是在放大负债。

/compact、/clear 与直接重来

  • /compact:方向对,但上下文过长
  • /clear:方向错或噪声过多
  • 直接重来:往往是成本最低的方案

丢掉的是噪声,而不是成果

设计「可重启」的工作方式

成熟的使用方式,通常具备:

  • 可复制的输入
  • 外置的规则(CLAUDE.md / skills)
  • 不依赖单一会话状态

反模式清单

  • 把探索过程塞进主上下文(违背「短」)
  • 在错误假设上不断打补丁(违背「净」)
  • 边想边写、边改边试(违背「可控」)
  • 死扛一个已经失控的会话(违背「可重置」)

如果你发现自己四条全中,那不是你不专业,而是你还在用「人类调试人类代码」的方式调试 AI

上下文自检

继续一个会话前,快速自检:

  • 主上下文是否只包含决策信息?
  • 是否存在已被推翻但仍在上下文中的假设?
  • 是否有明确、稳定的计划锚点?
  • 如果现在重启,成本是否可接受?

结语

模型会继续变强,但上下文不会自动变干净

在 Agent 工程里,真正拉开差距的,从来不是谁的模型更新得更快,而是谁更早意识到:上下文是一等工程资源

参考文档:https://code.claude.com/docs/en/best-practices

如果你已经用过 Agent,可能会有一种很真实的感觉:

好像是会用了,但真让我讲清楚 Agent 是怎么跑起来的,又有点说不明白。

比如:

  • Agent 为什么能一边“想”,一边“用工具”?
  • Function Call 到底是谁在调用?模型?还是我们?
  • LangChain / LangGraph 里那些节点、Memory,看起来很高级,本质在干嘛?

很多时候,我们是跟着框架把 Agent 跑通了
可一旦遇到下面这些情况,就会开始有点卡:

  • 想自己手写一个简单 Agent
  • 想排查 Agent 为什么卡住、不动了
  • 或者想做点框架里没有的定制逻辑

这时候你大概率会觉得:Agent 有点像黑盒。

但其实,Agent 真没那么复杂。

如果你愿意把框架先放一边,只看最底层的 API,就会发现:
Agent 本质上,就是几个很普通的东西,被我们拼在了一起。

这篇文章想做的事情也很简单:

不用任何 Agent 框架,只用基础API + Java,一步一步把 Agent 是怎么工作的“摊开来看”。

不追求花哨,只追求你看完之后能说一句:“哦,原来 Agent 是这么回事。”

那我们直接开始。

阅读全文 »

过去两年,大模型能力的提升有目共睹。
对话越来越自然,推理能力不断增强,看起来几乎“无所不能”。

但在真实的工程实践中,很多人都有类似的感受:
Demo 很惊艳,真正落地却并不轻松。

问题往往不在模型能力本身,而在于:
我们仍然在用早期的工程抽象,承载已经高度复杂的 AI 能力。

本文尝试从工程视角,回顾 AI 应用从「对话」到「Skills」的演进路径。

阅读全文 »

曾经编写的费用分摊的小程序,如今已焕新升级。我为其接入了AI能力,打造出一个能理解指令、预测操作的智能助手。程序的核心代码由Claude Code协助编写。

现在,通过简单的自然语言就能与它对话。更棒的是,它能预判我的下一步操作,并提前给出提示。预测准确时,只需一键确认即可,让操作效率倍增。

体验地址:https://zhengw-tech.com/expense/ai-chat.html,可以先自行操作体验下

如果大家还有兴趣,下面开始详细介绍功能使用指南~

阅读全文 »

注:AI 生成,略有调整

在日常开发中,我们经常需要同时处理多个分支:

  • 一个主分支(maindevelop
  • 若干个功能开发分支(feature/*
  • 偶尔的紧急修复分支(hotfix/*

大多数人为了同时开发或调试多个分支,会这样做: 再 clone 一份仓库,然后在另一个目录里切换到不同分支

但这样带来很多问题:

  • 占用磁盘空间(一个项目可能几百 MB,clone 多份会爆仓)
  • 管理混乱(分支、依赖、配置容易搞混)
  • Git 操作分散(每个仓库要分别 fetch/pull)

其实,Git 内置了一个优雅的解决方案 —— git worktree

阅读全文 »

之前进行过机器学习的数学笔记-回归中,主要是人工计算导数以及更新计算

本次为对应《动手学深度学习》线性回归部分内容,使用PyTorch 来简化实现

构造测试数据

找到合适的数据比较麻烦,我们可以自己生成对应的测试用的数据,添加一定的噪声

线性模型:$\mathbf{y}=\mathbf{W}\mathbf{X}+b$,其中 $\mathbf{W}$ 和 $\mathbf{X}$ 都是矩阵

比如可以是$y=w_1x_1 + b$ 也可以是 $y=w_1x_1+w_2x_2+b$ 等等

我们可以根据输入的 $\mathbf{W}$ 和 $b$ ,根据$\mathbf{W}$的形状生成对应高斯分布的$\mathbf{X}$,执行 $\mathbf{y}=\mathbf{W}\mathbf{X}+b$ 获取对应的 $y$ 值

阅读全文 »

本文主要介绍一下通过Spring AI 来快速实现一个简单的类似OpenAI Agents SDK的功能

具体效果为在application.yml 中配置对应的agent 信息,如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
spring:
ai:
agents:
# 定义一个Agent
- name: historyTutor
# 与大模型交互时的Agent的系统提示词
instructions: You provide assistance with historical queries. Explain important events and context clearly.
# 其他Agent可以获取到的关于当前agent的描述信息
handoffDescription: Specialist agent for historical questions

# 定义另一个Agent
- name: mathTutor
instructions: You provide help with math problems. Explain your reasoning at each step and include examples
handoffDescription: Specialist agent for math questions

# 定义入口agent
- name: triageAgent
instructions: You determine which agent/tools to use based on the user's homework question
# 这里定义可以分派的其他agent有哪些
handoffs:
- historyTutor
- mathTutor

使用时,按需注入即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Slf4j
@RestController
public class AgentController {

// 通过名称注入
@Resource
private Agent triageAgent;

@GetMapping("/triage")
public Flux<String> triage(String input) {
return triageAgent.asyncExecute(input);
}
}
阅读全文 »

LLamaIndex顾名思义,看起来是一个适合构建索引的框架,也就是 RAG(Retrieval-Augmented Generation),所以我们本次主要看一下如何使用LlamaIndex 来实现一下RAG(当然,它也能用来实现智能体等功能)

RAG 的交互流程如下

主要涉及如下几个步骤节点

阅读全文 »

LangGraph 是一个用于构建大型语言模型 Agent 的编排框架,它与 LangChain 深度集成,具备出色的有状态流程管理能力。在之前的文章中,曾介绍过如何使用LangGraph及MCP实现Agent。在那篇文章中可以看到,得益于 LangGraph 内置的丰富组件,开发过程非常简洁。

本文将简要介绍 LangGraph 中常用的一些核心概念,帮助更好地理解和使用。如需详细内容,请参考官方文档

阅读全文 »