跳转到内容

控制流与动态编排——Huginn 的 CommanderAgent 模式

控制流与动态编排——Huginn 的 CommanderAgent 模式

学习目标

  • 理解 ControlLink 与 Link 的分离设计
  • 掌握 CommanderAgent 的四种控制操作
  • 学会使用 Liquid 模板实现条件编排
  • 了解 SchedulerAgent 的运行时动态调度机制

前置知识

本章涉及 Agent 控制流与动态编排的通用原理,建议先阅读:

下文假设你已理解控制流与数据流的基本概念,直接聚焦 Huginn 的具体实现。

项目实践

关键区别:

  • Link 有 event_id_at_creation——用于追踪事件水位线;ControlLink 不需要
  • Link 传播 Event 数据;ControlLink 传递控制指令
  • 一个 Agent 可同时拥有两种连接

四种控制操作的实现

AgentControllerConcern 模块提供统一的控制逻辑:

CommanderAgent 条件编排

通过 Liquid 模板动态决定控制动作:

{
"action": "{% if conditions contains 'Rain' %}enable{% else %}disable{% endif %}"
}
{
"action": "configure",
"configure_options": {
"location": "{{_location_.latlng}}"
}
}

实际应用场景

SchedulerAgent 运行时动态调度

SchedulerAgent 与普通 CommanderAgent 的区别:

维度CommanderAgentSchedulerAgent
触发方式调度或事件触发仅自定义 cron 调度
执行频率每次触发执行一次按 cron 周期反复执行
调度引擎标准 SCHEDULES 列表Rufus::Scheduler 自定义 cron
适用场景条件响应自定义定时任务

运行时注册流程

  1. HuginnScheduler 每分钟调用 schedule_scheduler_agents
  2. 对每个 SchedulerAgent,检查是否有变化(options_changed? 清除 scheduled_at
  3. 通过 Rufus::Scheduler.schedule_cron 注册/更新定时任务
  4. 当 Agent 被禁用或删除时,自动 job.unschedule

问题与规避

对不可调度 Agent 执行 run

CommanderAgent 的 validate_control_action 会验证:如果目标是 cannot_be_scheduled? 的 Agent(如 TriggerAgent),执行 run 操作会添加验证错误。

规避方式:对 TriggerAgent 类型的 Agent 使用 enable/disable 而非 run

配置合并的意外覆盖

deep_merge 只会覆盖已指定的键,不会清空未提及的键。但如果是嵌套 Hash 中的同名键,会被完全替换。

规避方式configure_options 只包含需要修改的字段。

启用 Agent 的积压事件

禁用期间上游 Agent 仍向目标发送事件。重新启用时可能瞬间处理大量积压事件。

规避方式:CommanderAgent 的 enable 操作配合 drop_pending_events 选项,启用时自动跳过积压事件。

设计取舍

控制与数据分离 vs 统一

维度分离设计(Huginn)统一设计
概念清晰度高(两种连接职责明确)低(一种连接承担多种职责)
可视化两种连接可分别展示混合展示难以理解
实现复杂度中(两套关系模型)低(一套关系模型)

分离设计让用户可以清晰理解”数据怎么流”和”谁控制谁”。

参考来源