面试-Agent任务编排怎么处理?

一、核心问题:S03-S06 平面Todo清单的致命缺陷

背景:
https://fairy-study.blog.csdn.net/article/details/159253372?spm=1001.2014.3001.5502

S03的 TodoManager 本质是内存中的扁平检查表,在复杂任务/多Agent协作场景下完全不够用,核心痛点:

  1. 无依赖关系:无法定义「任务B必须等任务A完成才能做」,模型不知道哪些任务该先做、哪些被阻塞;
  2. 无并行性:无法识别「任务C和D可并行执行」,只能串行处理,效率极低;
  3. 无持久性:Todo只存在于内存,上下文压缩(S06)或Agent重启后就丢失,无法跨会话/跨Agent协作;
  4. 状态单一:只有「待做/进行中/完成」,无法体现「被阻塞」这种关键状态(比如任务B等A完成,此时B是「被阻塞」而非单纯「待做」)。

这些问题导致Agent在处理复杂工程任务(如「搭建数据库→写API→做认证→部署」)时,无法合理规划执行顺序、无法协作、无法断点续跑。

二、核心解决方案:基于磁盘的任务依赖图(DAG)

S07的核心是把「扁平内存清单」升级为「带依赖的持久化任务图」,核心设计:

1. 核心概念(先理解这3个词)
  • 任务图:用「有向无环图(DAG)」描述任务关系,比如「任务1→任务2→任务4」「任务1→任务3→任务4」;
  • blockedBy/blocks:任务的双向依赖关系(A blocks B = B blockedBy A,即B依赖A);
  • 持久化 :每个任务以JSON文件存在磁盘(.tasks/task_1.json),而非内存,重启/压缩都不丢。
2. 解决思路(对应问题)
问题 解决方案
依赖/并行 blockedBy定义「谁阻塞我」,blocks定义「我阻塞谁」,支持串行+并行;
状态不完整 扩展状态为pending→in_progress→completed,并新增「被阻塞」的隐含状态(blockedBy非空则阻塞);
无持久性 任务存在磁盘JSON文件,而非内存,跨会话/重启不丢;
无法自动解阻塞 完成任务后,自动清除所有依赖该任务的blockedBy列表,解除阻塞;

三、核心代码逻辑(落地实现)

1. TaskManager:任务图的核心管理器(CRUD+依赖处理)
python 复制代码
import json
from pathlib import Path

class TaskManager:
    def __init__(self, tasks_dir: Path):
        self.dir = tasks_dir
        self.dir.mkdir(exist_ok=True)  # 确保.tasks目录存在
        self._next_id = self._max_id() + 1  # 自动生成任务ID(避免重复)

    # 私有方法:加载单个任务(从JSON文件)
    def _load(self, task_id):
        f = self.dir / f"task_{task_id}.json"
        return json.loads(f.read_text())

    # 私有方法:保存任务(写入JSON文件,持久化核心)
    def _save(self, task):
        f = self.dir / f"task_{task['id']}.json"
        f.write_text(json.dumps(task, indent=2))

    # 核心1:创建任务(初始状态pending,无依赖)
    def create(self, subject, description=""):
        task = {
            "id": self._next_id,
            "subject": subject,  # 任务名称(如"Setup project")
            "status": "pending", # 初始状态
            "blockedBy": [],     # 被谁阻塞(依赖的任务ID列表)
            "blocks": [],        # 阻塞谁(被我依赖的任务ID列表)
            "owner": ""          # 可选:任务归属(多Agent时用)
        }
        self._save(task)  # 写入磁盘文件
        self._next_id += 1
        return json.dumps(task, indent=2)  # 返回创建结果

    # 核心2:更新任务(状态+依赖处理)
    def update(self, task_id, status=None, add_blocked_by=None, add_blocks=None):
        task = self._load(task_id)
        # 1. 更新状态
        if status:
            task["status"] = status
            # 关键:任务完成时,自动清除所有依赖该任务的blockedBy
            if status == "completed":
                self._clear_dependency(task_id)
        # 2. 添加依赖关系(比如任务2 blockedBy 任务1)
        if add_blocked_by:
            task["blockedBy"].extend(add_blocked_by)
        if add_blocks:
            task["blocks"].extend(add_blocks)
        self._save(task)
        return json.dumps(task, indent=2)

    # 核心3:自动解阻塞(完成任务后触发)
    def _clear_dependency(self, completed_id):
        # 遍历所有任务文件,清除包含该ID的blockedBy
        for f in self.dir.glob("task_*.json"):
            task = json.loads(f.read_text())
            if completed_id in task.get("blockedBy", []):
                task["blockedBy"].remove(completed_id)
                self._save(task)  # 写入修改后的文件

    # 辅助:列出所有任务(查看依赖图)
    def list_all(self):
        tasks = []
        for f in sorted(self.dir.glob("task_*.json")):
            tasks.append(json.loads(f.read_text()))
        return json.dumps(tasks, indent=2)
