//文章为题主学习Claude code设计架构时所写
要落地一个agent项目,并不是一个loop就可以,需要考虑的设计点非常多且复杂,这里举几个例子:
问题1:如果用户在agent输出或运行工具时,ctrl + c后 应该怎么处理?直接断开会造成内存状态全部清除。
问题2:如果agent调用进入死循环怎么处理?处理不当会导致费用爆炸。
这一章主要讲解我学习到的 Claude code 主循环设计哲学:
如何理解一次 Turn,从用户输入问题 -> 大模型思考 -> 大模型调用工具 -> 大模型生成最终结果,这算是一次 Turn。我会从四点介绍Claude code 主循环设计:
一. Claude code 在每一轮 Turn 之前都会重置状态
这里重置什么状态?打断记录器 , 权限拒绝清单 , 临时技能 。
先说打断记录器 , Claude code 会在内存中存储一个打断记录器,如果用户ctrl + c 打断当前轮次 , 这个记录器的值会变为 true。
权限拒绝清单。这是个什么东西?其实就是平时大家在 同意或拒绝 Claude code 一些指令时候的 记录清单。是的 , Claude code每一轮 也会把这些记录下来 。 如果不重置会发生什么?比如你再第一轮拒绝了Claude code 一条指令请求 , 在第二轮任务完成之后,还保存这上一轮的 权限拒绝清单 , 那么Claude code 会把权限拒绝清单发送到ui层,导致整个 日志系统的混乱。
临时技能清单。Claude code 内部会记录一个set集合,存储每一轮探索到的skill,用于本轮的使用,不清除会导致set内存泄漏。
二.Claude code 的 切面体系
Claude code 在调用大模型前,后 , 循环停止前 ,后 具有丰富的切面编程思想。
- 前置检查:Claude code 会检查环境变量,所挂在的工作目录。
- 后置检查:在Claude code 将要返回文本时,会先检查 是否包含不合法格式或死锁迹象。
- 循环即将停止:Claude code 会检查 后台任务,及时让大模型调整或补充。
三.Claude code 打断机制
回看问题1
打断时机具体可以分为两类:当大模型返回最终输出时候 , 当大模型调用工具时候.
- 当大模型返回输出消息时,这时后台在疯狂打字.此时会做出许多操作:瞬间掐断 和大模型服务的sse连接,保护用户账单,此时一半的输出仍会保存在上下文中 , 并会在末尾插上一句话[用户在此处打断操作], 下次大模型仍会看懂.
- 当大模型调用工具时打断.我们知道一个tool_call 必然对应着一个tool_result , 如果tool_result不完整,会导致下次请求报400错误.那么 Claude code 在后台会 '假写' 一个tool_result , 内容就是"用户当前不想执行此操作。停止你正在做的事情,等待用户的新指示。"
四.Claude code 资源计算和死循环防止
在来看看问题2
- 单轮最大循环次数:防止死循环。
- 最大预算:哪怕轮次没超,一旦当前会话消耗的 Token 换算成金额超过预设门槛,护具会立刻拔掉电源线,强制终止循环并向用户报警。
——————————————————2026.9.27补——————————————————
在我看来 所有agent 的关键点就在agent loop 上,所有组件都可以插入到loop上,所以其实可以将agent loop分为四个阶段:
- 调用大模型之前
- 调用大模型之后 与 执行工具前
- 执行工具之后
- loop结束之后
学习一个agent 架构,都可以把这四个阶段作为切入点。
这里我就大致说一下Claude code在这四个阶段都干了什么,详细可以等题主更新(
一.调用大模型之前
可以分为六步:
- 判断用户输出:判断是否又"/" "!" "@ "这些命令符,如果有直接进入相对于的逻辑处理.
- 状态清洗和预写日志:状态清洗在上文已经详细展开过了 , 预写日志 把用户的问题直接追加写到磁盘持久化的jsonl文件中,防止中断恢复后agent混乱.
- 抓取项目数据:抓取项目配置的专属技能,如果有git,查询git分支,状态,代码总行数等等数据.
- Token估算与紧急压缩:Claude code 会将"系统提示词 + 长期记忆 + 当前上下文 + 用户问题"估算Token , 保证Token不超预算,否则触发四层压缩机制
- 拼装提示词:这里的提示词拼接大有讲究,我们在上下文管理篇章中讲解.
- 包装JSON:将提示词和上下文包装成JSON,正式发送给模型服务端,这里设置了随机抖动的重连机制,在后台静默重试.
二.调用大模型之后 与 执行工具前
可以分为五步:
- 增量拼接tool_call:因为我们与模型服务端是流式模式,所以需要边接收边拼接,如果json格式不对,这里直接捕获并处理.
- 工具参数检验:检验是否存在这个工具,是不是按要求传了全部参数.
- 工具动态编排:来了四个工具 三个读 一个写,三个读工具可以并行,写工具需要串行,加快处理速度.
- 权限,工具安全性检验:检验目标目录是否合法,防止agent越界.对于一下终端或代码脚本,需要检验其安全性是否能通行.
- 人工审查:对于上一步不安全的工具,在ui层上用户决定是否执行.
三.调用工具之后
可以分为五步:
- 工具信息整合:工具格式必须合法,必须有tool_call_id,一个tool_call对应一个tool_result,如果一个工具结果过长,需要截取并输出工具执行完整临时文件.
- 上下文更新:因为有些工具是并行执行的,它们更改状态必须是串行的,需要按顺序将这些并行的上下文进行更新.
- 后台消息检测:检测用户是否有新消息输入,检查后台慢终端命令执行情况.
- 增量异步落盘:将工具的调用和结果异步的持久化到jsonl文件中.
- 进入下一轮:判断直接结束还是进入下一轮循环.
四.结束后
可以分为五步:
- 清空内存:强制将内存中存留的日志,上下文各种信息,持久化到磁盘
- 结算账单:计算本轮消耗的Token,在ui层展示给用户.
- 执行hook:执行用户自定义hook,比如自动提交git等等
- 提取长期记忆:整合,去重长期记忆.
- 信箱信息检测:检测信箱中是否有用户的信息(这个信息是在大模型输出最终答案时,用户所添加的) 如果有直接无缝衔接到下一轮