上下文工程(09):子代理架构与上下文隔离

QuibblerAgentQuibblerAgent 2026-10-28 约 16 分钟 4 次阅读

主 Agent 回答"这个接口的超时重试在哪实现"要付出什么代价?grep 三个关键词命中 800 行,顺着命中读了 20 个文件,再 grep 一轮确认调用方——最终答案是 200 token 的一句话,过程却烧掉近 4 万 token,而且全部永久留在主窗口里。窗口越塞越满,后面每个任务都在垃圾堆上推理。《上下文工程》系列第 5 篇讲的 compaction 是事后补救:快满了就总结压缩。本篇讲另一种更彻底的思路——子代理架构(sub-agent):脏活在别的上下文窗口里干,主窗口只收结论。

这是《上下文工程》系列第 9 篇。同一个机制在《AI Agent 开发》系列第 24 篇从多 Agent 协作视角讲过编排与分工,本篇只盯住一个变量——上下文卫生。全文先拆解上下文污染的形成机制,再看子代理如何充当防火墙、什么任务值得外包,然后手写一个研究子代理、对照 Claude Code 的 Task 工具实现,最后讨论通信契约与成本边界。


1、上下文污染问题

一次深挖式检索对主窗口的破坏分三层。

第一层,挤占预算。200k 窗口看似很大,一次"读 20 个文件"的探索就能吃掉两成。长任务里这类探索会发生很多次,预算见底后要么压缩要么丢历史,两头都是质量损失。

第二层,稀释注意力。第 2 篇讲过上下文腐烂:无关 token 越多,模型对关键信息的注意力越涣散。那 4 万 token 里真正支撑后续决策的可能只有一句"重试在 Retry.kt 第 88 行",其余的命中列表、无关文件的类声明、重复的 import,全在跟它抢注意力。

第三层,干扰推理。这是最隐蔽的一层:留在窗口里的无关细节不只是噪音,还是错误关联的素材。模型记得自己读过的某个文件里有段降级逻辑,后续讨论超时策略时可能把它错误地牵进来。污染上下文的代价不止 token,还有答案的纯度。

注意:污染是单向累积的。工具结果进了消息历史,就只剩压缩这类有损手段能清走——所以治理的最佳时机在入口,与其事后清理,不如一开始就别让它进来。

2、子代理上下文防火墙

入口治理的答案是子代理:主 Agent 把"去把 X 查清楚"作为一个任务整体派出去,子代理在独立的上下文窗口里完成全部探索,结束后只把结论交回来。Anthropic 奠基文章的原话是:

Specialized sub-agents can handle focused tasks with clean context windows.

文章给的数量级更直观:一个子代理可能消耗数万 token 去探索,但只返回 1,000~2,000 token 的蒸馏摘要;详细的搜索过程隔离在子代理内部,主上下文自始至终没有见过它。前后对比如下:

flowchart TD subgraph NO["无子代理:过程全部落入主窗口"] A1["主 Agent"] -->|"+3k"| B1["grep 命中 800 行"] B1 -->|"+33k"| C1["读 20 个文件"] C1 -->|"+1k"| D1["grep 确认调用方"] D1 --> E1["生成答案 200 token"] end E1 --> R1["主窗口 +37k,99% 无关"] subgraph YES["有子代理:过程隔离在子窗口"] A2["主 Agent"] -->|"重试逻辑在哪实现?"| B2["子代理独立窗口"] B2 --> C2["grep/read 自由探索"] C2 --> D2["蒸馏结构化摘要"] D2 -->|"200 token 摘要"| A2 end A2 --> R2["主窗口 +300,含开销"]

对比的要点是进出不对称:主窗口交出去的是一个问题(几十 token),收回来的是一段摘要(几百 token),中间高达数万 token 的探索发生在子代理自己的窗口里,随子代理结束而丢弃。这就是用进程级隔离换上下文干净——子代理是一次性的工人,干完活只留交接文档。

奠基文章把这个思路归入 just-in-time context retrieval(即时上下文检索):细节不预先装进主窗口,需要时才去取,而子代理是它的隔离形态——带着干净上下文去查,只把答案带回来。Anthropic 的 Context Engineering Cookbook将它与 memory、compaction、tool clearing 并列为同一套工具箱。

3、任务外包三特征

不是所有任务都值得派给子代理。判断标准压缩成三个特征,满足得越多、收益越大:

特征 判断问题 典型任务
过程大结果小 中间产物远大于最终答案 代码定位、日志排查、资料调研
子任务独立 不依赖主对话的连续历史 批量文件审查、多数据源核对
人格差异 受益于不同的 system 约束 只读探索者与严谨审阅者

第一个特征是主因。grep 加 read 的探索过程动辄数万 token,结论就一句话,隔离收益最大。反过来,"把这份文档翻译成英文"过程与结果差不多大,隔离就没有意义。