2. 工具注册(模型可调用的任务操作)
python 复制代码
# 初始化任务管理器(持久化到.tasks目录)
TASKS = TaskManager(Path(".tasks"))

# 任务操作工具(模型可调用)
TOOL_HANDLERS = {
    # 基础工具(bash/read/write/edit/load_skill)
    # 新增4个任务工具
    "task_create": lambda **kw: TASKS.create(kw["subject"]),  # 创建任务
    "task_update": lambda **kw: TASKS.update(
        kw["task_id"], 
        status=kw.get("status"),
        add_blocked_by=kw.get("add_blocked_by"),
        add_blocks=kw.get("add_blocks")
    ),  # 更新状态/依赖
    "task_list":   lambda **kw: TASKS.list_all(),  # 列出所有任务(看依赖图)
    "task_get":    lambda **kw: TASKS.get(kw["task_id"]),  # 获取单个任务详情
}

# 工具定义(告诉模型怎么调用)
TOOLS.extend([
    {
        "name": "task_create",
        "description": "Create a new task with pending status",
        "input_schema": {"type": "object", "properties": {"subject": {"type": "string"}}, "required": ["subject"]}
    },
    {
        "name": "task_update",
        "description": "Update task status or dependencies",
        "input_schema": {
            "type": "object",
            "properties": {
                "task_id": {"type": "int"},
                "status": {"type": "string", "enum": ["pending", "in_progress", "completed"]},
                "add_blocked_by": {"type": "array", "items": {"type": "int"}}
            },
            "required": ["task_id"]
        }
    },
    # task_list/task_get 工具定义省略
])

四、执行流程示例(直观理解)

用户指令:「创建3个任务:Setup project(1)、Write code(2)、Write tests(3),按顺序依赖(2依赖1,3依赖2);完成任务1后,列出所有任务看依赖变化」

步骤1:创建任务+设置依赖
  1. 模型调用task_create(subject="Setup project") → 生成.tasks/task_1.json(status=pending,blockedBy=[]);
  2. 模型调用task_create(subject="Write code") → 生成task_2.json
  3. 模型调用task_update(task_id=2, add_blocked_by=[1]) → 修改task_2.jsonblockedBy=[1]
  4. 模型调用task_create(subject="Write tests") → 生成task_3.json
  5. 模型调用task_update(task_id=3, add_blocked_by=[2]) → 修改task_3.jsonblockedBy=[2]

此时任务文件内容:

  • task_1.json:{"id":1, "status":"pending", "blockedBy":[], "blocks":[2]}
  • task_2.json:{"id":2, "status":"pending", "blockedBy":[1], "blocks":[3]}
  • task_3.json:{"id":3, "status":"pending", "blockedBy":[2], "blocks":[]}
