能否举一个实际场景,说明如何使用 DAG(有向无环图)来编排多个 Skill 的执行?

面试官:“能举一个实际的业务场景,说明你是怎么用 DAG 来编排多个 Skill 的吗?”

候选人:

“最经典的场景就是‘商务出行全流程安排’。用户说一句‘下周二去深圳见客户,帮我安排一下’,背后涉及七八个 Skill 的协作。我以这个为例,完整走一遍 DAG 的构建和执行过程。


场景:商务出行全流程安排

涉及 Skill 清单:

查看内嵌表格


构建 DAG

编排引擎拿到“安排出差”这个复合意图后,规划器生成如下 DAG:

                    ┌──────────────┐
                    │  A. 查日历   │
                    └──────┬───────┘
              ┌────────────┼────────────┐
              ▼            ▼            ▼
      ┌───────────┐ ┌───────────┐ ┌───────────┐
      │ B. 查天气 │ │ E. 查政策 │ │ C. 订机票 │
      └─────┬─────┘ └─────┬─────┘ └─────┬─────┘
            │             │             │
            │             │      ┌──────┴──────┐
            │             │      ▼             ▼
            │             │ ┌─────────┐  ┌─────────┐
            │             │ │ D. 订酒店│  │F. 约打车│
            │             │ └────┬────┘  └────┬────┘
            │             │      │            │
            └──────┬──────┘      └─────┬──────┘
                   ▼                   ▼
            ┌─────────────────────────────────┐
            │         G. 发送行程              │
            └───────────────┬─────────────────┘
                    ┌──────────────┐
                    │ H. 写日报草稿│
                    └──────────────┘

DAG 设计的关键决策点

  1. 并行与串行判断

A(查日历)是所有任务的先行条件——如果周二有全天会议,直接终止后续流程并提醒用户。A 完成后,B(查天气)、E(查政策)、C(订机票)三个完全互不依赖,编排引擎会同时发起三个异步调用,大幅缩短总耗时。

  1. 条件分支:A 的检查逻辑

A 执行完后,编排引擎检查输出 has_conflict。如果为 true,整个 DAG 在 A 节点就中断,引擎生成一个澄清问题:“您周二已有全天会议,是否仍然需要安排?”用户确认后再继续。这种条件分支不需要硬编码在 Skill 里,而是作为 DAG 边的路由规则配置在编排层。

  1. 多级依赖链

C(订机票)成功后,D(订酒店)和 F(约打车)才能执行——D 需要知道航班到达时间来确定入住时间,F 需要落地时间。这两者之间无依赖,所以订机票完成后,订酒店和约打车又并行发起。

  1. 非关键路径降级

B(查天气)和 E(查政策)不是必须成功的路径。如果天气 API 挂了,G(发送行程)用默认提示“请关注当地天气”代替具体温度;如果政策 API 超时,挂一个标记让用户自行确认。在 DAG 配置中,这两条边标记为 weak_dependency,失败不阻塞后续。

  1. 最终汇聚与收尾

G(发送行程)需要等待 B、E、D、F 全部完成(或部分降级),汇总所有信息生成行程邮件。H(写日报草稿)只依赖 G,因为需要确认行程已发送,日报里要附上邮件链接。


执行过程中的断点恢复

假设在 D(订酒店)执行后,酒店涨价超出用户预算,D 返回 WAITING_USER_INPUT 状态,询问用户是否接受溢价。编排引擎暂停整个 DAG,把当前执行快照(已完成:A、B、C、E,等待确认:D)序列化存 Redis。用户回复“接受”后,引擎从 Redis 加载快照,从 D 的断点继续,随后并行触发 F,最后汇聚到 G 和 H。