通过分阶段写 markdown 文件并在阶段间清理上下文,解决 AI Agent 长期任务中的上下文膨胀和幻觉问题,目标是维持主 agent 上下文利用率低于 40%。
你有没有遇到过这样的情形:不得不中途停下 AI Agent 的任务去纠正它?与 AI Agent 打交道足够久之后,你会看到一个规律:会话运行的时间越长,输出质量就越差。
你给 Agent 的每一条输入,以及它产生的每一条输出,都会追加到上下文窗口中。没有任何内容会离开。到你对话到第五十条消息时,Agent 正在重新阅读那些早已被放弃的方案、过时的文件内容,以及一小时前做出的修正。
解决方案不是更好的提示词,而是更少的上下文。
让上下文窗口保持精简。有两个习惯可以让你的 AI Agent 避免幻觉:
委托给子 Agent。子 Agent 在自己的上下文中完成大量阅读工作,只返回摘要结果。
在阶段之间清理上下文。一旦某个阶段产生了文件,你就不再需要导致它的那段上下文了。
我的目标是让主 Agent 的上下文使用率保持在 40% 以下。
这个工作流是从 HumanLayer 的一次分享中看到的,也是我用过的最可靠的方案。它分为三个阶段,每个阶段以一个 markdown 文件结束,阶段之间会清理上下文。
研究 — Agent 撰写研究文档,然后清理上下文。
计划 — Agent 撰写计划文档,然后清理上下文。
实现 — Agent 执行计划。
主 Agent 永远不需要记住前一个阶段,因为前一个阶段已经把内容写下来了。它只需要结论。
研究阶段回答的是"某样东西今天是如何运作的"。例如:描述支付流程是如何端到端工作的。仔细查看 API 端点的实现。
主 Agent 启动并行的子 Agent 来弄清楚这些问题。从 HumanLayer 的仓库中,我发现了三个最有用的子 Agent:
codebase-locator — 找到相关代码的位置
codebase-analyzer — 解释某个组件是如何工作的
codebase-pattern-finder — 找到现有模式,作为新工作的参照
使用子 Agent 最大的好处是,你可以让它们使用更便宜的模型。我的子 Agent 跑 Sonnet,而编排层跑 Opus。
计划阶段创建构建该功能所需的具体步骤。它列出需要修改的文件、具体行号,以及确切需要做什么修改。它并行运行 codebase-locator 和 codebase-analyzer,然后撰写计划。
你可以传入一份已有的研究文档。Agent 会参考它,但仍然会自行验证,以防代码在那之后已经发生了变化。
计划的质量取决于你给出的需求质量。Agent 没有完整上下文,所以它们通过假设你需要的来填补空白。我发现这些假设很少与应用实际需要的内容相符。把边缘情况和确切的行为写出来。
我还会加上第四个子 Agent:context-locator,它能找到与你的任务相关的先前研究。我的研究文档重叠很多,引入更早的文档能产生明显更好的计划。
一个真正的计划会很长——通常跨多个阶段几百行。下面是一个针对虚构功能的计划结构:给 API 添加限流。
# Rate Limiting Implementation Plan
## Current State Analysis
- **All routes are unthrottled** — `src/api/router.ts:34-58`
- **Redis is already available** for session storage, so no new infra is needed
— `src/lib/redis.ts:12`
- **Auth middleware runs before routing**, which is where a limiter would slot
in — `src/middleware/auth.ts:20-45`
**Key gaps:**
- No rate-limiting library installed (verified: absent from `package.json`)
- No per-user identifier available on unauthenticated routes
## Desired End State
- Authenticated requests are limited to 100/min per user; unauthenticated to
20/min per IP.
- Exceeding the limit returns `429` with a `Retry-After` header.
- Limits are configurable per route without code changes.
### Key Discoveries
- The existing Redis client is created per-request, which will not work for a
shared counter — it needs a singleton — `src/lib/redis.ts:12-19`
- Health-check endpoints must stay unthrottled or the load balancer will mark
instances unhealthy — `deploy/lb-config.yaml:22`
## What We're NOT Doing
- No distributed quota syncing across regions.
- No admin UI for adjusting limits (config file only).
- No billing-tier-based limits — that's a follow-up.
---
## Phase 1: Shared Redis Client
### Changes Required
#### 1. Convert the Redis client to a singleton
**File**: `src/lib/redis.ts`
**Changes**: Export one shared connection instead of constructing per request.
```ts
let client: RedisClient | null = null;
export function getRedis(): RedisClient {
if (!client) client = createClient({ url: process.env.REDIS_URL });
return client;
}
Files: src/middleware/auth.ts:28, src/api/session.ts:15
Changes: Replace new RedisClient(...) with getRedis().
npm testnpm run typecheckImplementation Note: Pause after Phase 1 for confirmation — this touches session handling, so a regression here breaks login.
这其中有几件事比看起来更重要:
文件路径附带了行号。`src/api/router.ts:34-58` 意味着 Agent 实际读取了文件,而不是在猜测它的结构。
差距是经过验证的,而不是假设的。"verified: absent from package.json" 告诉你它确实检查了,而不是推断的。
关键发现捕捉的是那些会让你栽跟头的事情。按请求创建的 Redis 客户端和健康检查豁免权,正是那些你会在 Code Review——或者生产环境中——痛苦地发现细节。
"我们不做什么"是范围栅栏。正是这个部分阻止了 Agent 兴高采烈地构建一个你从未要求的管理界面。
成功标准把自动化的和手动的分开了。Agent 可以自己运行第一个清单,并知道把第二个清单交给你。
暂停点是明确标注的。有风险的阶段会说明这一点并停下来等待确认。
实现阶段在触碰任何东西之前会完整地阅读计划。如果它看不到各部分如何组合在一起,应该停下来验证而不是猜测。然后它执行计划,在遇到模糊之处时进行检查。
## 读文件。真的读它们。
这是人们会跳过的一步。
我数不清有多少研究和计划文档假定了错误的东西。在早期抓住这些错误,能让你免去之后本要做的大量 bug 修复工作。
这与任何开发周期中的规则相同:尽早捕获错误。在进入下一阶段之前,阅读每一份研究和计划文件。
## 何时跳过研究阶段
本能会驱使你总是走 研究 → 计划 这条路。但这并不总是最佳流程。
小功能?跳过研究,直接写计划。研究文档只会给 `context-locator` 更多要检索的内容,白白消耗 token。
需要了解一个陌生的领域?从研究开始。那个领域的未来功能可以复用这份文档。
大功能?为你的应用的每个领域写一份研究文档——支付是如何工作的、端到端的用户流程是什么样的,等等。这样,当需要执行类似"添加一种新支付方式"这样的任务时,已经知道去哪里找了。
## 文件存放在哪里
对于 monorepo,我使用 `thoughts/shared/`,下面有 `research/` 和 `plans/` 两个子文件夹,我把创建的所有文件都提交到版本库,让上下文和代码待在一起。
例外是大型团队,很多人可能会同时提交他们的文件。这种情况下,我会把文件保持在本地,需要时再分享。
## 结尾
这套流程对你是否有效,取决于你的具体场景和团队结构。HumanLayer 的方法论强调的是让 Agent 的工作透明化、可追溯,而不是让它们在模糊的指令中摸索。
如果你想深入了解这套工作流的更多细节,可以参考 Dex Horthy 在 HumanLayer 分享的演讲《No Vibes Allowed: Solving Hard Problems in Complex Codebases》,里面对如何在复杂代码库中管理 Agent 行为有更详细的案例分析。