ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Agent Zero 用户干预消息模板解析:fw.intervention.md 的机制、结构与源码实现

Agent Zero 用户干预消息模板解析:fw.intervention.md 的机制、结构与源码实现 Agent Zero 用户干预消息模板解析fw.intervention.md 的机制、结构与源码实现【免费下载链接】agent-zeroAgent Zero AI framework项目地址: https://gitcode.com/GitHub_Trending/ag/agent-zero导读fw.intervention.md是 Agent Zero AI 框架位于仓库根目录 prompts/fw.intervention.md中专门用于承载用户干预user intervention消息的 JSON 提示模板。当用户在一个正在运行的 Agent 对话中途插入新指令例如纠正、追加需求或紧急叫停当前操作时框架不会把它当作普通用户消息处理而是通过该模板将其包装成带有明确user_intervention标记的结构化消息写入历史记录。读完本文你将理解该模板的字段含义、它与普通用户消息模板 prompts/fw.user_message.md 的差异、模板在 agent.py 中的完整装配流程以及干预消息如何借助InterventionException中断当前任务循环。一、模板文件本体一个三字段的 JSON 骨架fw.intervention.md的完整内容非常精简全文就是一个被代码围栏包裹的 JSON 模板{ system_message: {{system_message}}, user_intervention: {{message}}, attachments: {{attachments}} }它定义了三个占位字段每个字段都由双花括号变量在运行时被实际内容替换字段占位符含义system_message{{system_message}}干预发生时携带的系统级消息/提示可能为空user_intervention{{message}}用户输入的实际干预文本即用户中途插入的那条指令attachments{{attachments}}随干预消息附带的多媒体附件列表可能为空需要注意的关键设计干预消息在历史记录中的字段名是user_intervention而不是普通用户消息的user_message。这一点在与 prompts/fw.user_message.md 的对比中尤为明显{ system_message: {{system_message}}, user_message: {{message}}, attachments: {{attachments}} }两份模板结构几乎一致唯一的本质区别就是第二个字段名。这种刻意设计的字段命名差异使得 LLM 在读取上下文时能够一眼区分普通用户输入与执行过程中的用户干预从而对干预指令给予更高优先级——因为干预通常意味着 Agent 当前的行为方向需要被纠正或打断。二、模板的装配流程从干预消息到历史记录fw.intervention.md并不是被直接拼接进上下文的静态文本而是由 Agent 的核心历史写入方法动态渲染。该逻辑位于 agent.py 的hist_add_user_message方法约第 728-755 行extension.extensible def hist_add_user_message(self, message: UserMessage, intervention: bool False): self.history.new_topic() # user message starts a new topic in history # load message template based on intervention if intervention: content self.parse_prompt( fw.intervention.md, messagemessage.message, attachmentsmessage.attachments, system_messagemessage.system_message, ) else: content self.parse_prompt( fw.user_message.md, messagemessage.message, attachmentsmessage.attachments, system_messagemessage.system_message, ) # remove empty parts from template if isinstance(content, dict): content {k: v for k, v in content.items() if v} # add to history msg self.hist_add_message(False, contentcontent, idmessage.id) # type: ignore self.last_user_message msg return msg这段代码揭示了完整的装配链路新话题分隔self.history.new_topic()在调用前被触发用户消息无论是否干预都会在历史中开启一个新话题topic确保上下文分段清晰。模板分流通过intervention: bool False布尔参数决定加载fw.intervention.md还是fw.user_message.md。该参数默认值为False只有干预场景显式传入True。参数注入parse_prompt将message.message、message.attachments、message.system_message三个运行时值注入模板占位符。这三个值恰好对应UserMessage数据类的三个核心字段定义于 agent.py 第 327-332 行dataclass class UserMessage: message: str attachments: list[str] field(default_factorylist[str]) system_message: list[str] field(default_factorylist[str]) id: str 空字段清理content {k: v for k, v in content.items() if v}会剔除值为空的字段例如没有附件或没有 system_message 时避免向 LLM 传递冗余空值。写入历史hist_add_message(False, contentcontent, idmessage.id)将渲染后的消息以非 AI 消息身份写入历史并记录到self.last_user_message。parse_prompt本身定义于 agent.py 第 681-688 行它通过files.parse_file完成模板解析并支持扩展点extension.extensible允许插件层覆盖模板加载行为。而模板文件若被判定为完整 JSON 模板files.is_full_json_template实现见 helpers/files.py则会先经files.remove_code_fenceshelpers/files.py剥除外层 json 代码围栏再使用——这正是fw.intervention.md全文带围栏的原因围栏仅服务于文件存储与展示运行时会被自动剥离。三、干预的触发用户如何在运行中插话模板本身只是数据结构真正让fw.intervention.md生效的是干预消息的投递机制。入口在AgentContext.communicate方法agent.py 第 259-277 行extension.extensible def communicate(self, msg: UserMessage, broadcast_level: int 1): self.paused False # unpause if paused current_agent self.get_agent() if self.task and self.task.is_alive(): # set intervention messages to agent(s): intervention_agent current_agent while intervention_agent and broadcast_level ! 0: intervention_agent.intervention msg broadcast_level - 1 intervention_agent intervention_agent.data.get( Agent.DATA_NAME_SUPERIOR, None ) else: self.task self.run_task(self._process_chain, current_agent, msg) return self.task这里区分了两种截然不同的场景Agent 空闲self.task不存在或已结束消息通过_process_chain作为新的普通用户消息启动一轮全新对话。Agent 正在运行self.task.is_alive()为真消息不会进入普通队列而是被写入当前正在流式输出的 Agent 的intervention属性。broadcast_level参数控制干预沿上级链传播的层级从当前 Agent 开始通过DATA_NAME_SUPERIOR逐级向上如存在子 Agent 层级每一级都会把同一份干预消息挂载到其intervention槽位直到broadcast_level递减到 0 或没有更上级 Agent。intervention槽位在Agent.__init__中初始化agent.py 第 381 行self.intervention: UserMessage | None None并在每次干预处理完成后被重置为None。四、干预的处理handle_intervention与异常中断挂载到intervention槽位的消息最终由Agent.handle_intervention方法消费agent.py 第 1070-1089 行extension.extensible async def handle_intervention(self, progress: str ): await self.wait_if_paused() if ( self.intervention ): # if there is an intervention message, but not yet processed msg self.intervention self.intervention None # reset the intervention message # If a tool was running, save its progress to history last_tool self.loop_data.current_tool if last_tool: tool_progress last_tool.progress.strip() if tool_progress: self.hist_add_tool_result(last_tool.name, tool_progress) last_tool.set_progress(None) if progress.strip(): self.hist_add_ai_response(progress) # append the intervention message self.hist_add_user_message(msg, interventionTrue) raise InterventionException(msg)处理流程包含五个关键步骤等待解除暂停wait_if_paused()确保在会话未暂停状态下处理干预。取出并清空槽位读取self.intervention后立即置None保证同一干预只被处理一次。保留工具运行进度如果干预发生时某个工具正在执行其progress文本会被以工具结果hist_add_tool_result的形式先写入历史防止中断导致已产出的中间结果丢失。写入干预消息调用hist_add_user_message(msg, interventionTrue)——这正是上一节中fw.intervention.md模板被装配的位置。抛出InterventionException中断当前消息循环迭代让控制权立刻交还给上层调度使新干预指令尽快进入下一次 LLM 调用。InterventionException定义于 helpers/errors.py其文档字符串清楚地说明了用途An exception type raised on user intervention, skipping rest of message loop iteration.用户干预时抛出的异常类型用于跳过消息循环迭代的剩余部分。此外AgentContext.nudgeagent.py 第 245-250 行展示了另一种形态的干预它通过kill_process()强制结束当前任务并以fw.msg_nudge.md模板见 prompts/fw.msg_nudge.md重新发起一次催促通信用于让停滞的 Agent 重新动起来。这与fw.intervention.md的插入式干预形成互补nudge 属于强制重启式催促而 intervention 属于原地插话式纠正。五、从源码验证干预字段语义干预消息在历史中的字段名user_intervention并非只被模板使用它同时也是框架内部代码识别的语义标记。在聊天命名插件 plugins/_chat_naming/helpers/naming.py 中可以看到该插件提取消息主题时会同时检查user_message与user_intervention两个键说明干预消息会被视为与普通用户消息同等级别的用户发言参与主题推导for key in (user_message, user_intervention):其测试用例 plugins/_chat_naming/tests/test_chat_naming.py 也以_Message({user_intervention: Okay, do it}, sequence4)的形式构造了干预消息样本验证干预消息能被正确识别与处理。同时测试套件 tests/test_responses_architecture.py 中出现了agent.intervention None重置干预槽位与agent.handle_intervention no_intervention替换处理函数的写法说明干预机制在设计上预留了测试与扩展的替换点handle_intervention是可被插件覆盖的扩展方法。六、自定义与扩展建议由于parse_prompt、hist_add_user_message、handle_intervention均标注了extension.extensible插件开发者可以针对干预链路做三类定制改写模板通过扩展覆盖parse_prompt对fw.intervention.md的解析或在 Agent 的 prompts 目录参见 agents/default/agent.yaml 的 prompt 目录配置机制中放置同名文件覆盖默认模板为干预消息增加额外字段如干预原因、优先级权重。改变历史写入形态覆盖hist_add_user_message在interventionTrue分支对渲染结果做后处理例如追加时间戳或上下文快照。改变中断行为覆盖handle_intervention在抛出InterventionException前执行自定义清理逻辑例如保存检查点、通知上级 Agent。结语fw.intervention.md虽然只有三行 JSON却是 Agent Zero 干预机制的数据契约核心它以user_intervention字段在历史中标记用户中断指令配合 agent.py 中的communicate投递、intervention槽位挂载、handle_intervention消费与InterventionException异常中断构成了一个完整且可扩展的运行中插话闭环。理解这份模板就等于理解了 Agent Zero 如何处理真实世界中边说边改的协作方式。【免费下载链接】agent-zeroAgent Zero AI framework项目地址: https://gitcode.com/GitHub_Trending/ag/agent-zero创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表