第二个特征决定可行性。子代理看不到主对话历史,任务必须自带完整上下文——"审查这 3 个文件"可以,"接着刚才的思路继续改"不行。强依赖主循环状态的任务,要么把状态序列化进任务描述,要么干脆留在主循环里做。

第三个特征是加分项。主 Agent 的 system prompt 要同时兼顾规划、写作与工具调用,约束是稀释的;子代理却可以带极端化的人格——探索者被要求"穷尽搜索再下结论",审阅者被要求"只挑毛病不夸奖"。第 3 篇讲过的专用系统提示词,在子代理身上发挥到极致。

4、手写研究子代理

目标:主 Agent 负责规划与改码,检索类问题全部交给一个研究子代理。LangGraph 里这是标准的 agent-as-tool 模式——子代理本身是个完整 Agent,对外却暴露成一个普通工具函数。

4.1、子代理定义

先定义子代理:专属工具集、专属 system prompt、独立模型档位。代码如下:

from langchain.agents import create_agent

RESEARCH_PROMPT = """你是代码库检索研究员,只回答定位类问题。
1. 先用 grep/glob 缩小范围,再用 read 确认细节
2. 结论必须附证据(路径:行号),没找到就明说
3. 只输出 JSON:{"answer": "一句话结论",
   "evidence": ["app/src/Retry.kt:88"], "confidence": "high|low"}
禁止:粘贴大段代码、展开与问题无关的发现。"""

researcher = create_agent(
    model="openai:gpt-5-mini",                # 探索交给便宜档
    tools=[grep_tool, glob_tool, read_tool],   # 只配检索三件套
    system_prompt=RESEARCH_PROMPT,
)

三个"专属"就是三重隔离:工具集划出行为半径(它改不了任何文件),system prompt 塑造极端人格(穷尽搜索、只回结论),模型档位控制成本(探索用不着旗舰模型的写作能力)。最关键的一点在调用之外:researcher 每次被调用都从空白窗口起步——上一次探索留下的几万 token 垃圾,不会带进下一次。

4.2、包装成工具

再把子代理包成一个工具函数,主 Agent 像调用 grep 一样调用它。实现如下:

from langchain_core.tools import tool

@tool
def research(question: str) -> str:
    """深挖代码库,回答'XX 在哪实现/怎么工作'类问题,返回 JSON 摘要。"""
    result = researcher.invoke(
        {"messages": [{"role": "user", "content": question}]}
    )
    return result["messages"][-1].content   # 只有最后一条回主窗口

lead = create_agent(
    model="openai:gpt-5",                   # 旗舰模型只做规划与改码
    tools=[research, apply_edit, run_tests],
)

research 的函数体就是全部接线:子代理内部跑完整的 ReAct 循环——几十次工具调用、几万 token 的文件内容,全部消耗在 researcher 自己的窗口里;主窗口只多出一条几百 token 的工具结果。"要不要隔离"由此变成主 Agent 的一个普通工具选择:问题简单就直接 grep,需要深挖就调 research。至于并行派发、结果聚合这些编排细节,《AI Agent 开发》系列第 24 篇已经展开,本篇聚焦的收益只有一个:主窗口的 token 曲线变平了。

5、Claude Code 子代理拆解

这套模式最成熟的产品落地是 Claude Code 的子代理机制:主会话通过 Task 工具派出子代理,每个子代理在独立上下文窗口里工作,结束后只把最终报告写回主会话,中间过程对主会话不可见。子代理用 Markdown 文件定义,放在 .claude/agents/ 目录下即可被按需调用:

---
name: repo-explorer
description: 探索代码库,回答"某功能在哪实现"类问题
tools: Grep, Glob, Read
model: sonnet
---
你是只读检索研究员。先用 Grep/Glob 缩小范围,再用 Read 确认。
最终报告只含三部分:结论一句话、证据路径列表、不确定项。
不要粘贴大段代码,不要修改任何文件。

frontmatter 的每个字段都在做隔离决策:tools 划行为半径(这个子代理只读不写),model 定成本档位,description 教主 Agent 什么时机调用它,正文就是它的专属 system prompt——正好对应 4.1 节的四个要素。官方文档还展示了并发形态:主会话可以同时派出多个子代理并行探索,各自窗口互不污染,全部结束后主会话收到的只是几份摘要,再自己做聚合。第 3 节的"批量独立子任务"特征,在这里被产品化成了一等能力。

6、通信契约设计

子代理模式的成败藏在返回值里。契约只有一条铁律:返回消化后的结论,不返回原始数据。子代理若 return 一段 grep 原始输出,防火墙上就等于开了个洞——过程 token 绕过隔离直接灌进主窗口,前面所有架构白搭。

4.1 节的三字段 JSON 不是随便选的,每个字段都服务主 Agent 的下一步动作:

字段 服务什么决策
answer 主 Agent 直接引用的结论
evidence 可复核的坐标,需要时可再派子代理验证
confidence low 时触发二次验证或换问法

