在claude code源码当中当用户下达任务后会由plan agent进行任务拆解但是当任务复杂并且拆解的任务数量过多时模型非常容易忘记后续的任务因此一个行之有效的方法就是设置一个TodoManager强制让AI大模型将任务转化为todo list然后再调用大模型进行下一步的规划。核心思想LLM绑定工具包括文件读写执行命令编辑文件以及任务更新等使用TodoManager让模型自己管理任务状态待办/进行中/完成模型连续3轮不更新任务- 自动注入提醒全程不写四执行步骤模型自主规划自主推进核心创新点模型自己追踪进度而不是程序硬编码流程nag reminder提醒机制3轮不更新todo就强制提醒同一时间只能有一个任务进行防止模型发生混乱流程分析下面我们来分析一下流程如果超过三次没有调用todo工具则直接在messages中插入一条提醒消息, 并计数归零ifrounds_since_todo3:# 将提醒作为一条独立的 user 消息注入messages.append({role:user,content:reminderUpdate your todos./reminder})# 注意注入提醒后计数器重置为 0 或保持原逻辑没有重置这里保持原样# 提醒只是附加消息不影响计数但为避免无限提醒可以重置 rounds_since_todo 0# 建议根据需求调整以下重置为 0 更合理rounds_since_todo0当大模型接受到这条最新的消息后则会调用todo工具其中todo工具的distpatch map是这么定义的{name:todo,description:Update task list. Track progress on multi-step tasks.,input_schema:{type:object,properties:{items:{type:array,items:{type:object,properties:{id:{type:string},text:{type:string},status:{type:string,enum:[pending,in_progress,completed]}},required:[id,text,status]}}},required:[items]}},从代码中我们可以看出大模型会返回一个items列表该任务列表中会详细列举任务的id,text,状态然后我们看一下当大模型返回todo列表后程序会遍历items, 检查是否所有的to do list是否合法以及当前输入in_progress的任务是否只有一个如果都符合要求则进行render。 将render后的字符串组转成消息发送给大模型进行下一轮的任务。这里提一下render的规则如果是pending任务 渲染成: [ ] #item_id #item[text]如果是in_progress任务 渲染成: [] #item_id #item[text]如果是completed任务 渲染成: [x] #item_id #item[text]defupdate(self,items:list)-str:iflen(items)20:raiseValueError(Max 20 todos allowed)validated[]in_progress_count0fori,iteminenumerate(items):textstr(item.get(text,)).strip()statusstr(item.get(status,pending)).lower()item_idstr(item.get(id,str(i1)))ifnottext:raiseValueError(fItem{item_id}: text required)ifstatusnotin(pending,in_progress,completed):raiseValueError(fItem{item_id}: invalid status {status})ifstatusin_progress:in_progress_count1validated.append({id:item_id,text:text,status:status})ifin_progress_count1:raiseValueError(Only one task can be in_progress at a time)self.itemsvalidatedreturnself.render()//reader函数defrender(self)-str:ifnotself.items:returnNo todos.lines[]foriteminself.items:marker{pending:[ ],in_progress:[],completed:[x]}[item[status]]lines.append(f{marker}#{item[id]}:{item[text]})donesum(1fortinself.itemsift[status]completed)lines.append(f\n({done}/{len(self.items)}completed))return\n.join(lines)