前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Agent 计划循环依赖检测与修复
AIAI Agent任务规划

Agent 计划出现循环依赖,如何检测并定位阻塞?

拓扑排序没处理完的节点表示受到环路阻塞,不代表它们每一个都在环上。

前端进阶之旅 · 一题精讲更新于 2026.09.06
AI Agent#任务规划
先看核心答案读代码示例
理解线索

分清三种异常

  1. 引用错误依赖不存在的任务或标识被重复使用
  2. 依赖成环若干任务必须等待彼此先完成
  3. 下游阻塞自身不成环,但依赖的产物无法生成

检测结构错误不等于验证整份任务计划符合真实业务目标。

核心回答

先记住这个答案

先检查任务标识和依赖引用,再用拓扑排序判断前置依赖图是否存在环。Kahn 算法反复处理入度为零的节点;若最终处理数少于总节点数,剩余部分受到环路阻塞。要定位真正的环,可继续使用带递归栈的 DFS 或强连通分量分析。修复时应回到产物语义,拆分先产出草稿再评审的阶段,不能随便删除依赖让调度继续。

  • 未知依赖和重复标识应先作为输入错误处理
  • 拓扑排序剩余节点包括环内节点及其受阻下游
  • 合法反馈循环应显式建模状态、版本和退出条件

先确认边的方向与输入契约

约定依赖从前置任务指向使用它的任务,或者在节点中列出前置标识,整个系统必须一致。重复依赖可以按集合去重;重复节点标识则不能静默覆盖,否则一个任务可能凭空消失。依赖不存在的节点也应直接报错,而不是让它永久等待。

自依赖是最短的环,可以直接识别。一般环路需要遍历图判断,不能只检查两两互相引用,因为三个以上任务也可能形成闭环。下面示例先做基本输入校验,再维护入度和后继表,每条边只在建图与释放时处理有限次数。

区分已排序节点和受阻节点JavaScript
function inspectPlan(tasks) {
  const byId = new Map(tasks.map(task => [task.id, task]));
  if (byId.size !== tasks.length) throw new Error('duplicate id');
  const degree = new Map(tasks.map(task => [task.id, 0]));
  const next = new Map(tasks.map(task => [task.id, []]));
  for (const task of tasks) {
    for (const dep of new Set(task.deps)) {
      if (!byId.has(dep)) throw new Error('unknown dependency');
      degree.set(task.id, degree.get(task.id) + 1);
      next.get(dep).push(task.id);
    }
  }
  const queue = tasks.filter(task => degree.get(task.id) === 0)
    .map(task => task.id);
  const order = [];
  for (let head = 0; head < queue.length; head++) {
    const id = queue[head];
    order.push(id);
    for (const child of next.get(id)) {
      degree.set(child, degree.get(child) - 1);
      if (degree.get(child) === 0) queue.push(child);
    }
  }
  return { order, blocked: tasks.filter(task => degree.get(task.id) > 0)
    .map(task => task.id) };
}
const result = inspectPlan([
  { id: 'research', deps: [] },
  { id: 'draft', deps: ['research', 'review'] },
  { id: 'review', deps: ['draft'] },
  { id: 'publish', deps: ['review'] }
]);
console.log(result.order.join(','));
console.log(result.blocked.join(','));
查看输出与解释
research
draft,review,publish

draft 与 review 互相依赖;publish 只是它们的下游,也会出现在 blocked 中。用队列下标推进,在通常的 Map 操作代价假设下,时间为 O(V+E),空间为 O(V+E)。

定位真正需要修改的依赖

输出中 publish 不属于环,它只是等不到 review。因此不能把剩余节点全部叫做环成员。可以在剩余子图用 DFS 的当前访问路径发现回边,或用强连通分量找出互相可达的节点组;单节点分量还要检查是否存在自环。

面向用户的诊断最好展示一条闭合等待路径以及每条边等待的产物。例如草稿等待评审结论、评审又等待草稿,说明阶段定义混在一起。改为先生成初稿,再评审,再生成修订稿,可以保留业务要求并消除一次性任务间的互相等待。

不要把合理迭代误判成业务错误

评审后修改再评审是合理的运行循环,但要标明稿件版本、终止条件和迭代上限。一次性依赖图可展开有限轮次,或由外层状态机管理循环。不能仅因为工作流允许循环,就忽略某个阶段内部永远无法开始的前置依赖。

计划修改后应重新检查受影响结构,并核查已经运行的任务是否采用旧输入。自动修复可以提出拆分或替换依赖的候选方案,最终仍要验证它没有跳过必需检查。检测失败时保留图和错误路径,比让模型反复盲目重写整份计划更便于定位原因。

回答前,多想一步

容易答错的地方

随便删一条边让图无环
无环不代表依赖正确。删除评审前置条件可能使未经检查的产物进入后续流程,必须根据业务产物重新建模。
用重试解决结构死锁
相同图和相同状态下重复调度不会产生缺失产物,应先修正依赖或为合法迭代建立可执行的初始状态。
试着用自己的话回答

面试官还会怎么问?

排序结果一定唯一吗?

不一定。多个无依赖关系的就绪节点可以交换顺序,仍满足所有前置关系;需要稳定输出时再增加明确的排序策略。

只想知道有没有环,需要找所有环吗?

不需要。拓扑处理数量就能判断,或用 DFS 找到第一条回边停止;详细诊断再进一步定位。针对“Agent 计划循环依赖检测与修复”,还应保留最小复现、预期结果和失败路径,避免只凭一次现象下结论。

依赖图正确就能保证任务成功吗?

不能,它只排除一类结构错误。输入质量、工具能力、资源冲突和业务验收仍需单独验证。针对“Agent 计划循环依赖检测与修复”,还应保留最小复现、预期结果和失败路径,避免只凭一次现象下结论。

从一道题,走向一组知识

把知识连起来

任务规划

如何为 Agent 子任务建立可执行的依赖图?

先定义节点、产物与依赖边的语义

任务规划

LLM Agent 什么时候值得采用分层任务分解?

通过阶段与层级拆分避免互相等待

任务规划

依赖已知的子任务如何安全地并行执行?

把合法就绪节点交给调度器处理继续对照“Agent 计划循环依赖检测与修复”的触发条件、结果与失败边界。

参考资料

  • NetworkX:拓扑排序的前提与环路错误

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 先确认边的方向与输入契约
  3. 定位真正需要修改的依赖
  4. 不要把合理迭代误判成业务错误
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