步骤2:完成任务1,自动解阻塞
  1. 模型调用task_update(task_id=1, status="completed")
  2. _clear_dependency(1) 触发:遍历所有任务,移除blockedBy中的1;
  3. task_2.json的blockedBy变为[](从[1]清空),状态仍为pending,但已「解除阻塞」;
步骤3:列出任务(查看结果)

模型调用task_list(),返回:

json 复制代码
[
  {"id":1, "status":"completed", "blockedBy":[], "blocks":[2]},
  {"id":2, "status":"pending", "blockedBy":[], "blocks":[3]},  // 已解阻塞
  {"id":3, "status":"pending", "blockedBy":[2], "blocks":[]}
]

五、从S06到S07的核心变化(面试重点)

组成部分 S06(扁平Todo) S07(任务图)
工具数量 5(基础+load_skill) 8(新增task_create/update/list/get)
规划模型 内存中的扁平检查表 磁盘上的依赖任务图(DAG)
任务关系 无(仅顺序) blockedBy/blocks 双向依赖
状态体系 pending/in_progress/completed(无阻塞态) 新增「被阻塞」隐含状态(blockedBy非空)
持久性 上下文压缩/重启后丢失 磁盘文件存储,跨会话不丢
核心能力 单场次简单任务跟踪 复杂任务排序/并行/多Agent协作

六、核心价值(面试答法)

S07的任务图解决了「复杂任务规划+多Agent协作」的核心问题:

  1. 依赖有序 :通过blockedBy/blocks定义任务执行顺序,避免模型乱序执行(比如先写测试再搭项目);
  2. 并行提效:识别可并行的任务(如任务2和3都依赖1,完成1后2、3可并行),提升执行效率;
  3. 持久化协作:任务存在磁盘,多Agent可读写同一个任务图(比如Agent A创建任务,Agent B执行,Agent C验收),支持断点续跑;
  4. 自动解阻塞:完成上游任务后自动解除下游阻塞,无需模型手动判断,减少出错。

这也是S07之后所有进阶功能(后台执行S08、多Agent团队S09、工作树隔离S12)的基础------任务图是多Agent协作的「统一协调骨架」。

总结

S07的核心是「从扁平内存清单到持久化依赖任务图」:

  1. 用磁盘JSON文件实现任务持久化,跨会话/Agent不丢;
  2. blockedBy/blocks定义依赖关系,支持串行/并行任务规划;
  3. 完成任务时自动解阻塞,让Agent能自主判断「哪些任务可以开始做」;
  4. 新增任务操作工具,让模型能自主创建/更新/查看任务,成为复杂任务的「指挥中枢」。

面试时重点说清「依赖图(DAG)」「持久化」「自动解阻塞」这三个关键词,以及它们如何解决S06之前的「无依赖、无并行、无持久化」问题。

相关推荐
闻哥2 小时前
深入理解 MySQL InnoDB Buffer Pool 的 LRU 冷热数据机制
android·java·jvm·spring boot·mysql·adb·面试
Ivy_belief2 小时前
Qt网络编程实战:从零掌握 QUdpSocket 及 UDP 通信
网络·qt·udp
koping_wu2 小时前
Java面试汇总:java基础、多线程、spring、jvm、分布式
java·spring·面试
EW Frontier2 小时前
【UAV识别】基于分层学习的射频无人机检测与识别技术,准确率达99%!【附python代码】
python·无人机·无人机信号识别
Du_chong_huan2 小时前
5.3 通过负载均衡分担流量
网络
booksyhay2 小时前
XCP协议学习笔记
网络·笔记·学习
WangYaolove13142 小时前
基于循环神经网络的情感分类(源码+文档)
python·mysql·django·毕业设计·源码
badhope2 小时前
GitHub超有用项目推荐:skill仓库--用技能树打造AI超频引擎
java·开发语言·前端·人工智能·python·重构·github
专家大圣2 小时前
告别付费 OCR!PaddleOCR-VL + cpolar,打造专属便携识别工具✨
网络·ocr·内网穿透·cpolar