多 Agent 编排

运行多个 Agent,把顺序交给 controller 决定。

有些工作的顺序无法事先写下来。设置 type: controller,声明运行结束时什么必须成立,Dagu 就让模型根据回传的结论挑选下一个要执行的 Agent 步骤。每个动作仍然是普通的工作流步骤,带有日志、重试、审批和审计记录。

两个评审、一个修改,没有 depends
# code-review.yaml
type: controller

llm:
  provider: anthropic
  model: claude-opus-5
  system: |
    Get top_n.py past both reviews. When a review fails, pass its finding
    to revise, then ask that same reviewer again. A revision made for one
    reviewer can break the other.

steps:
  - name: review_simplicity
    description: Judge simplicity. Prints PASS, or FAIL with what to change.
    action: harness.run
    with:
      provider: opencode
      prompt: Read top_n.py. Print "PASS" or "FAIL: <what to change>".

  - name: review_correctness
    description: Judge correctness. Prints PASS, or FAIL with the bug.
    action: harness.run
    with:
      provider: codex
      prompt: Read top_n.py. Print "PASS" or "FAIL: <the bug>".

  - name: revise
    description: Edit top_n.py to resolve one review finding.
    action: dag.run
    with: { dag: revise }

tasks:
  - name: simplicity_passed
    description: The latest simplicity review returned PASS on the current file.
  - name: correctness_passed
    description: The latest correctness review returned PASS on the current file.

声明完成条件,而不是步骤顺序

每个动作都是真实的 Agent CLI: Claude、Codex、Gemini、OpenCode

任务以完成、跳过或失败三种状态收敛

等待人工回答时挂起,不留下常驻进程

At a glance

Controller 工作流与 Agent 框架

终止条件
Dagu

由你声明完成条件。没有任务处于 open 时运行结束。

Agent 框架

要么模型自己判断已经做完,要么提前画出全部路径并靠人维护。

持久性
Dagu

等待中的运行退出进程,并在新进程上恢复。

Agent 框架

长时间等待通常意味着一个要保活的进程和一套要运维的状态存储。

运维能力
Dagu

调度、队列、重试、产物和审计记录都来自这次 DAG 运行。

Agent 框架

每个项目重造一遍,或者交给托管的控制面。

影响范围
Dagu

工作流文件里的那组步骤。

Agent 框架

工具定义允许的一切。

In depth

Where each tool fits

01

无法写下来的正是顺序

图可以按退出码分支,却无法按评审实际说了什么分支。Controller 工作流固定动作集合,只把排序交出去。

  • 步骤变成动作目录,不再有需要维护的 depends
  • tasks 声明运行结束时什么必须成立
  • Controller 把一个 Agent 的结论带进下一个 Agent 的参数
02

模型选择的是顺序,绝不是能力

Controller 只能在你声明过的步骤中挑选。它无法凭空创造步骤、无法自己写 shell 命令、也够不到文件里没写的东西,因此影响范围就是这份工作流定义。

  • 每个 Agent 可以跑在主机上,也可以跑在挂载和出网规则都写明的容器沙箱里
  • 按角色分配不同的 provider 和模型,避免同一个模型给自己的产出打分
  • 已经足够可信的部分移进子工作流,就不再是一个决策
03

生产管控来自运行本身,而不是框架

Controller 运行就是一次 DAG 运行。调度、队列、重试、产物和审计记录原样适用,限制 Agent 花费的上限也是引擎设置,而不是提示词里的叮嘱。

  • ask_user 会持久挂起运行: 进程退出,worker 槽位释放
  • 几小时后有人回答,运行在新进程上继续
  • 触及轮次、动作重试或提问次数上限时运行失败,而不是无边界地消耗
04

事后可以还原任何一次运行

Controller 没有依赖边,因此运行展示为它实际做出的决策序列,而不是一张图。

  • 决策时间线: 每轮一行,含尝试次数、耗时,以及每个动作产生的子运行链接
  • 任务视图显示每个目标被判为完成、跳过还是失败,以及给出的理由
  • 完整对话记录,包含模型看到的每一条工具结果

FAQ

Practical questions before adopting Dagu

Controller 工作流和 Agent 循环有什么区别?

裸循环把「是否结束」交给模型。Controller 保留循环,但把终止条件收回来: 你声明任务以及「完成」的含义,没有任务处于 open 时运行结束。

如果某个任务其实没必要做,会怎样?

Controller 会把它标记为跳过并记录理由,运行仍然算成功。跳过和失败是两种状态,因为「不需要做」和「做不到」在审计日志里是不同的结果。

不同步骤能用不同的模型吗?

可以。每个 Agent Harness 步骤指定自己的 provider 和模型,controller 自身的模型单独配置,因此可以用便宜的模型驱动昂贵的专家,也可以让两个 provider 互相校验。

怎样避免运行无节制地花钱?

上限由引擎强制执行。单次运行中一个动作最多执行五次,最多提五个问题,轮次上限默认五十并且可以调低。触及上限会让运行失败,并指出还有哪些任务未收敛。

什么时候仍然应该用普通的图?

画得出来就画出来。type: graph 仍是默认值,因为它更快、更便宜、可复现。只有当顺序确实取决于前面步骤产出了什么时,才动用 controller。

Next step

Start with one workflow.

Install Dagu, move one fragile script or agent task into YAML, and decide from a real run history.