1. 项目概述:当智能体“记错”时,如何让它“回滚”并自我修复?
在构建具备长期记忆能力的智能体(Memory-Augmented Agents)时,我们总会遇到一个令人头疼的问题:智能体基于记忆做出了错误的决策或行动。这就像一个人根据一段模糊甚至错误的回忆,做出了一个糟糕的决定。更棘手的是,在复杂的任务链中,一个早期的错误记忆可能会像多米诺骨牌一样,导致后续一连串的行动都偏离正轨。传统的“重试”或“从头开始”策略在长序列任务中成本极高,而简单的“回滚到上一步”又可能因为忽略了动作间的复杂依赖关系而无效,甚至引发新的错误。
“依赖引导的回滚修复”(Dependency-Guided Rollback Repair)正是为了解决这一核心痛点而生。它不是一个简单的“撤销”按钮,而是一套让智能体能够像经验丰富的工程师进行故障排查一样,精准定位错误源头、理解错误影响范围,并执行最小化、最有效的修正动作的机制。其核心思想在于,智能体的行动序列并非孤立的步骤,而是像程序代码一样,存在数据流和控制流的依赖关系。一个动作的输出(例如,生成的文件路径、计算出的变量值、查询到的数据库ID)可能是后续多个动作的输入。当某个动作因基于错误记忆而失败时,我们必须首先理清:“这个错误到底影响了谁?”
最近在开发者社区频繁出现的“内存访问冲突”(0xc0000005)、“内存不足”(OutOfMemoryError)等错误,虽然表面上是系统资源问题,但其深层逻辑与智能体的记忆-行动纠错有异曲同工之妙。当程序因内存错误崩溃时,优秀的调试器或日志系统不会简单地重启进程,而是会尝试定位引发错误的指令指针(0x%p)和内存地址(0x%p),分析堆栈调用关系(依赖链),从而找到根源——是某个变量越界、指针悬挂,还是资源泄漏?Dependency-Guided Rollback Repair 为智能体赋予的,正是这种“调试”自身行动链的能力。
这个机制特别适合需要多步交互、状态持续累积的复杂任务场景,例如自动化运维(Ansible/Puppet剧本执行)、业务流程自动化(RPA)、对话系统长期一致性维护,以及AI编程助手执行复杂代码生成与修改任务。如果你正在开发或使用这类具有“记忆”和“规划”能力的智能体,并且苦于其偶发的、难以追溯的连贯性错误,那么深入理解并实现这套回滚修复框架,将极大提升智能体的鲁棒性和可信度。
2. 核心思路拆解:为什么是“依赖引导”,而不是简单回滚?
在深入代码之前,我们必须从设计哲学上厘清本方案与朴素回滚的根本区别。这决定了整个架构的走向和最终效果。
2.1 记忆增强型智能体的典型故障模式
首先,我们需要明确智能体为什么会“做错”。对于一个具备记忆模块的智能体,其决策循环通常可以简化为:1)感知当前环境/任务状态;2)从记忆库中检索相关历史信息(记忆);3)结合记忆与当前状态进行规划,产生下一个动作;4)执行动作,观察结果,并将新的经验存入记忆。
故障通常发生在第2和第3步:
- 记忆检索错误:智能体检索到了不相关、过时或被污染的记忆片段。例如,在自动化部署任务中,智能体可能错误地记住了上次测试环境的配置文件路径,并将其用于生产环境。
- 记忆推理错误:即使记忆本身正确,智能体在规划时也可能错误地解读或应用了该记忆。例如,记忆显示“服务A依赖于服务B的端口8080”,但智能体却错误地尝试去连接服务B的端口8081。
当错误动作被执行后,系统会进入一个非预期的状态。此时,如果我们只是命令智能体“退回一步并重试”,但导致错误的那段错误记忆依然存在于它的上下文中,那么重试很可能再次失败,或者以一种不同的方式失败。
2.2 依赖关系的捕获与建模
“依赖引导”的精髓在于对动作间依赖关系的显式建模。每个动作(Action)可以被视为一个函数:Action_i: (State_{i-1}, Memory) -> (State_i, Output_i)。
- State(状态):执行环境在某一时刻的快照,可能包括文件系统状态、数据库记录、运行中的进程、环境变量等。
- Output(输出):该动作执行后产生的特定数据产物,如生成的文件内容、返回的API响应、计算出的关键值等。
依赖关系就体现在:Action_j的输入可能依赖于Action_i产生的State_i的某个子集或Output_i。例如:
Action_1: “创建配置文件/app/config.yaml”。Action_2: “读取/app/config.yaml并解析数据库连接字符串”。- 这里,
Action_2直接依赖于Action_1产生的文件系统状态(/app/config.yaml文件的存在与内容)。
我们可以通过几种方式捕获这种依赖:
- 静态声明:在动作定义时,显式声明其输入和输出资源。这需要严谨的设计,但最为精确。
- 动态追踪:在动作运行时,通过钩子(hook)或包装器监控其对系统资源的访问(如文件读写、网络请求、API调用),自动推断依赖。这类似于“系统调用追踪”。
- 基于LLM的推断:对于由大语言模型生成的自然语言指令或代码片段,可以通过分析指令文本,推断其可能访问的资源。例如,指令“读取刚才生成的那个日志文件”暗示了对上一个动作输出的依赖。
一个实用的混合策略是:对于已知的、关键的动作类型采用静态声明;对于未知或动态生成的动作,辅以轻量级的动态追踪或LLM推断进行补充。
2.3 回滚修复的三阶段流程
基于依赖关系,回滚修复流程可以清晰地分为三个阶段:
故障检测与根因定位:当动作
Action_k失败时(抛出异常、返回错误码、结果验证失败),系统首先将其标记为“故障点”。然后,逆向遍历依赖图,分析是哪些前置动作的哪个输出(或记忆检索结果)直接或间接导致了本次失败。目标是找到第一个引入错误信息的“源头动作”(Root Action)。这可能就是Action_k本身(规划错误),也可能是更早的某个Action_m(其输出是错误的),甚至是记忆检索模块(提供了错误记忆)。影响范围分析:定位到源头后,正向遍历依赖图,从源头动作开始,分析所有直接或间接依赖于该错误输出的后续动作。这些动作构成了“污染区”。这些动作可能已经执行成功,但它们是建立在错误的基础上的,其结果不可信。例如,如果
Action_1创建的配置文件内容是错的,那么依赖此文件的所有后续动作(Action_2,Action_3...)即使当时执行成功,其实际效果也是错误的。最小化修复执行:修复的目标不是重启整个任务,而是执行一个最小化的操作集合,使系统能从一个一致且正确的状态继续执行。这通常包括:
- 回滚(Rollback):对“污染区”内已执行的动作,执行其逆操作(如果存在且安全),或将相关状态恢复到执行前的快照。对于文件,可能是删除或还原;对于数据库,可能是执行补偿事务。
- 修复(Repair):纠正“源头动作”。这可能涉及:a) 清除或更正导致错误的记忆条目;b) 用正确的参数重新执行
Action_m;c) 如果错误源于规划,则重新规划Action_k。 - 重试(Retry):从修复后的源头开始,重新执行“污染区”内被回滚的动作,以及原本失败的动作
Action_k。
这个流程确保了修复的精准性,避免了“一刀切”式重启带来的不必要开销。
3. 系统架构与核心组件设计
要将上述思路落地,我们需要设计几个核心组件。这里以一个面向自动化运维的智能体为例,阐述一个可参考的架构。
3.1 动作执行器与状态追踪器
这是系统的基础设施。每个动作的执行必须被包裹在一个可追踪的单元内。
class Action: def __init__(self, id, command, expected_output_schema=None): self.id = id self.command = command # 可以是shell命令、API调用、函数等 self.dependencies = [] # 依赖的其他Action ID self.outputs = {} # 执行后记录的输出 self.state_snapshot_before = None self.state_snapshot_after = None class StateTracker: def __init__(self): self.current_state = {} # 关键状态标识,如 {‘file:/etc/app.conf’: ‘md5_xxx’, ‘process:nginx’: ‘running’} def take_snapshot(self): """捕获当前关键状态快照""" import hashlib snapshot = {} # 示例:记录关键文件的哈希 for key in [‘file:/etc/app.conf’, ‘file:/app/config.yaml’]: if os.path.exists(key[5:]): with open(key[5:], ‘rb’) as f: snapshot[key] = hashlib.md5(f.read()).hexdigest() # 记录服务状态 snapshot[‘service:mysql’] = self._check_service(‘mysql’) return snapshot def register_action(self, action: Action): action.state_snapshot_before = self.take_snapshot() # 执行action.command... result = self._execute(action.command) action.outputs = self._extract_outputs(result) # 解析输出 action.state_snapshot_after = self.take_snapshot() # **关键:自动推断依赖变更** self._update_dependencies(action) return result def _update_dependencies(self, action: Action): """对比前后快照,推断本动作修改了哪些资源,后续动作可据此建立依赖""" changed_resources = [] for key in action.state_snapshot_before: if action.state_snapshot_before.get(key) != action.state_snapshot_after.get(key): changed_resources.append(key) action.modified_resources = changed_resources注意:状态追踪的粒度是需要权衡的。追踪过细(如每个文件字节)性能开销大;追踪过粗(如只记录动作是否成功)则依赖分析不精确。通常建议追踪任务领域的核心资源(如配置文件、数据库表、服务端口)。
3.2 依赖图管理器
这个组件负责维护动作之间的依赖关系图(DAG)。它需要在动作执行时动态构建这个图。
import networkx as nx class DependencyGraphManager: def __init__(self): self.graph = nx.DiGraph() # 使用有向图 self.resource_to_last_action = {} # 资源 -> 最后一个修改它的Action ID def add_action(self, action: Action): self.graph.add_node(action.id, action=action) # 基于声明的依赖添加边 for dep_id in action.dependencies: if dep_id in self.graph: self.graph.add_edge(dep_id, action.id) # **动态依赖发现**:基于资源变更自动添加依赖 for resource in action.modified_resources: if resource in self.resource_to_last_action: last_actor = self.resource_to_last_action[resource] if not self.graph.has_edge(last_actor, action.id): self.graph.add_edge(last_actor, action.id) self.resource_to_last_action[resource] = action.id def find_root_cause(self, failed_action_id): """逆向BFS,寻找可能的根因节点""" visited = set() queue = deque([failed_action_id]) potential_roots = [] while queue: current = queue.popleft() if current in visited: continue visited.add(current) predecessors = list(self.graph.predecessors(current)) if not predecessors: # 没有前驱,可能是规划起点或记忆输入点 potential_roots.append(current) else: queue.extend(predecessors) return potential_roots # 可能多个,需要结合故障信息进一步分析 def get_affected_actions(self, root_action_id): """正向BFS,获取所有受影响的后续动作""" affected = [] for node in nx.descendants(self.graph, root_action_id): affected.append(node) return affected3.3 记忆管理器与错误记忆诊断
记忆模块是错误的重要来源。我们需要一个能支持诊断和修复的记忆系统。
class MemoryManager: def __init__(self, vector_store): self.vector_store = vector_store # 用于相似性检索 self.memory_entries = [] # 列表,存储带元数据的记忆 self.access_log = [] # 记录每次检索的上下文和结果 def retrieve(self, query, context): """检索记忆,并记录审计日志""" results = self.vector_store.similarity_search(query, k=3) self.access_log.append({ ‘timestamp’: time.time(), ‘context’: context, # 当时在做什么任务 ‘query’: query, ‘retrieved_ids’: [r.id for r in results] }) return results def diagnose_memory_fault(self, failed_action_id, action_context): """分析在失败动作执行前,是否检索到了错误或无关的记忆""" relevant_logs = [log for log in self.access_log if log[‘context’] == action_context] if not relevant_logs: return None last_retrieval = relevant_logs[-1] retrieved_memories = self._get_entries_by_ids(last_retrieval[‘retrieved_ids’]) # 诊断逻辑示例:1. 记忆是否过时? 2. 记忆与当前任务是否真的相关? fault = None for mem in retrieved_memories: if self._is_outdated(mem): fault = {‘type’: ‘outdated’, ‘memory_id’: mem.id, ‘action’: failed_action_id} break if not self._is_relevant(mem, action_context): fault = {‘type’: ‘irrelevant’, ‘memory_id’: mem.id, ‘action’: failed_action_id} break return fault def repair_memory(self, fault): """根据诊断结果修复记忆""" if fault[‘type’] == ‘outdated’: # 标记为过时,降低其检索优先级或归档 self._deprecate_memory(fault[‘memory_id’]) elif fault[‘type’] == ‘irrelevant’: # 可能是嵌入模型或查询问题,暂时无法自动修复,可加入人工审核队列 self._flag_for_review(fault[‘memory_id’]) # 触发重新规划:清除与失败动作相关的缓存,迫使智能体重新检索 self._invalidate_cache_for_action(fault[‘action’])3.4 回滚修复执行引擎
这是协调整个修复流程的“大脑”。
class RollbackRepairEngine: def __init__(self, state_tracker, dep_graph, memory_manager): self.state_tracker = state_tracker self.dep_graph = dep_graph self.memory_manager = memory_manager self.rollback_strategies = {} # 注册不同资源类型的回滚策略 def handle_failure(self, failed_action_id: str, error_info: dict): print(f“[Repair Engine] 处理失败动作: {failed_action_id}, 错误: {error_info}”) # 阶段1: 根因分析 potential_roots = self.dep_graph.find_root_cause(failed_action_id) root_cause = None for root_id in potential_roots: action = self.dep_graph.get_action(root_id) # 分析1: 是否是记忆错误? mem_fault = self.memory_manager.diagnose_memory_fault(root_id, action.context) if mem_fault: root_cause = {‘type’: ‘memory’, ‘action_id’: root_id, ‘fault’: mem_fault} break # 分析2: 是否是动作自身执行错误(参数错误、环境问题)? if root_id == failed_action_id or self._is_action_execution_error(action, error_info): root_cause = {‘type’: ‘execution’, ‘action_id’: root_id} break # 分析3: 是否是前置动作输出错误? if self._is_input_corrupted(action): root_cause = {‘type’: ‘propagation’, ‘action_id’: root_id} break if not root_cause: root_cause = {‘type’: ‘unknown’, ‘action_id’: failed_action_id} # 阶段2: 影响范围分析 affected_actions = self.dep_graph.get_affected_actions(root_cause[‘action_id’]) print(f“ 根因类型: {root_cause[‘type’]}, 源头动作: {root_cause[‘action_id’]}, 影响动作数: {len(affected_actions)}”) # 阶段3: 制定并执行修复计划 repair_plan = self._create_repair_plan(root_cause, affected_actions) self._execute_repair_plan(repair_plan) # 修复后,通知调度器从合适的点重新开始 return self._get_resume_point(repair_plan) def _create_repair_plan(self, root_cause, affected_actions): plan = {‘rollbacks’: [], ‘repairs’: [], ‘retries’: []} # 1. 回滚受影响的动作 for action_id in affected_actions: action = self.dep_graph.get_action(action_id) rollback_cmd = self._generate_rollback_command(action) if rollback_cmd: plan[‘rollbacks’].append({‘action_id’: action_id, ‘command’: rollback_cmd}) # 2. 修复根因 if root_cause[‘type’] == ‘memory’: plan[‘repairs’].append({‘type’: ‘memory_correction’, ‘fault’: root_cause[‘fault’]}) # 修复后,需要重新执行源头动作(因为其决策依据变了) plan[‘retries’].append(root_cause[‘action_id’]) elif root_cause[‘type’] == ‘execution’: # 可能是参数错误,重新规划该动作 plan[‘repairs’].append({‘type’: ‘replan_action’, ‘action_id’: root_cause[‘action_id’]}) plan[‘retries’].append(root_cause[‘action_id’]) elif root_cause[‘type’] == ‘propagation’: # 需要修复源头动作的输出,然后重试它 plan[‘repairs’].append({‘type’: ‘fix_output’, ‘action_id’: root_cause[‘action_id’]}) plan[‘retries’].append(root_cause[‘action_id’]) # 3. 重试被回滚的动作以及原失败动作 plan[‘retries’].extend(affected_actions) # 重试受影响动作 if failed_action_id not in plan[‘retries’]: plan[‘retries’].append(failed_action_id) # 去重并排序,确保执行顺序符合依赖 plan[‘retries’] = self._topological_sort_retries(plan[‘retries’]) return plan def _execute_repair_plan(self, plan): # 执行回滚 for job in plan[‘rollbacks’]: print(f“ 执行回滚: {job[‘action_id’]}”) self.state_tracker.execute(job[‘command’]) # 执行回滚命令 # 执行修复 for fix in plan[‘repairs’]: if fix[‘type’] == ‘memory_correction’: self.memory_manager.repair_memory(fix[‘fault’]) # ... 其他修复类型 # 注意:重试动作由外部调度器根据返回的 resume_point 触发4. 实战案例:一个自动化部署故障的修复全流程
让我们通过一个具体的场景,将上述组件串联起来,看整个系统如何工作。
场景:一个智能运维Agent需要为一个Web应用部署更新。任务序列如下:
A1: 从记忆库检索生产环境数据库连接字符串(记忆:上次部署成功的连接串)。A2: 使用该连接串,备份当前数据库。A3: 从版本库拉取最新应用代码。A4: 修改应用配置文件config.yaml,填入数据库连接串。A5: 重启应用服务。
故障发生:A5重启失败,日志显示“数据库连接失败”。
4.1 故障处理流程推演
故障检测:
A5返回错误码,RollbackRepairEngine.handle_failure(‘A5’, error_log)被调用。根因定位:
- 引擎逆向分析依赖图:
A5依赖A4(因为A4修改了配置文件),A4依赖A1(因为A4需要数据库连接串)。 - 检查
A1:MemoryManager通过审计日志发现,A1检索记忆时使用的查询是“生产环境数据库连接串”,但返回的记忆条目其元数据标签却是“测试环境”。诊断结果:根因为记忆错误(irrelevant),源头动作是A1。
- 引擎逆向分析依赖图:
影响范围分析:
- 正向遍历:依赖于
A1输出的动作有A2(备份了错误的数据库?)、A4(配置文件写入了错误的连接串)。A3不依赖A1,不受影响。 - 污染区:
A2,A4,A5。
- 正向遍历:依赖于
制定修复计划:
- 回滚:生成并执行
A4的回滚命令(将config.yaml恢复至A4执行前的备份或版本)。A2的回滚可能比较复杂(需要删除错误的备份文件),但在此场景下,一个错误的备份文件可以暂时保留并标记,不作为回滚重点。A5无需回滚,因为它执行失败了。 - 修复:
MemoryManager将那条标签错误的记忆条目标记为“待审核”或降权。同时,触发系统重新规划A1的动作——可能需要换一个更精确的查询,或从可信源(如密钥管理系统)直接获取连接串。 - 重试:计划重试
A1(修复后)、A2、A4、A5。执行顺序需遵循依赖:先A1,然后A2和A4可以并行(如果资源不冲突),最后A5。
- 回滚:生成并执行
执行与恢复:
- 引擎首先回滚
A4,配置文件被还原。 - 记忆被修复/标记。
- 调度器从
A1开始重新执行:A1’(重新检索或从可信源获取正确连接串)->A2’(用正确连接串备份)->A4’(用正确连接串更新配置)->A5’(重启服务)。A3由于不受影响,其成果(拉取的代码)被保留,无需重复执行。
- 引擎首先回滚
4.2 关键配置与参数考量
在实际实现中,以下几个参数和策略需要仔细调优:
- 状态追踪粒度:在我们的案例中,追踪了
config.yaml文件的MD5。对于数据库,可能需要追踪关键表的行数或某个校验和。粒度越细,依赖分析越准,但开销越大。 - 依赖推断的启发式规则:除了资源修改,还可以考虑“时间邻近性”和“语义相似性”作为弱依赖信号。例如,短时间内连续执行的两个操作,即使没有明确的资源依赖,也可能存在逻辑顺序。
- 回滚策略注册表:不是所有操作都可逆。需要为不同类型的操作(文件写入、数据库插入、服务启动)预定义或学习其回滚命令。对于不可逆或高风险操作,修复计划可能选择“创建修复补丁”而非“回滚”。
- 修复的激进程度:
repair_aggressiveness参数可以控制。保守模式可能只回滚直接导致失败的动作;激进模式则会回滚整个污染区。需要在安全性和效率间权衡。 - 记忆诊断的置信度阈值:如何判定一条记忆是“错误”的?可能需要结合多个信号:检索相似度分数、记忆的创建时间、被成功使用的历史次数、与其他记忆的一致性等。
5. 常见问题、挑战与优化策略实录
在实际开发和测试这类系统时,会遇到许多预料之外的问题。以下是我从几个原型系统实践中总结出的经验与避坑指南。
5.1 依赖误报与漏报
这是最核心的挑战。动态追踪不可能完美。
- 问题:动作通过全局变量、环境变量或未监控的临时文件传递信息,导致依赖关系漏报。例如,
A1设置了一个环境变量EXPORT DB_HOST=192.168.1.100,A2读取了这个变量。如果状态追踪器只监控文件,就会漏掉这个依赖。 - 解决策略:
- 混合方法:核心依赖通过动作定义时静态声明。对于脚本类动作,可以要求开发者使用特定的“输出声明”语法(如
::set-output name=db_host::$DB_HOST)。 - 沙盒环境:在受控的沙盒或容器中运行动作,可以更彻底地监控系统调用(如
ptrace),但会带来显著的性能开销和复杂性,仅适用于对可靠性要求极高的场景。 - 容忍不确定性:接受依赖图可能不完整。当修复引擎无法确定依赖时,可以采取更保守的策略,例如回滚到上一个已知的、完好的全局检查点(Checkpoint)。
- 混合方法:核心依赖通过动作定义时静态声明。对于脚本类动作,可以要求开发者使用特定的“输出声明”语法(如
5.2 非幂等操作与副作用管理
许多操作不是幂等的,执行两次可能导致错误或资源浪费。
- 问题:
A1是“向用户发送通知邮件”。回滚时无法“取消发送”。重试A1会导致用户收到重复邮件。 - 解决策略:
- 标记与跳过:为这类动作打上
non_idempotent标签。在重试阶段,如果检测到该动作在污染区内且已执行成功过一次,则跳过其重试,并记录一条警告。这要求系统能准确判断一个动作“是否已成功执行过”。 - 补偿事务:设计一个补偿动作
A1_compensate,例如“发送一封澄清邮件”。但这通常业务逻辑复杂。 - 人工介入点:将涉及外部系统、不可逆操作的动作设置为“关键点”,失败时暂停流程并请求人工决策。
- 标记与跳过:为这类动作打上
5.3 修复过程中的新故障
修复行动本身可能失败。
- 问题:回滚命令
rm -f /tmp/backup.tar执行时,文件可能已被其他进程锁定或不存在,导致回滚失败。 - 解决策略:
- 回滚操作的鲁棒性设计:回滚命令需要比原始命令更加强壮。例如,使用
rm -f而不是rm,忽略不存在的文件。对于数据库回滚,使用事务。 - 分层修复与检查点:修复计划应分步执行,每步之后验证状态。如果某步回滚失败,系统应能回退到上一步,而不是陷入更混乱的状态。考虑在修复开始前创建一个新的系统快照作为“修复检查点”。
- 定义终极回退方案:当自动修复失败时,明确一个终极回退方案,例如“还原整个虚拟机快照”或“切换到灾备环境”。这定义了系统可靠性的底线。
- 回滚操作的鲁棒性设计:回滚命令需要比原始命令更加强壮。例如,使用
5.4 性能开销与复杂度平衡
全面的依赖追踪和状态管理是有成本的。
- 问题:每个动作前后都进行完整的状态快照(如计算所有文件的哈希)会使任务执行速度慢数倍。
- 优化策略:
- 增量式快照:只记录被监控资源的变化部分,而不是全部重新计算。
- 抽样与摘要:对于大型文件或数据库,不记录完整内容,而是记录其大小、修改时间、或关键部分的校验和。
- 按需启用:不是所有任务都需要高强度的回滚修复。可以为任务设置“可靠性等级”,低等级任务只进行最基本的日志记录,高等级任务才开启全量依赖追踪。
- 异步分析:依赖图的构建和分析可以异步进行,不影响主任务执行流水线。只有在故障发生时,才同步执行修复分析。
5.5 与现有智能体框架的集成
如何将这套机制嵌入到 LangChain、AutoGPT 或自定义的智能体框架中?
- 建议路径:
- 包装执行层:不修改智能体核心的规划和记忆逻辑,而是包装其“动作执行”模块。每当智能体调用一个工具(Tool)或执行一个命令时,都通过我们的
StateTracker和DependencyGraphManager。 - 注入记忆检索:通过装饰器或中间件模式,在智能体调用记忆检索函数前后加入审计日志记录。
- 钩入异常处理:框架通常有全局异常处理器。在其中捕获动作执行异常,然后调用我们的
RollbackRepairEngine.handle_failure()。 - 提供修复回调:修复引擎在计算出重试起点后,应能回调智能体的调度器,告诉它“请从动作X开始重新规划/执行”。
- 包装执行层:不修改智能体核心的规划和记忆逻辑,而是包装其“动作执行”模块。每当智能体调用一个工具(Tool)或执行一个命令时,都通过我们的
这套机制的本质,是为智能体增加了一个具备“元认知”能力的纠错层。它让智能体不仅能行动,还能观察自己的行动链,诊断其中的故障,并进行有针对性的修正。这离我们期望的、真正稳健可靠的自主智能系统,又近了一步。