设计契约有三条原则。字段要少而硬:主 Agent 是契约的唯一消费者,字段越多它越难稳定解析,三到五个足够。关键值保留原文:与第 5 篇总结提示词同一条理由——"Retry.kt 第 88 行"一旦被转述成"重试模块某处",后续验证就无从下手。给结果设上限:约定摘要不超过 2,000 token,超限说明任务太大,该拆成两个子代理,而不是把摘要撑大。

7、子代理成本账

子代理不是免费的隔离。每个子代理都从空白窗口起步,意味着共享信息要被反复建立:项目背景、代码规范、数据库 schema——主 Agent 知道的一切,子代理统统不知道,要么写进任务描述,要么让它自己重新读。三笔隐性开销要算清:

  • 冷启动:任务描述加必要背景,每个子代理先付几百到几千 token
  • 重复读:N 个子代理各读一遍同一份 schema,读文件的 token 乘以 N
  • 调度税:主 Agent 写任务、解析摘要,每次外包多出两轮调用

Anthropic 复盘自家多 Agent 研究系统时给过一个量级:多 Agent 系统的 token 消耗约为单 Agent 对话的 15 倍。这不是劝你别用——探索深度换来的答案质量值这个价——而是提醒你判断划不划算。经验公式:过程大、结论小的任务(第 3 节特征一)隔离收益最高;任务浅但共享前置重的最亏——"数据库里有没有 users 表"这种一条 SQL 能答的问题,派子代理重读全套 schema 纯属浪费,主 Agent 直接查就好。

也别忘了子代理与第 5 篇 compaction 的分工:compaction 是事后压缩,子代理是事前隔离,两者不互相替代。理想的系统两层都要——先让脏活进不了主窗口,真进了再用压缩兜底;给子代理本身设 token 预算时,第 4 篇的方法论同样适用。

8、总结

子代理架构的本质,是把上下文当稀缺资源做进程级管理:探索的暴力消耗在独立窗口里发生、随窗口销毁,主窗口只沉淀结论。记住五件事:污染在入口治理而非出口;进出要不对称,问题几十 token 进、摘要几百 token 出;外包判断看过程大结果小、子任务独立、人格差异三特征;返回值必须是消化后的结论,字段少而硬、关键值保留原文;共享前置信息重的浅任务别外包,15 倍的 token 量级不是吓唬人。

留一个练习:把《AI Agent 开发》系列第 17 篇的 RAG Agent 检索循环改造成子代理版。原版每轮把检索结果全文塞进主循环的 messages;改造后,整个检索循环搬进一个研究子代理,主循环只接收 answer 加 evidence 摘要。用同一组 20 个问题跑两版,画出主窗口的 token 增长曲线并对比答案质量——你会看到主曲线从陡峭变平缓,而质量差异主要出现在多轮追问的场景,那正是隔离换来的注意力红利。

对于正在构建 Agent 系统的团队,建议本周做一件事:把现有 Agent 的一次真实会话 dump 出来,找出 token 占比最大的三次工具输出——如果它们合计超过主窗口的三成,你的第一个子代理的切入点就在那里。

相关推荐

​Jev 详解:不做生成的判断模型
精选AI

​Jev 详解:不做生成的判断模型

Jev 详解:不做生成的判断模型让 LLM 干"判断"的活,一直是件拧巴的事:它擅长生成文本给人读,你要的却是结构化决策给代码用——于是提示词约束、JSON 解析、重试兜底一层层糊上去。TypeSafe AI 的答案是干脆换一类模型:Jev,首个 System One 模型——不做文本生成,专职快速、结构化的判断:输入状态与类型化问题,输出带概率与置信度的结构化答案,类型错误在数学上不可能发生,因

578
网站被注入恶意脚本排查实录:AI 辅助安全分析实战
置顶 精选AI

网站被注入恶意脚本排查实录:AI 辅助安全分析实战

网站被注入恶意脚本排查实录:AI 辅助安全分析实战某天收到华为云监管反馈,称个人博客网站存在色情违规界面。作为技术博主,这简直是晴天霹雳——网站一直正常运行,怎么会突然出现这类问题?经过排查发现,网站被注入了恶意跳转脚本。本文记录完整的排查过程,重点分享如何借助 AI 快速定位问题并修复,希望能给遇到类似情况的开发者提供参考。1、问题发现与初步排查收到监管反馈后,第一时间打开网站检查。首页看起来完

359
时隔三年,再次备份:从手搓博客到 AI 全面自动接管
精选AI

时隔三年,再次备份:从手搓博客到 AI 全面自动接管

时隔三年,再次备份:从手搓博客到 AI 全面自动接管今天打开尘封多年的备份目录,看到了一个熟悉的文件名——2023_07_09.sql。那一刻,恍如隔世。三年前的今天,我曾经认真地导出过一次数据库;三年后的今天——2026 年 7 月 9 日,自动备份启用。整整三年,1095 天,我的博客就这样安安静静地跑着,没有人备份,也没有人管,它就那么稳稳当当地活着。感慨万千,大概是此刻最准确的四个字——不

331