CrabNote螃蟹笔记

小松鼠:万字长文,循序渐进,学习搭建像Claude Code一样好用的智能体

小松鼠:万字长文,循序渐进,学习搭建像Claude Code一样好用的智能体

小松鼠:万字长文,循序渐进,学习搭建像Claude Code一样好用的智能体 小松鼠:万字长文,循序渐进,学习搭建像Claude Code一样好用的智能体 Modified March 10 Code block Python Copy msg type="shutdown request" ) 等待所有人响应 self. wait for responses() def wait for responses(self, timeout: int = 30): """等待关机响应""" start = time.time() pending = set(self.tm.teammates.keys()) while pending and (time.time() start) < timeout: for msg in self. get shutdown responses(): if msg["request id"] == self.request id: pending.discard(msg["from"]) time.sleep(0.5) if pending: 超时了还有人没响应,强制终止 for tid in pending: self.tm.force terminate(tid) 流程是这样的: 1. 主Agent发送shutdown request给所有队友 2. 队友收到后,完成手头工作,发送shutdown response 3. 主Agent等待所有响应(最多30秒) 4. 超时的直接强制终止 主Agent关闭进程时,给队友时间收尾,但不会无限等待。 request id追踪 一次主Agent的协调关闭流程, 可能有多次shutdown请求。 假设第一次shutdown超时了,强制杀掉一些进程, 然后主Agent又创建了新队友。 这时候如果还有老的shutdown response飞过来, 怎么区分是响应哪次请求的? request id就是用来匹配请求和响应的。 每次shutdown生成新的request id, 只接受匹配的response。 这是分布式系统的常见模式。 六、v8完整的协作流程 把v8a/b/c串起来,完整流程是这样的: Code block Plain Text Copy 1. 主Agent收到复杂任务 2. 分析任务,决定需要几个队友 需要一个搞代码的 需要一个做测试的 需要一个写文档的 3. 创建队友(v8a) TeamCreate(agent type="code", name="小代") TeamCreate(agent type="test", name="小测") TeamCreate(agent type="doc", name="小文") 4. 发布任务到任务板(v8c) task 1: 重构auth模块 task 2: 写auth模块的单测 task 3: 更新auth文档 5. 队友们认领任务 小代 claim task 1 → 成功 小测 claim task 2 → 成功 小文 claim task 3 → 成功 6. 并行执行 小代:改代码... 小测:(等小代的结果) 小文:先写框架... 7. 通过消息协调(v8b) 小代 → 小测:"auth.py改完了,你可以开始测了" 小测:"收到,开始写测试" 8. 任务完成 各自在任务板标记completed 9. 主Agent检查任务板 发现都完成了 10. 发起shutdown shutdown request → 等待response → 清理资源 11. 返回最终结果 这就是一个完整的多Agent协作周期。 七、v9:自治团队 v8的团队还是主Agent在创建和指挥, 队友只是执行者。 v9让队友也能创建队友。 这就变成了递归的团队结构: Code block Plain Text Copy 主Agent ├── 队友A(可以创建自己的子队友) │ ├── 队友A 1 │ └── 队友A 2 ├── 队友B └── 队友C └── 队友C 1 每个Agent都可以: • 创建自己的团队 • 管理自己的任务 • 和其他Agent通信 代码实现上主要是解除了一些限制: Code block Python Copy v8: 只有主Agent能创建队友 if not is main agent: raise PermissionError("Only main agent can create teammates") v9: 任何Agent都能创建队友 (删掉上面的检查就行了) 但自治也带来新问题: • 怎么防止无限递归创建? • 怎么追踪整个团队树? • 怎么处理跨层级通信? 简单说一下v9的解决思路: 防止无限递归:深度限制 + 总数限制 每个Agent有个depth属性(主Agent是0,它创建的是1,再创建是2...),设置max depth=3,超过就拒绝创建。同时限制全局最大Agent数,比如max total agents=10。 追踪团队树:共享注册表文件 Code block Plain Text Copy .team/registry.json { "main": {"parent": null, "children": ["t1", "t2"], "depth": 0}, "t1": {"parent": "main", "children": ["t1 1"], "depth": 1}, "t1 1": {"parent": "t1", "children": [], "depth": 2} } 每个Agent创建/销毁时更新这个文件,任何人都能看到完整的团队结构。 跨层级通信:查注册表直接发 想给谁发消息,先查注册表找到对方的inbox路径,直接写文件过去。不用逐级转发,但需要权限控制(比如只能给同一棵树上的Agent发消息)。 有兴趣可以去看源码,这里不展开了 八、尾声 流程是这样的: 1. 主Agent发送shutdown request给所有队友 2. 队友收到后,完成手头工作,发送shutdown response 3. 主Agent等待所有响应(最多30秒) 4. 超时的直接强制终止 主Agent关闭进程时,给队友时间收尾,但不会无限等待。 request id追踪 一次主Agent的协调关闭流程, 可能有多次shutdown请求。 假设第一次shutdown超时了,强制杀掉一些进程, 然后主Agent又创建了新队友。 这时候如果还有老的shutdown response飞过来, 怎么区分是响应哪次请求的? request id就是用来匹配请求和响应的。 每次shutdown生成新的request id, 只接受匹配的response。 这是分布式系统的常见模式。 六、v8完整的协作流程 把v8a/b/c串起来,完整流程是这样的: 这就是一个完整的多Agent协作周期。 七、v9:自治团队 v8的团队还是主Agent在创建和指挥, 队友只是执行者。 v9让队友也能创建队友。 这就变成了递归的团队结构: 每个Agent都可以: • 创建自己的团队 • 管理自己的任务 • 和其他Agent通信 代码实现上主要是解除了一些限制: 但自治也带来新问题: • 怎么防止无限递归创建? • 怎么追踪整个团队树? • 怎么处理跨层级通信? 简单说一下v9的解决思路: 防止无限递归:深度限制 + 总数限制 每个Agent有个depth属性(主Agent是0,它创建的是1,再创建是2...),设置max depth=3,超过就拒绝创建。同时限制全局最大Agent数,比如max total agents=10。 追踪团队树:共享注册表文件 每个Agent创建/销毁时更新这个文件,任何人都能看到完整的团队结构。 跨层级通信:查注册表直接发 想给谁发消息,先查注册表找到对方的inbox路径,直接写文件过去。不用逐级转发,但需要权限控制(比如只能给同一棵树上的Agent发消息)。 有兴趣可以去看源码,这里不展开了 八、尾声 到这里,v0到v9全部讲完了。 让我们回顾一下这趟旅程: v0 v2:单Agent基础 v3 v6:上下文与记忆 v7 v9:团队协作 从50行代码到几千行代码, 从一个Agent到一个团队, 核心思想始终没变: 🏅 Agent = LLM + Plan + Tools + Memory Agent = LLM + Plan + Tools + Memory 当然,目前这些工程化的操作, 都是用代码和工具来补全LLM本身的能力不足。尤其是上下文的限制。 如果哪一天,大模型进化到超量的上下文,足够的强, 这套框架中的代码就都可以省去了 这个系列就到这里了。 有兴趣的可以去看源码: https://github.com/shareAI lab/learn claude code 看高手的工程代码,来学习设计思路, 是一件很快乐的事情 看到这里了,如果觉得不错: ✓ 点个「赞」,让我知道你在看 ✓ 点个「在看」,分享给更多朋友 ✓ 点个「转发」,帮助更多人 ✓ 加个「星标⭐」,第一时间收到推送 也可以加我的个人微信围观学习:archerqc 小松鼠爱你们! 大家好,我是小松鼠。 这是我的第 30 32 篇 AIGC 文章合集。 分成了上中下三期。 万字长文,结合工程源码,去了解如何从零开始,构建一个Agent。 😀 三篇的内容循序渐进,可以按照目录学习 • Bash is all you need(智能体结构和基本循环) • 上下文管理与记忆系统 • 多Agent团队协作 三篇的内容循序渐进,可以按照目录学习 • Bash is all you need(智能体结构和基本循环) • 上下文管理与记忆系统 • 多Agent团队协作 Bash is all you need(v0 v2) 大家好,我是小松鼠。 一名AI时代的学习者,专注探索个体在新时代的生存模式。 这是我的第 30 篇 AIGC 文章、。 最近高强度用Claude Code, 它能自己分析项目结构,读代码,改bug,写测试, 能创建子任务,自己递归解决问题。 我就想搞清楚一件事: 这玩意儿到底是怎么实现的? 这几天在GitHub上又发现了一个宝藏仓库 learn claude code, https://github.com/shareAI lab 由shareAI Lab发布, 用最简单的代码揭露了Claude Code的底层原理。 (声明一下,这是独立的教育项目,和Anthropic没关系,就是民间大神的逆向分析和推测) 从v0到v9,一共10个版本, 渐进式地展示了 🏅 一个AI编程Agent怎么从最简单的50行代码, 进化成一个复杂的多Agent协作系统。 一个AI编程Agent怎么从最简单的50行代码, 进化成一个复杂的多Agent协作系统。 今天先讲v0到v2。 尤其是v0部分,讲解了Bash操作 Bash是精华,是灵魂,是所有复杂能力的起点。 搞懂Bash,你就理解了AI Agent最核心的东西。 建议收藏慢慢看。 一、什么才是真正的AI Agent 还记得我们的核心公式么? 🏅 Agent = LLM + Plan + Tools + Memory Agent = LLM + Plan + Tools + Memory 我们今天篇幅所限,先不讲Memory部分。 该项目的作者理解最基础的Agent公式: AI Agent = 大模型(LLM) + 工具调用(Tools) + 循环执行(Plan) 就这三样东西,看是不是一模一样 用动画来看更直观: 传统的大模型对话: • 你问一句 • AI答一句 • 完事 Agent模式: • 你给一个任务 • AI想一想,决定用什么工具 • 执行工具,拿到结果 • 再想一想,需不需要继续 • 继续执行,或者返回最终答案 核心区别在于那个"循环"。 普通聊天是单轮对话, Agent是多轮工具调用。 模型自己决定什么时候停。 这就是为什么Agent能"自主完成任务", 二、v0:Bash就是一切 这是整个仓库最精华的部分。 核心代码只有50行左右, 🏅 一个工具(bash)+ 一个循环 = 完整的Agent能力 一个工具(bash)+ 一个循环 = 完整的Agent能力 为什么是Bash? 这里有一个深刻的洞察:Unix哲学 🏅 Unix世界里有两句话: • 一切皆文件 • 一切皆可管道 Unix世界里有两句话: • 一切皆文件 • 一切皆可管道 Bash是Unix世界的入口。 文件意味着可以增删改查。 管道意味着可以链式传递。 当你拥有了Bash,你就拥有了一切 • 读文件?cat, head, tail, grep • 写文件?echo '...' file, sed • 搜索?find, grep, rg, ls • 执行任意命令?python, npm, make... • 甚至子代理?python v0 bash agent.py "子任务" 最后一行是关键。 通过Bash调用自身,就能实现子代理。 不需要什么Task工具, 不需要什么Agent注册表, 一个最简单的智能体,只需要递归。 什么是递归啊? 递归这个概念,高中数学就学过。 函数自己调用自己,就是递归。 子代理的实现原理一模一样: 主Agent通过Bash命令调用v0 bash agent.py, 子进程启动,有自己独立的上下文(history=[]), 干完活,把结果通过stdout返回给主Agent。 进程隔离 = 上下文隔离 这就是"分而治之"的编程思想在Agent领域的应用。 来看核心代码(简化版): 没了。就这么点代码。 看到没有? 整个Agent的核心就是一个while True循环。 孩子们,就是这么简单。 大模型不断调用工具, 工具结果不断反馈给大模型, 直到大模型觉得任务完成了(stop reason != "tool use"), 循环才结束。 这就是所有AI编程Agent背后的模式 Claude Code是这样,Cursor,Codex CLI也是这样 AI圈最擅长造词营销== 什么自主智能、具身智能、多模态Agent... 归根结底,本质都是这个循环。 大模型的决定性差异 一个Agent好不好用,模型是80%,代码是20%。 代码只是提供工具和运行循环, 决策权完全在模型手里。 模型决定: • 调用什么工具 • 按什么顺序 • 什么时候停止 这就是为什么他们叫它"Model as Agent", 🏅 模型即代理。 代码不是Agent,模型才是。 模型即代理。 代码不是Agent,模型才是。 三、v1:工具专业化 v0证明了Bash就是一切, 但在实际使用中有点问题: 用Bash写文件太难受了 你得写 echo 'xxx' file 或者 cat << 'EOF' file, 一旦内容里有引号、特殊字符,就容易出错。 而且Bash命令的输出不够结构化,模型容易误解。 把常用操作抽象成工具 v1的解决方案: 从1个Bash工具扩展到4个工具: • bash:执行任意shell命令 • read file:读取文件内容 • write file:写入文件 • edit file:精确替换文件中的文本 这4个工具覆盖了90%的编程场景。 核心循环完全不变,只是工具更专业了。 来看read file的简化实现: 我这里重点提一下那个50000的数字。 这是上下文管理的技巧。 大模型的上下文窗口是有限的, 工具输出太长会"撑爆"上下文, 所以要做截断。 edit file更精巧: 用精确字符串匹配来定位修改位置, 只改第一处,防止批量误改。 这些小细节,都是实战中踩坑踩出来的 工具的哲学 🏅 一个好工具胜过复杂的框架。 一个好工具胜过复杂的框架。 工具设计得好,模型自然用得好。 (目前很多Agent框架搞得特别复杂,其实没必要,够用就好) 四、v2:让计划可见 v1对简单任务效果很好, 但遇到复杂任务就出问题了。 比如让它 Agent会发生什么? • 它会在任务之间反复横跳 • 做着做着忘了之前做到哪了 模型上下文失去焦点。 在v1里,计划只存在模型的"脑子"里,是隐式的: (这里没有真正的脑子,还没有引入记忆功能) v2的解决方案:TodoWrite工具(也就是claude中的ToDolist) 让计划显式化,写出来。 现在你和模型都能看到计划了。 模型可以: • 更新任务状态 • 看到已完成和待完成 • 一次只专注一件事 来看TodoManager的核心代码约束: 两个核心约束: • 最多20个任务:防止无限列表 • 同时只能有1个in progress:强制聚焦 max tokens限制 → 让回复可控,不会无限扩张超长回答 工具schema约束 → 让调用结构化 TodoList约束 → 让复杂任务可追踪 🏅 好的约束让事情变简单,而不是更难。 好的约束让事情变简单,而不是更难。 v2还加了一个小技巧:reminder机制。 如果模型10轮没更新todo,就注入一个提醒: 不是强制,是软提醒。 鼓励而非强迫。 这种设计思路很值得学习。 五、尾声 到这里,我们体验了基础的Agent思路 后面还有v3的子代理机制、v4的Skills注入、v5的上下文压缩、v6 v9的任务系统和多Agent协作... 内容太多,下篇再说。 有兴趣的可以直接去看源码: https://github.com/shareAI lab/learn claude code 代码不长,注释很全,Python写的,跑起来也简单。 或者,你可以等小松鼠的分析文章。 我们一起进步 上下文管理与记忆系统(v3 v6) 上篇我们讲了v0到v2, 搞清楚了AI Agent最简单的核心模式: 大模型(LLM) + 工具(Tools) + while循环(Plan) 小松鼠一再强调, 智能体的核心公式是 🏅 Agent = LLM + Plan + Tools + Memory Agent = LLM + Plan + Tools + Memory 目前的Agent,还缺了最关键的记忆系统。 Agent会遗忘。 这就是今天要讲的核心问题: 上下文管理和记忆机制 v3到v6,就是围绕这个问题展开的。 建议收藏慢慢看。 一、Agent的"记忆"到底是什么 先搞清楚一个基本概念。 大模型没有真正的"记忆"。 它不像人脑那样存储长期记忆。 模型每次对话,都是从头开始。 🏅 那它怎么记住之前的对话? 答案是:上下文窗口。 那它怎么记住之前的对话? 答案是:上下文窗口。 我们来祛魅,说人话就是: 把历史消息全部塞进去,一起发给模型~~ 模型看到完整历史,假装记得之前发过的对话。 但问题来了: 上下文窗口是有限的。 一个复杂重构任务,100+工具调用, 每次读文件几百行, 很快就撑爆了。 撑爆之后怎么办? 要么截断历史。 (之前的对话丢了) 要么压缩历史。 (只保留关键点,压缩也会伴随信息丢失) 小松鼠给你加一个课 这里有个关键问题很多人没搞明白: 上下文到底存在哪?远端还是本地? 答案是:全在本地。 每次你和AI对话,本质上是这样的: 远端模型是无状态的。 它不记得你是谁,不记得你之前说了什么。 每次调用API,你得把所有对话历史全部发过去。 模型看到完整历史,处理完,返回结果,然后忘掉一切。 🏅 这就是为什么上下文管理这么重要—— 对话越长,每次发送的内容就越多。 这就是为什么上下文管理这么重要—— 对话越长,每次发送的内容就越多。 Token计费:输入 vs 输出 说到这里,顺便讲讲Token计费。 很多人看账单看不明白,为什么分"输入"和"输出"两部分? 输出Token通常比输入贵3 5倍。 为什么? 因为输入只是"读",模型扫一遍就行。 输出是"写",模型要逐个生成每一个token。 每生成一个token,都要基于前面所有内容重新计算概率, 计算量是指数级的。 所以输出更贵,合理。 对话越长,消耗越大 假设一轮对话的上下文是1000 tokens: 每一轮都要重新发送所有历史。 在代码里,是个history的数组,会不断塞历史数据进去。 所以,无论用什么Agent工具,当你的会话已经和之前的内容关系不大时。强烈建议重新开一个会话,避免上下文太长。 那么,怎么去优化这一系列的问题呢? 往下看 二、v3:上下文隔离 🏅 进程隔离 = 上下文隔离 子Agent用独立历史,不污染主上下文 进程隔离 = 上下文隔离 子Agent用独立历史,不污染主上下文 来看一个真实场景: 用户说:"搜索整个代码库,然后重构商城模块" 单Agent模式: 上下文被每一个文件的细节填满了, 关键信息反而找不到了,被淹没了。 这叫上下文污染~~ v3的解决方案:Task工具。 子Agent干完活,只会按照设定好的格式,返回关键的内容总结 探索过程中的几百行信息, 主Agent根本看不到。 Agent类型注册表 v3定义了三种Agent类型: 类型 工具权限 用途 Explore bash, read file 只读权限去思考,不能改文件 general purpose 全部工具 完整实现能力(能做一切) Plan bash, read file 设计规划,不能改文件 类型 类型 工具权限 工具权限 用途 用途 Explore Explore bash, read file bash, read file 只读权限去思考,不能改文件 只读权限去思考,不能改文件 general purpose general purpose 全部工具 全部工具 完整实现能力(能做一切) 完整实现能力(能做一切) Plan Plan bash, read file bash, read file 设计规划,不能改文件 设计规划,不能改文件 主Agent会利用大模型来判断问题类型,去调用不同类型的子Agent 为什么要区分? 因为不同任务需要不同权限。 比如探索任务不需要写文件的能力, 给它写权限反而容易出问题。 这里是不是有点像公司内部的团队开发了? 策划写案子,程序员写代码,互不干扰对方的工作内容 来看核心代码(简化版伪代码): 看到那个 sub messages = [{"role": "user", "content": prompt}] 了吗? 这是关键。 子Agent不继承父Agent的上下文。 把复杂任务拆成小任务,每个小任务用干净的上下文。 三、v4:Skills v3解决了上下文隔离, 但还有一个问题: 模型怎么知道某些特定问题如何解决? 难道每次都要去重新搜索么? • 处理PDF?它得知道用什么python的代码库 • 构建MCP服务器?它得知道协议规范 这些知识不是工具,是专业能力。 v4的解决方案:Skills机制。 🏅 把知识存在可编辑的文件里,用的时候再加载 把知识存在可编辑的文件里,用的时候再加载 Skills是我们文章中的常客, 核心内容是“提示词的渐进式披露” 想要详细了解内容的,可以移步,这里不多赘述。 四、v5:策略性遗忘 v3隔离了上下文,v4外化了知识, 即使上述两个版本对上下文省了又省 上下文窗口终究是有限的 一个复杂重构任务,100+工具调用, 即使有子Agent分担,主Agent的历史也会越来越长。 撑爆上下文只是时间问题。 v5的解决方案: 选择性的去遗忘上下文 听起来反直觉? 其实人类也是这样。 你写了3小时代码,能记住每一行吗? 但你记得"做了什么、为什么这么做、现在的任务完成状态"。 (要是你全程vibeCoding,或者Ctrl V黏贴,当我没说==) 🏅 细节可以忘,要点必须留。 细节可以忘,要点必须留。 三层压缩管道 代码中,封装了三层Layer来选择性遗忘内容。 Layer 1: 微压缩 每轮自动执行,用户无感知。 关键点: • 保留工具调用结构 (模型知道它调用过什么,这里的结构越统一越好) • 只清比较久远的内容,把最近三次调用的结果继续传递 (并没有真的清理掉,需要的时候可以重新读取) • 阈值控制 (少量的内容不清理,大于特定值才清理,比如20K tokens) Layer 2: 自动压缩 当上下文接近窗口限制时触发 关键设计: • 全量长期存档到磁盘(JSON格式,或者XML,或者他自定义的格式) • 只压缩工作区的记忆,不删除长期存档 • 自动恢复最近读过的5个文件(保持上下文连贯性) Layer 3:手动压缩 相当于用户在claude里输入命令 做的事情和自动压缩的逻辑相同 认知类比 压缩机制,其实是模拟人类认知: 人类 Agent 短期记忆会自动衰减 清旧内容,只记最近最关键的几件事情 细节记忆→模糊的概念记忆 compact做总结 长期→好记性不如烂笔头 存磁盘 人类 人类 Agent Agent 短期记忆会自动衰减 短期记忆会自动衰减 清旧内容,只记最近最关键的几件事情 清旧内容,只记最近最关键的几件事情 细节记忆→模糊的概念记忆 细节记忆→模糊的概念记忆 compact做总结 compact做总结 长期→好记性不如烂笔头 长期→好记性不如烂笔头 存磁盘 存磁盘 五、v6:共享看板 到v5为止,解决了单Agent的记忆问题 但是压缩引入了一个新问题: 压缩会擦除内存状态 还记得我们上篇文章里,讲到的显示执行任务么? TodoWrite的数据存在内存里, 一压缩,任务列表就没了。 更重要的是: 当Agent从一个变成多个, 任务需要统筹管理, 再不是一个Agent中,从上到下执行了。 很多时候,一个子Agent完成后,另一个子Agent才开始工作。 比如 美术创作完成UI界面资源,前端才去拼页面。 v6解决了这个问题: 一个共享看板,所有Agent都能看到进度 和 写入更新 🏅 从TodoWrite进化成了更复杂的Tasks 从TodoWrite进化成了更复杂的Tasks TodoWrite vs Tasks 对比 TodoWrite (v2) Tasks (v6) 存储 内存 文件 持久化 压缩即丢失 跨进程存活 操作 覆盖整个列表 CRUD,单条操作 协作 单Agent 多Agent可共享 依赖 无 支持blocks/blockedBy 对比 对比 TodoWrite (v2) TodoWrite (v2) Tasks (v6) Tasks (v6) 存储 存储 内存 内存 文件 文件 持久化 持久化 压缩即丢失 压缩即丢失 跨进程存活 跨进程存活 操作 操作 覆盖整个列表 覆盖整个列表 CRUD,单条操作 CRUD,单条操作 协作 协作 单Agent 单Agent 多Agent可共享 多Agent可共享 依赖 依赖 无 无 支持blocks/blockedBy 支持blocks/blockedBy 这个对比表格中,我重点讲两个名词解释 CRUD单条操作: Create,Read,Update,Delete 这是数据库操作的标准术语,几乎所有系统都是这四种操作。 我换个更亲切的名词你就懂了:增删改查 TodoWrite (v2): 每次操作都要传整个列表 [任务1, 任务2, 任务3] → 覆盖成 → [任务1, 任务2修改版, 任务3] Tasks (v6): 只操作单条 TaskUpdate(id="2", status="completed") → 只改任务2 blocks / blockedBy 这是任务依赖关系,项目管理里很常见: 用代码表示: Tasks是完全重新设计的任务系统: 最关键的就是我们上述提到的这两个名词, 意味着每条任务是个独立的对象,并且互相存在依赖和阻塞状态。 依赖图 任务A完成后,自动从任务B的blocked by里移除。 文件持久化 • 一个文件一个任务 ( 天然隔离,不同Agent操作不同文件互不干扰) • 子Agent可能在不同进程,但都可以只读某个文件(读操作不需要锁) • JSON文件人类可读,方便调试 每个任务一个文件 多个Agent可以并发操作不同任务, 通过"每个任务对应各自独立文件"的架构设计, 避免冲突,而不是靠传统的文件锁。 CRUD工具 v6提供4个针对任务的独立工具: • TaskCreate:创建新任务 • TaskGet:获取任务详情 • TaskUpdate:更新状态、添加依赖、设置所有者 • TaskList:列出所有任务 至此,v6完成了从个人到团队的看板 通过保存文件的方式来防止上下文压缩过程的任务丢失。 通过设置依赖关系和所有者,来联动管理各个Agent。 六、尾声 至此,我们跟着项目作者的思路,分析了v3到v6的进化。 有兴趣的可以直接去看源码: https://github.com/shareAI lab/learn claude code 小松鼠带着大家分析, Agent中是如何管理上下文和记忆功能。 并且在v6的末尾,除了解决压缩造成的任务bug, 还引入了Agent从单兵作战进化到团队协作。 这,是我们下篇的功能了 多Agent团队协作(v7 v9) 大家好,我是小松鼠。 一名AI时代的学习者,专注探索个体在新时代的生存模式。 这是我的第 32 篇 AIGC 文章。 终于来到了这个系列的最后一篇。 前两篇讲了: • Agent的本质是什么(while循环 + 工具调用) • 上下文和记忆怎么管理(压缩、外化、持久化) 这篇要讲的是AI Agent的终极形态: 多Agent团队协作 一个Agent干活太慢? 那就让一群Agent一起干。 今天就把v7到v9的代码拆开来, 看看多Agent协作到底是怎么实现的。 建议收藏慢慢看。 一、为什么需要多Agent协作 🏅 单Agent模式有天花板。 单Agent模式有天花板。 想象一下这个场景: 你让Claude Code "重构整个项目,添加单元测试,优化性能,然后部署"。 一个Agent会怎么做? 串行执行。 先重构,再测试,再优化,最后部署。 任务A完成 → 任务B开始 → 任务C开始... 一个接一个,按顺序来。 但人类团队是怎么工作的? 并行执行。 小王重构模块A,小李写单元测试用例,小张做性能分析。 每个人同时在工作,各干各的,最后合并。 这就是多Agent协作要解决的问题: 🏅 把串行变成并行,把一个人干变成一群人干。 把串行变成并行,把一个人干变成一群人干。 二、v7:后台执行(先让单个任务能并行) 在讲团队之前,得先解决一个前置问题: 怎么让单个任务在后台跑? v7之前,所有工具调用都是同步的: 调用工具 → 等待结果 → 继续下一步 如果其中某一步,比如工具执行要5分钟呢? 干等着 v7的解决方案:BackgroundManager。 核心设计 看到关键了吗? subprocess.Popen 启动子进程后立即返回,不等待。 主Agent拿到task id后可以继续干别的事。 两个配套工具 有了后台执行,还需要两个工具: TaskOutput:查询任务结果 TaskStop:终止任务 光看这个代码结构还是太抽象。 我们有了第二篇上下文的详细解释, 我来讲讲,LLM到底是如何检查任务是否完成的。 起初,小松鼠觉得任务的进度,是根据task id, Agent通过代码,在本地去定时轮询检查每个任务的进度。 实际上: 🏅 本地程序负责存储和执行,远端模型负责思考和决策。 本地程序负责存储和执行,远端模型负责思考和决策。 task id作为对话历史的一部分,每次都发给模型,模型看到后自己决定什么时候查。 模型的决策基于: 1. 对话历史 — 它看到之前有task 1在跑(task id存到history数组中了) 2. 系统提示词 — 告诉它"你有TaskOutput工具可以根据task id查状态" 3. 当前输入 — 用户说"看看结果"或者模型自己觉得"差不多了"(大多数场景是模型自己觉得) 模型的决定本质上是概率生成: • 它生成的下一个token可能是"我来查一下状态" • 然后生成工具调用TaskOutput 没有定时器,没有精确控制。 就是模型"觉得"该查了就查。 使用场景 这三个工具组合起来,主Agent可以: 1. 启动后台任务(传入run in background=True) 2. 继续做其他事 3. 时不时查一下状态(检查TaskOutput block=False) 4. 后台任务完成后获取结果(检查TaskOutput block=True) 5. 必要时终止后台任务(强制调用TaskStop) 这就是单Agent内的"伪并行"。 任务在后台跑,主Agent不阻塞,模型自己会去检查后台完成进度。 但这还不是真正的多Agent, 因为只有一个大脑在思考。 三、v8a:团队成员管理 真正的多Agent协作从v8开始。 v8被拆成三个文件,因为内容太多了 • v8a:团队基础设施 • v8b:消息通信系统 • v8c:协调机制 但是我还是想一次性讲完,他们具有思维上的连续性。