1-learn-claude-code
GitHub上一个以Claude code为例子的agent/harness原理教程
前言¶
agent = model + harness
Agency¶
agency是感知、推理、行动的能力,llm的agency是训练出来的,不是编写出来的。
提示词水管工式 "Agent" 是不做模型的程序员的意淫。
从开发agent到开发harness¶
开发agent一方面是开发model,另一方面是开发harness
harness工程师在做什么¶
实现工具、策划知识、管理上下文、控制权限、收集执行过程数据
Claude code的构成¶
| Text Only | |
|---|---|
一个agent loop¶
| Text Only | |
|---|---|
学习路线¶
能动手、能做复杂任务、能记住和恢复、能长期运行、能协作、能扩展并合体
flowchart TD
%% 统一定义卡片样式:加入 text-align:left 保证列表不会居中乱飘
classDef stage1 fill:#E3F2FD,stroke:#1976D2,stroke-width:2px,color:#0D47A1,rx:12,ry:12,text-align:left
classDef stage2 fill:#E8F5E9,stroke:#388E3C,stroke-width:2px,color:#1B5E20,rx:12,ry:12,text-align:left
classDef stage3 fill:#FFF3E0,stroke:#F57C00,stroke-width:2px,color:#E65100,rx:12,ry:12,text-align:left
classDef stage4 fill:#FCE4EC,stroke:#C2185b,stroke-width:2px,color:#880E4F,rx:12,ry:12,text-align:left
classDef stage5 fill:#F3E5F5,stroke:#7B1FA2,stroke-width:2px,color:#4A148C,rx:12,ry:12,text-align:left
classDef stage6 fill:#E0F7FA,stroke:#0097A7,stroke-width:2px,color:#006064,rx:12,ry:12,text-align:left
%% 背景框样式
classDef groupBox fill:#F8F9FA,stroke:#CED4DA,stroke-width:2px,stroke-dasharray: 5 5,rx:15,ry:15,color:#495057
%% 第一层:1-3阶段
subgraph Phase1 ["🌱 阶段 1-3:基础能力构建(从简单到复杂)"]
direction LR
S1["<b>第一阶段:让 Agent 能动手</b><br/>━━━━━━━━━━━━━<br/><b>s01 Agent Loop</b><br/>└─ 一个循环 + bash<br/><br/><b>s02 Tool Use</b><br/>└─ 单个到多个工具<br/><br/><b>s03 Permission</b><br/>└─ 判断能不能做<br/><br/><b>s04 Hooks</b><br/>└─ 工具前后留扩展插口"]:::stage1
S2["<b>第二阶段:做复杂任务</b><br/>━━━━━━━━━━━━━<br/><b>s05 TodoWrite</b><br/>└─ 先列计划,再执行<br/><br/><b>s06 Subagent</b><br/>└─ 全新消息,返回最终文本<br/><br/><b>s08 Context Compact</b><br/>└─ 长下文腾空间"]:::stage2
S3["<b>第三阶段:跨会话记忆</b><br/>━━━━━━━━━━━━━<br/><b>s09 Memory</b><br/>└─ 保存并召回可复用知识"]:::stage3
S1 ==> S2 ==> S3
end
%% 第二层:4-6阶段
subgraph Phase2 ["🚀 阶段 4-6:高阶能力进化(长期、协作与融合)"]
direction LR
S4["<b>第四阶段:让任务长期运行</b><br/>━━━━━━━━━━━━━<br/><b>s10 Task System</b><br/>└─ 任务落盘记依赖<br/><br/><b>s11 Background Tasks</b><br/>└─ 慢操作丢后台<br/><br/><b>s12 Cron Scheduler</b><br/>└─ 按时自动触发"]:::stage4
S5["<b>第五阶段:让多个 Agent 协作</b><br/>━━━━━━━━━━━━━<br/><b>s13 Agent Teams</b><br/>└─ 队友 + 消息投递 + 协作协议<br/>└─ 原子认领就绪任务<br/>└─ 任务绑定的 Worktree"]:::stage5
S6["<b>第六阶段:接外部能力合体</b><br/>━━━━━━━━━━━━━<br/><b>s07 Skill Loading</b><br/>└─ 技能按需展开<br/><br/><b>s14 MCP Plugin</b><br/>└─ 外部接进工具池<br/><br/><b>s15 Agent Harness 集成</b><br/>└─ 课程机制回到同一循环"]:::stage6
S4 ==> S5 ==> S6
end
%% 第三层:编排与目标闭环
subgraph Phase3 ["🎯 第七阶段:编排与目标闭环"]
direction LR
S7["<b>第七阶段:编排并完成</b><br/>━━━━━━━━━━━━━<br/><b>s16 Workflow Runtime</b><br/>└─ 脚本拥有固定编排<br/><br/><b>s17 Goal Loop</b><br/>└─ 独立判断决定何时停止"]:::stage1
S6 ==> S7
end
%% 将三个模块连接起来,形成 Z 字形阅读流
Phase1 ===> Phase2 ===> Phase3
%% 应用背景样式
class Phase1,Phase2,Phase3 groupBox
S01-Agent loop¶
One loop & bash is all you need
传统chat的问题:大模型输出完了就结束了,不会自己调试。
解决方案:引入agent loop,harness内核本质是一个循环
s02-Tool Use¶
s03-Permissiong¶
s04-Hooks¶
想扩展agent的行为,又不改变循环本身,把扩展挂在外面
s05-TodoWrite¶
问题:注意力稀释
(🤔:需要这些工具的原因是model的context不够用,如果够用的话这些工具其实不是必要的,但是会不会有了这些工具之后,一个强大的模型会变的更强大,还是会被拖累,拭目以待。
todo_write本质上是一个tool
s06-Subagent¶
新的问题:如果一个任务太大,todo列表也不够,那就需要subagent
Subagents give each subtask a clean message history while preserving the main thread.
父agent和子agent共享workdir
只有一层委派
s07-Skills¶
一方面,也是因为上下文的问题,不同的任务需要不同的知识;另一方面一个重复的流程完全可以封装成一个skill进行复用
s08-Context Compact¶
上下文总是会满,压缩让有限的上下文持续服务于长任务
压缩管线设计
第一步:tool_result_budget¶
工具返回结果预算
第二步:snip_compact¶
用于控制消息数量
先把完整历史写入.transcripst/,再保留头尾,中间明确标记会写明删去了多少消息,以及完整记录在哪里
第三步:micro_compact¶
前面读过的后面就不用读了
第四步:compact_history¶
s09-Memory¶
Some facts should survive summarization and future sessions
Memory要解决的问题:哪些信息值得跨对话保存,当前任务应该回取哪几条。
全部写入,不合适¶
可能会引入很多无关紧要的东西。一种更合适的方式:保留剪短的索引,只在需要时加载正文。
需要处理的四件事情:存储、召回、提取和整理
存储:一个记忆一个文件¶
每条记忆是.memory/下的一个Markdown文件
type有四类:user记录用户的长期偏好,feedback记录以后仍适用的工作反馈,project记录稳定的项目事实
召回:先选择,再加载正文¶
由大模型完成记忆挑选
提取:回合结束后保存可复用信息¶
整理:合并重复和过期内容¶
旧文件被替换前会保存快照
s10-Task System¶
Todo是让agent记录当前任务执行步骤,提醒不要忘记。Task System负责记录每个任务独立的ID和状态,blockedBy记录前置任务,owner记录执行agent
s11-Background Tasks¶
The agent can keep reasoning while slow work completes elsewhere
任务图有了,但全量测试、安装依赖和部署等命令可能需要很长时间。同步执行这些命令时,Agent Loop 会一直停在当前工具调用上,只有命令结束后才能继续处理其他工作。
s11 Background Tasks → 把慢操作放到后台。Agent 可以继续处理其他任务,后台执行完成后再接收通知。
should_run_background: 显示请求¶
是否进入后台由工具调用明确决定
Background Manager: 后台执行与生命周期¶
collect_background_results: 通知收集¶
s12-Cron Scheduler¶
后台任务解决了"慢操作不阻塞"。但如果想定时做某件事呢?比如"每天早上 9 点跑测试"、"每 5 分钟检查一次服务器状态"。
s12 Cron Scheduler → 给 Agent 装一个闹钟。
Recurring work should be created by the harness, not remembered by the model
s13-Agent Team Runtime¶
1.Lead先提出团队,再等待用户确认¶
2.每个队友拥有独立循环¶
subagent是一次性调用,队友则是持久执行单元
3.MessageBus把通信放在模型上下文之外¶
Lead和队友不能共享一个message数组。
4.收件箱事件由运行时投递¶
5.结果与IDLE是两个事件¶
就是说,一个队友干完之后会发送干完了和等待工作两条消息
6.IDLE先看收件箱,再找ready task¶
队友进入IDLE先处理消息,再检查共享任务板
7.发现和认领分成两步,认领必须原子执行¶
8.认领后的工作复用同一个WORK循环¶
9.由任务选择工具的工作目录¶
选择worktree或在主目录
10.worktree的移除由宿主负责¶
11.控制消息使用类型和request_id¶
12.计划审批会约束执行¶
s14-MCP Tools¶
Lead 和队友目前只能调用直接写在 code.py 里的工具。接入 Jira、部署平台或知识库时,Harness 还要为每个外部系统分别编写工具定义和调用逻辑;外部系统增加或修改工具,也要跟着修改课程代码。
s14 MCP Tools → 通过统一的发现与调用协议,在运行时连接外部服务并把它们的工具加入工具池。
External services can become agent tools through a standard discovery and call protocal
接入文档系统和部署平台时,我们还可以继续手写 search_docs、deploy_status 和 trigger_deploy,但每增加一个服务,都要重新维护工具定义、参数格式和调用代码。
1.Agentloop不需要改变¶
2.MCPClient保存发现结果和调用入口¶
3.connect_mcp只负责连接和发现¶
4.前缀区分不同server的同名工具¶
5.工具定义和handler一起加入工具池¶
6.权限由宿主配置决定¶
7.工具输入错误留在工具边界内¶
s15-Agent Harness集成¶
多种机制、一个循环。
一个能长期工作的 coding agent 需要同时拥有:
- 工具分发和权限边界
- hooks 扩展点
- todo 计划和任务图
- 技能、记忆、系统 prompt 组装
- 压缩和错误恢复
- 后台任务和 cron 调度
- 团队、协议和 idle 任务认领
- 任务绑定的 worktree
- MCP 外部工具接入
s16-Workflow Runtime¶
有些任务重复一套固定的流程。执行前已经知道步骤和先后关系。这样就可以用workflow写入代码。
s17-Goal Loop¶
是否停止循环由一个独立判断器决定。
1. /goal是一个会话级Stop hook¶
2. 判断器是一次独立的模型调用¶
3.对话记录就是判断依据¶
对话器终究只是一个只读对话的模型,可靠性取决于对话里有没有把关键结果说清楚。
4.好的完成条件要能检查¶
结束状态、验证方式、限制条件
5.没完成就回到同一个循环¶
6.后台任务没有结束时,先不要判断¶
7.自动继续也必须要有出口¶
任何自动机制都不能无限占住一次请求。
停止出口:全局max_turns,stop hook






















