事件订阅

🔵 概述事件如何进入平台并触发智能体。机制分为 pull(平台主动轮询)、push(外部系统推送)和 内部(内核进程事件)。

机制 类型 触发内容 配置位置
Cron pull(定时器) 按计划/间隔触发智能体运行 cron: 在 agent.yaml / config/cron.yaml
监控器 pull(源) 源中新元素触发智能体运行 config/monitors.yaml
入站 webhook push 通过 POST /v1/inbound/:template 触发一次智能体运行 server.yaml → inbound
工作流 Webhook push 通过 POST /v1/workflows/<name>/webhook 启动工作流 triggers.webhook
反应 内部事件 对进程事件执行动作(on:) config/reactions.yaml
await_event 等待 智能体运行等待事件(webhook 或定时器) 工具 kind: await_event

Push vs pull。 当外部系统本身知道事件发生时(支付、CRM、CI),push 更方便。Pull 适用于需要轮询源的场景;此时监控器仅在变更时触发,而 cron 始终按计划触发。

内部事件。 反应 订阅的不是外部系统,而是内核进程事件(ProcessEvent):启动/完成、工具调用、响应内容、预算等——并触发智能体、工具、webhook 或 signal(实时进程的 steering)。

在运行中等待事件。 await_event 暂停运行并等待外部回调 POST /v1/events/callback(通过 event_id)或定时器;async_action 执行完整的异步流程(请求 → 显示 URL → 回调 → 结果)。

结果投递。 运行/工作流的结果分发到 sink(notify):log、webhook、telegram、vk、yandex_messenger、email、messages_db、agent、workflow、storage——参见 Cron。

push 入口点(入站 webhook、Telegram/email 渠道)之间的区别——参见 组件与渠道。

对外:智能体操作日志(agent_events)

反方向——外部系统获知智能体的操作。原生钩子 kind: agent_events 在选定的生命周期点上将事件保存在内存环形缓冲区中(不落盘),而 GET /v1/events 路由在 ACCESS_ADMIN 下通过 long-poll 和 cursor drain(批量、不丢失事件)将日志对外提供。实现为 agent_os_events 模块;配置字段参见 扩展钩子。

智能体钩子(hook_files: [hooks/events.yaml]):

kind: agent_events
name: agent_events
agent: acme-agent
on: [after_tool_result, after_turn]   # по умолчанию только after_tool_result
ignore: [settings_get]                # служебные чтения не логируем
mutating: [order_create, order_cancel]
capacity: 5000                        # кольцевой буфер (в памяти)

读取:

GET /v1/events?agent=acme-agent&mode=wait&since=N

响应契约:{ ok, mode, agent, name, seq, since, count, events[], last, has_more, dropped_window }. Событие: seq, ts, agent, session, user_id, tool, kind, mutating, success, args_fp, detail (args_fp——参数的非加密指纹;参数/结果本身不保存)。

?mode= 行为
drain(默认) 立即返回一批事件,带 seq > since
wait long-poll:等待事件(最多 wait_ms),然后返回一批
events 最近 N 个事件
version 仅当前 seq(轻量计数器)

客户端维护游标——这样批次不会丢失:

let since = 0;
for (;;) {
  const r = await fetch(`/v1/events?agent=acme-agent&mode=wait&since=${since}&limit=100`,
    { headers: { Authorization: `Bearer ${adminToken}` } });
  const b = await r.json();
  for (const ev of b.events) handle(ev);            // события по возрастанию seq
  if (b.events.length) since = b.events.at(-1).seq; // сдвигаем курсор
  if (b.has_more) continue;                          // накопилась пачка — дочитываем
  if (b.dropped_window) resync();                    // часть вытеснена буфером
}

安全性。 路由 GET /v1/events——仅 ACCESS_ADMIN。Payload 最小化(不含参数/结果,仅 args_fp);since 被限制在 [0, max] 内,limit/wait_ms 有上限约束;capacity——内存中的环形缓冲区。