Bugfix/extract non memory fixes#195
Open
niiish32x wants to merge 5 commits into
Open
Conversation
## 问题严重性
Agent 在 Function Calling 模式下会陷入无限循环,LLM 不断重复调用同一个工具
却无法自行跳出。这导致用户请求长时间无响应,只能手动 Ctrl+C 终止进程,
大量无效 LLM 调用消耗 token 和时间。已到了不得不修复的程度。
## 根因
1. **DoomLoopDetector 阻断无效**:react_master_agent 中 doom loop 检测到
重复调用后返回 ActionOutput,但 terminate=False、have_retry=True,
导致 generate_reply 循环继续,LLM 重新发起相同调用,形成"元死循环"
2. **core/agent/base.py 无任何死循环检测**:ProductionAgent 路径完全没有
doom loop 防护,只能靠 max_retry_count(默认3)兜底,但 ReActMasterAgent
设为 300,几乎等于无限制
3. **core_v2 DoomLoopDetector 返回的 ActionResult 无终止信号**:
ReActReasoningAgent.act() 返回 ActionResult(success=False) 但
enhanced_agent.py 主循环不检查 doom loop metadata,继续执行
4. **按工具名计数导致误判**:连续调用 read 读取 5 个不同文件被误判为死循环,
应按 tool_name+args hash 计数,只有相同工具+相同参数才算
## 修复内容
1. **ReActMasterAgent**:doom loop 阻断时设 terminate=True + have_retry=False,
确保 generate_reply 循环立即退出;新增 _last_tool_name/_last_tool_args
追踪最后执行的工具
2. **core_v2 enhanced_agent.py**:主循环新增基于 hash 的连续相同调用检测,
同一工具+同一参数连续调用超过阈值(5次)时强制终止;检查 ActionResult
的 doom_loop metadata 终止信号
3. **core_v2 react_reasoning_agent.py**:doom loop ActionResult 增加
metadata={"doom_loop": True, "terminate": True}
4. **core/agent/base.py (ProductionAgent)**:新增基于 hash 的连续相同调用检测
## 检测算法
采用 tool_name + args hash 作为检测 key(与现有 DoomLoopDetector 一致),
只有连续调用相同工具+相同参数才触发。避免误判合法的连续不同参数调用
(如连续 read 5 个不同文件)。
## 对原有流程的影响
- 正常工具调用流程不受影响:不同参数的调用各自计数为 1,不会触发
- 已有 DoomLoopDetector 逻辑不变,本次修复只是补全终止信号
- 阈值设为 5(比 DoomLoopDetector 的 3 更宽松),给 agent 合理空间
- max_retry_count 等原有退出机制不受影响
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
## 问题严重性 Agent 在 Function Calling 模式下完成工具调用后,最终输出为空字符串。 VIS 层收到空消息导致前端"影响面分析"、"根因分析"全部为空,用户看到的 是 Agent 跑了 72 秒却没有任何分析结论。这是生产环境必须修复的问题。 ## 根因 Function Calling 循环中,每轮 reply_message.content = llm_out.content, 但 LLM 返回 tool_calls 时 content 为空。当循环因 max_retry_count 达到上限、 doom loop 终止、或其他原因退出时,reply_message.content 仍然是空字符串。 VIS 层通过 output_message_id 查找最终消息,发现 content 为空, 导致 output message is "" → 前端显示空的分析结果。 ## 修复内容 1. **强制 LLM 生成总结**:当 FC 循环退出后 reply_message.content 为空时, 额外调用一次 LLM(不带工具定义),强制生成最终分析总结。 提示词明确要求"Based on the tool execution results above, please provide a comprehensive analysis and summary. Do NOT call any more tools - provide your final answer directly." 2. **Action report fallback**:如果强制 LLM 调用失败,从 action_report 中拼接内容作为兜底 3. **SKILL.md 读取后阻止 BlankAction 终止**:追踪 _last_tool_name 和 _last_tool_args,当 BlankAction terminate=True 但上一轮是读取 SKILL.md 时,阻止终止并继续循环(这是 skill 不往下执行问题的代码层防护) ## 对原有流程的影响 - 正常流程(LLM 最终返回纯文本)不受影响:reply_message.content 有值, 不会触发额外 LLM 调用 - 只有 content 为空时才触发强制总结,且使用 try-except 保护 - _last_tool_name 追踪只记录非 blank 的工具调用,不影响 BlankAction 逻辑 - SKILL.md 读取保护只在 terminate=True + 上一轮是 view/read SKILL.md 时生效,其他场景完全不影响 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
## 问题严重性 Agent 读取技能文件后直接输出技能内容的总结就停止了,不按照技能中的方法论 继续调用工具执行任务。用户看到的是"读取了技能"而非"执行了分析", Agent 把"读技能"当成了"做完了"。这是技能体系可用性的根本性问题, 不修复则技能加载机制形同虚设。 ## 根因 1. **Prompt 缺少约束**:skills.md.j2 模板只说"用 view 读取 SKILL.md, 内化指令并立即应用",但没有明确"读取是前置步骤,不是任务完成" 2. **Sandbox prompt 缺少约束**:AGENT_SKILL_SYSTEM_PROMPT 同样没有 强调读取后必须继续执行 3. **BlankAction 无条件终止**:LLM 读取 SKILL.md 后返回纯文本总结 (无 tool_calls),触发 BlankAction(terminate=True), generate_reply 循环直接退出。(代码层防护已在上一条 commit 中加入) ## 修复内容 1. **shared/skills.md.j2**:增加"关键约束"段落,明确: - 读取 SKILL.md 是前置准备步骤,不是任务完成 - 读取技能后,必须按照技能中的方法论和工具链继续执行工具调用 - 禁止在读取技能后直接输出总结或结论 2. **react_master_agent/skills.md.j2**:同步增加相同约束 3. **sandbox/prompt.py AGENT_SKILL_SYSTEM_PROMPT**:增加 "读取不是完成"约束 ## 对原有流程的影响 - Prompt 变更只增加约束性指令,不修改任何工具调用逻辑 - 不影响不使用技能的 Agent 流程 - 不影响技能加载和解析机制 - 代码层防护(上一条 commit 中的 SKILL.md 读取后阻止 BlankAction 终止)作为双重保险,即使 LLM 忽略 prompt 约束也能阻止提前终止 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
## 问题 GET /api/v1/app/resources/list?type=app 在构建 App 资源动态参数时,会同步调用 AppManager.get_derisks() -> AppService.sync_app_list()。App 列表查询已迁移为异步 async_app_list/app_list,但同步入口 sync_app_list 缺失,触发 AttributeError: Service 无 sync_app_list。 ## 不改的影响 - 每次拉取 type=app 的资源列表都会在后台打 ERROR,堆栈指向 app_agent_manage / building app Service。 - 应用类资源下拉/参数发现拿不到真实应用列表:controller 捕获异常后退回空列表,界面表现为可选 App 为空或缺失,影响应用绑定与编排配置。 - get_app 中对同步方法 sync_app_detail 错误使用 await,若在异步路径调用会触发 TypeError(await 非 awaitable)。 ## 改动 - building/app/service/service.py: 新增 sync_app_list,过滤与分页语义与 async_app_list 对齐,使用同步 ORM 会话供仅能在同步上下文调用的资源发现代码使用。 - agent/agents/app_agent_manage.py: get_app 改为直接返回 sync_app_detail(app_code),去掉无效的 await。 Co-authored-by: Cursor <cursoragent@cursor.com>
…eted app Add null check after self.get() in _resource_to_app_detail to prevent AttributeError when a referenced app no longer exists. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
从
feat/nsh_memory分支提取 5 个与 memory_case 无关的 bug修复,独立合并。
Fixes
fix(agent): 修复 Agent 死循环无法终止 + doom loop 误判合法调用
fix(agent): 修复 FC 循环退出后最终输出为空的问题
fix(agent): 修复 Agent 读取 SKILL.md 后不继续执行任务的问题
fix(serve): restore sync_app_list for app resource discovery
fix(serve): handle null app_info when resource_agent references a
deleted app
Files changed
packages/derisk-core/src/derisk/agent/— agent loop termination, FCsummary fallback, doom loop detection
packages/derisk-core/src/derisk/sandbox/— skill prompt constraintspackages/derisk-serve/src/derisk_serve/— sync_app_list, null app_infocheck