news 2026/4/23 19:11:05

C# 实现简版 Claude Code | 子代理与上下文隔离(4)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C# 实现简版 Claude Code | 子代理与上下文隔离(4)

该系列文章基于github.com/shareAI-lab/learn-claude-code写就,该仓库以大道至简的风格剖析了Claude Code的核心原理,值得大家学习。由于该仓库是基于Python语言,为方便.NET开发者学习,我已经将代码基于.NET 10的dotnet file重写,源码已上传至github,源码地址见文末。

v3: 子代理机制 - 上下文隔离的艺术

本文是 Learn Claude Code (C# 版) 系列的第四篇,对应代码文件v3_subagent.cs

问题:上下文污染

v2 添加了规划能力。但对于大型任务:

You: 探索代码库的架构,然后重构 auth 模块

单 Agent 的执行过程:

[探索中...] cat src/Services/AuthService.cs -> 500 行 [探索中...] cat src/Models/User.cs -> 300 行 [探索中...] cat src/Controllers/AuthController.cs -> 400 行 ... 15 个文件后 ... [现在重构...] "等等,AuthService 里那个方法签名是什么来着?"

模型的上下文被探索细节填满了。当真正开始重构时:

  • 关键代码片段已经"滚出"上下文窗口

  • 模型需要重新读取文件

  • 效率低下,成本增加

这就是上下文污染——前置任务的输出污染了后续任务的工作空间。

解决方案:子代理

主 Agent 历史: [Task: 探索代码库] -> 子代理探索 20 个文件(在自己的上下文中) -> 只返回: "Auth 在 src/Services/AuthService.cs,依赖 User, Token 模型..." [现在用干净上下文重构]

进程隔离 = 上下文隔离

每个子代理有:

  1. 自己的干净消息历史

  2. 过滤后的工具集

  3. 专门的系统提示

  4. 只向父代理返回最终摘要

Agent 类型注册表

record AgentConfig(string Description, string[] Tools, string Prompt); var agentTypes = new Dictionary<string, AgentConfig> { ["explore"] = new( "只读代理,用于探索代码、查找文件、搜索", ["bash", "read_file"], // 没有写权限! "你是一个探索代理。搜索和分析,但不要修改文件。返回简洁的摘要。" ), ["code"] = new( "完整代理,用于实现功能和修复 bug", ["*"], // 所有工具 "你是一个编程代理。高效地实现请求的更改。" ), ["plan"] = new( "规划代理,用于设计实现策略", ["bash", "read_file"], // 只读 "你是一个规划代理。分析代码库并输出编号的实现计划。不要做更改。" ) };

类型

工具

用途

explore

bash, read_file

安全探索,不会意外修改

code

全部

实际实现

plan

bash, read_file

设计方案,不执行

Task 工具定义

var taskTool = new Tool { Name = "Task", Description = $""" 为专注的子任务生成子代理。 子代理在隔离上下文中运行 - 它们看不到父代理的历史。 用这个来保持主对话干净。 Agent 类型: - explore: 只读探索 - code: 完整实现 - plan: 设计策略 示例: - Task(explore): "查找所有使用 auth 模块的文件" - Task(plan): "设计数据库迁移策略" - Task(code): "实现用户注册表单" """, InputSchema = new InputSchema { Type = "object", Properties = new Dictionary<string, JsonElement> { ["description"] = ..., // 简短描述,3-5 词 ["prompt"] = ..., // 详细指令 ["agent_type"] = ... // explore | code | plan }, Required = ["description", "prompt", "agent_type"] } };

子代理执行核心

async Task<string> RunTaskAsync(string description, string prompt, string agentType) { var config = agentTypes[agentType]; // 1. 专门的系统提示 var subSystem = $""" 你是一个位于 {workDir} 的 {agentType} 子代理。 {config.Prompt} 完成任务并返回清晰简洁的摘要。 """; // 2. 过滤后的工具集 var subTools = GetToolsForAgent(agentType); // 3. 关键:隔离的消息历史! var subMessages = new List<Message> { prompt.AsUserMessage() }; // 4. 运行相同的 Agent 循环 while (true) { var response = await client.CreateMessageAsync( modelId, subMessages, new MessageParameters { System = subSystem, Tools = subTools }); if (response.StopReason != StopReason.ToolUse) { // 5. 只返回最终文本 return ExtractText(response); } // 执行工具,添加结果... } }

关键点:

  1. 隔离的subMessages- 不包含父代理的历史

  2. 过滤的工具- explore 不能写文件

  3. 专门的系统提示- 引导子代理行为

  4. 只返回摘要- 父代理不看中间细节

进度显示

Console.WriteLine($" [{agentType}] {description}"); var start = DateTime.Now; var toolCount = 0; // 执行中... Console.Write($"\r [{agentType}] {description} ... {toolCount} tools, {elapsed:F1}s"); // 完成 Console.WriteLine($"\r [{agentType}] {description} - done ({toolCount} tools, {elapsed:F1}s)");

输出效果:

> Task: 探索 auth 架构 [explore] 探索 auth 架构 ... 5 tools, 2.3s [explore] 探索 auth 架构 - done (8 tools, 4.1s)

用户看到子代理在工作,但不会被中间输出淹没。

典型工作流程

You: 重构 auth 模块使用 JWT 让我先了解现有架构: > Task: 探索 auth 架构 [explore] 探索 auth 架构 - done (12 tools, 5.2s) 摘要:Auth 模块位于 src/Services/AuthService.cs,使用 Session 认证。 依赖:User 模型、TokenRepository。主要方法:Login(), Logout(), ValidateToken()。 接下来设计迁移方案: > Task: 设计 JWT 迁移 [plan] 设计 JWT 迁移 - done (5 tools, 3.1s) 迁移计划: 1. 添加 JWT 依赖包 2. 创建 JwtService 类 3. 修改 AuthService 使用 JwtService 4. 更新 TokenRepository 5. 添加配置项 现在执行实现: > Task: 实现 JWT 认证 [code] 实现 JWT 认证 - done (15 tools, 12.3s) 完成:创建了 JwtService.cs,修改了 AuthService.cs, 更新了 appsettings.json,添加了 3 个单元测试。 任务完成!主要改动: - 新增 JwtService 处理 token 生成和验证 - AuthService 现在使用 JwtService 而非 Session - 配置文件新增 Jwt 配置节

深层洞察

分治策略

子代理本质上是分治法的应用:

  • :把大任务分解为独立子任务

  • :每个子代理独立解决其任务

  • :父代理整合子代理的摘要

上下文是稀缺资源

Claude 的上下文窗口有限(128K-200K tokens)。如何使用这个有限资源?

策略

效果

全部放主 Agent

快速溢出,早期信息丢失

子代理隔离

主 Agent 保持干净,按需获取摘要

子代理是上下文管理的工具。

工具权限控制

为什么 explore 不能写文件?

  1. 安全- 探索时意外修改很危险

  2. 专注- 强制子代理只做一件事

  3. 可预测- 你知道 explore 任务不会产生副作用

这是最小权限原则的应用。

v0 的递归 vs v3 的子代理

v0 用 bash 调用自身实现子代理:

dotnet run v0_bash_agent.cs "探索 src/"

v3 用显式的 Task 工具:

Task(explore, "探索 src/")

区别:

  • v0 更"纯粹"——一切通过 bash

  • v3 更"可控"——明确的类型和权限

防止无限递归

注意 v3 的设计:

List<Tool> GetToolsForAgent(string agentType) { var allowed = agentTypes[agentType].Tools; if (allowed.Contains("*")) return baseTools; // 不包括 Task 工具! return baseTools.Where(t => allowed.Contains(t.Name)).ToList(); }

子代理没有Task工具——不能再生成子代理。这防止了无限递归。

(生产系统可能允许有限深度的嵌套,但需要仔细控制。)

运行示例

Mini Claude Code v3 (with Subagents) - /path/to/project Agent 类型: explore, code, plan 输入 'exit' 退出。 You: 分析这个项目的架构并给出改进建议 让我先探索项目结构: > Task: 分析项目结构 [explore] 分析项目结构 - done (8 tools, 3.5s) 项目是一个 ASP.NET Core Web API: - Controllers/: 3 个控制器 - Services/: 5 个服务类 - Models/: 8 个模型 - Data/: EF Core DbContext 潜在问题:Services 直接使用 DbContext,没有 Repository 层。 接下来让我设计改进方案: > Task: 设计 Repository 模式 [plan] 设计 Repository 模式 - done (4 tools, 2.1s) 改进计划: 1. 创建 IRepository<T> 接口 2. 实现 GenericRepository<T> 3. 为每个实体创建具体 Repository 4. 修改 Services 使用 Repository 而非 DbContext 5. 更新 DI 配置 基于分析,我的改进建议是: 1. 引入 Repository 层分离数据访问 2. Services 应该依赖接口而非实现 3. 考虑添加 Unit of Work 模式管理事务 需要我实现这些改进吗?

从 v3 到 v4

v3 解决了上下文隔离问题。但还有一个挑战:

You: 处理这个 PDF 文件 You: 构建一个 MCP 服务器

模型怎么知道:

  • 处理 PDF 应该用pdftotext还是PyMuPDF

  • MCP 服务器需要什么协议规范?

这些是领域知识,不是工具能力。v4 将引入Skills 机制——按需加载专业知识。

总结

v3 的哲学:

分而治之,上下文隔离。干净上下文 = 更好结果。

子代理不是新概念,但用得好能显著提升 Agent 的能力边界。关键是理解:上下文是稀缺资源,需要精心管理。

点击阅读原文,获取仓库地址:👇👇👇

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:21:51

小白必看:REX-UniNLU文本匹配功能使用全指南

小白必看&#xff1a;REX-UniNLU文本匹配功能使用全指南 你是不是也遇到过这些情况&#xff1a; 客服系统里&#xff0c;用户说“我订单没收到”&#xff0c;但系统却把它当成“要退货”来处理&#xff1f;电商后台&#xff0c;两条商品描述明明说的是同一件衣服&#xff0c;…

作者头像 李华
网站建设 2026/4/23 11:20:29

亲测GPEN照片修复效果惊艳,批量处理人像只需3步

亲测GPEN照片修复效果惊艳&#xff0c;批量处理人像只需3步 最近整理老相册时翻出一堆模糊、泛黄、带噪点的人像照&#xff0c;有些甚至边缘发虚、细节糊成一片。试过好几款在线工具&#xff0c;不是修复后脸僵硬&#xff0c;就是肤色失真得像打了蜡。直到遇到这个由“科哥”二…

作者头像 李华
网站建设 2026/4/23 11:22:24

基于MAX232的RS232串口通信原理图系统学习路径

从“没信号”到示波器上跳动的波形:一个硬件工程师的MAX232实战手记 去年冬天,我帮一家做电力监测终端的客户调试一款新板子。MCU是STM32F407,串口引脚接了MAX232,DB9母座焊得工整漂亮——可连上PC串口助手后, 发送什么,返回什么;发‘A’回‘A’,发‘1’回‘1’,像镜…

作者头像 李华
网站建设 2026/4/23 10:43:58

浏览器打开即可使用的学生随机点名系统源码

源码介绍&#xff1a; 班级课堂点名小工具 挺有意思的&#xff0c;运行环境 html 下载地址 &#xff08;无套路&#xff0c;无须解压密码&#xff09;https://pan.quark.cn/s/13327d9d95fa 源码截图&#xff1a;

作者头像 李华
网站建设 2026/4/23 11:21:12

ChatTTS语音合成效果实测:长时间对话中声线稳定性与疲劳感抑制

ChatTTS语音合成效果实测&#xff1a;长时间对话中声线稳定性与疲劳感抑制 1. 为什么这次实测聚焦“长时间对话”&#xff1f; 你有没有试过让AI语音连续说5分钟以上&#xff1f;不是那种播音腔式的单段朗读&#xff0c;而是像真人聊天一样——有停顿、有换气、有情绪起伏、有…

作者头像 李华
网站建设 2026/4/23 11:21:12

Doris数据加密:企业级安全方案实现

Doris数据加密&#xff1a;企业级安全方案实现关键词&#xff1a;Doris、数据加密、企业级安全、加密算法、密钥管理摘要&#xff1a;本文围绕Doris数据加密展开&#xff0c;深入探讨企业级安全方案的实现。首先介绍Doris数据加密的背景&#xff0c;包括目的、预期读者、文档结…

作者头像 李华