事件订阅
🔵 概述事件如何进入平台并触发智能体。机制分为 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——内存中的环形缓冲区。