# 触发器

连接式集成不仅仅是代理可以按需读取的地方。它也是一个 **实时事件来源**。当有人给你发邮件、编辑 Notion 页面、在你的某个仓库上创建 GitHub issue、在 Stripe 上扣款，或在 Slack 上给你发私信时，OpenHuman 会近乎实时地接收该事件，并决定是否要对此采取行动。

本页讲述的是这条管道：触发器如何到达、如何被分类，以及触发器如何在你不输入任何内容的情况下变成完整的代理动作。

## 什么是触发器

触发器是由你已连接的集成发布的外部事件。常见形式：

| 集成         | 示例触发器                                                       |
| ---------- | ----------------------------------------------------------- |
| **Gmail**  | `GMAIL_NEW_GMAIL_MESSAGE`，收件箱中新邮件                           |
| **Slack**  | `SLACK_NEW_MESSAGE`，你被提及的频道/私信消息                            |
| **Notion** | `NOTION_PAGE_UPDATED`，被跟踪的页面发生了变化                           |
| **GitHub** | `GITHUB_ISSUE_OPENED`, `GITHUB_PULL_REQUEST_OPENED` ，在你的仓库上 |
| **Stripe** | `STRIPE_CHARGE_SUCCEEDED`，你账户上的一笔成功扣款                       |
| **日历**     | `GOOGLE_CALENDAR_EVENT_CREATED`，你日历中的一个新事件                  |

完整集合来自 [Composio](https://composio.dev) 驱动以下功能的连接器层： [第三方集成](/openhuman/zh/gong-neng/integrations.md)。当某个连接处于激活状态时，相关的触发器订阅会自动配置好。

### Gmail OAuth 作用域

Gmail 触发器订阅需要对已连接的 Google 账号拥有邮件读取权限。新的 OpenHuman Gmail 授权会请求 `https://www.googleapis.com/auth/gmail.readonly` ，因此 `GMAIL_NEW_GMAIL_MESSAGE` 可以启用，原生 Gmail 同步路径也可以读取新邮件元数据。

如果某个较早的 Gmail 连接是在请求该作用域之前创建的，请先在设置中重新连接 Gmail，再启用 Gmail 触发器。

## 触发器的来源，端到端流程

```
┌────────────────────┐
│ 第三方 API │ Gmail / Slack / Notion / GitHub / ...
└─────────┬──────────┘
 │ webhook
 ▼
┌────────────────────┐
│ OpenHuman 后端 │ 对 webhook 进行 HMAC 验证并规范化载荷
└─────────┬──────────┘
 │ Socket.IO 事件（"composio:trigger"）
 ▼
┌────────────────────┐
│ Rust 核心 │ 发布 DomainEvent::ComposioTriggerReceived
│（你的笔记本）│ 在进程内事件总线上
└─────────┬──────────┘
 │
 ▼
┌────────────────────┐
│ 触发器分诊 │ 分类：丢弃 / 确认 / 响应 / 升级
└─────────┬──────────┘
 │
 ▼
┌────────────────────┐
│ 以下之一：│
│ - 无操作 │ ← 丢弃
│ - 记忆笔记 │ ← 确认
│ - 触发器反应器 │ ← 响应（1-2 次工具调用）
│ - 编排器 │ ← 升级（完整多步骤规划）
└────────────────────┘
```

webhook 不会原样到达你的机器。后端持有 OAuth 令牌，并直接接收来自第三方的 webhook。它会进行 HMAC 验证、规范化载荷，并通过现有的已认证 socket 将其转发到你的 Rust 核心。你的笔记本只会看到一个干净、已验证的 `ComposioTriggerReceived` 事件出现在总线上，别无其他。

## 分诊步骤

在任何动作运行之前，每个触发器都会经过 [`trigger_triage`](https://github.com/tinyhumansai/openhuman/tree/main/src/openhuman/agent/agents/trigger_triage) 代理。它唯一的任务就是决定系统其余部分应该做什么。

它精确地选择以下四种动作之一：

| 动作       | 会发生什么                                                                                                                                 | 何时使用                                                 |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| **`丢弃`** | 什么都不做。触发器会被静默记录并丢弃。                                                                                                                   | 垃圾信息、重复项、无关噪音。对于你不关心的内容，这是默认选项。                      |
| **`确认`** | 保存一条简短的记忆笔记，不运行代理。                                                                                                                    | 值得记住的被动通知（“archive 中创建了一个新页面”）。                      |
| **`响应`** | 这个 [`trigger_reactor`](https://github.com/tinyhumansai/openhuman/tree/main/src/openhuman/agent/agents/trigger_reactor) 代理运行，调用一到两个工具。 | 一个小的单步副作用：保存记忆条目、快速回复、将某个线程标记为已读。                    |
| **`升级`** | 完整的 **orchestrator** 代理接管并具备规划能力。                                                                                                     | 任何需要推理、多步骤或多种技能的内容：起草回复、更新多个 Notion 页面、决定如何分诊一个传入问题。 |

分诊代理拥有与代理其余部分相同的记忆和工作区上下文。它可以判断某个触发器是否与你当前正在处理的事情相关，相关人员是谁，以及这是否属于你曾要求 OpenHuman 代为处理的那类事情。

## 当一个触发器变成代理动作时

这部分区分了“OpenHuman 有一个 Gmail 集成”和“OpenHuman 为你的收件箱待命”：

* **`响应`** 是廉价路径。触发器反应器是一个专门的窄角色，硬性预算只有少量工具调用。它非常适合：写一条一行的记忆笔记，内容是“看到 Stripe 上一笔 84 美元的新扣款，客户 X，商户 Y”；因为这是你本周已经分诊过两次的同类自动警报，所以静默地把一条 Slack 消息标记为已处理；或者存储一条结构化事件记录，供用户日后查询。
* **`升级`** 是重型路径。当分诊代理决定触发器需要真正处理时，它会带着一个自包含的任务描述将其交给编排器。编排器可以访问你的完整技能面、工具、记忆以及 [潜意识循环](/openhuman/zh/gong-neng/subconscious.md) 输出。从那里它可能会：
  * 为一封重要邮件起草回复并排队等待你的批准。
  * 为一个传入问题拉取相关的 Notion / Linear / Drive 上下文并写一条结构化评论。
  * 根据一个传入事件更新三个互联系统（“这个客户在 Stripe 中的方案变更了，更新 HubSpot，在 #revenue 发帖，并在他们的 Notion 文件中加一条备注”）。
  * 判断触发器意味着会议刚刚被安排，并预先加载 [会议代理](/openhuman/zh/gong-neng/mascot/meeting-agents.md) 以处理该通话。

在这两种情况下，动作都在你的机器上运行，针对你本地的记忆树，并使用代理其余部分相同的模型路由和工具面。

## 为什么还要有分诊步骤

很容易想跳过分类器，直接把每个触发器都送进编排器。但这样做有两个坏处：

1. **大多数触发器都是噪音。** 一个已连接的 Gmail 账户每小时会触发几十个触发器，而其中绝大多数用户并不关心。对每个触发器都运行编排器会消耗预算，并产生持续不断的后台活动流。
2. **不同触发器应当有不同的上限。** 一张自动生成的 Stripe 收据和一条个人 Slack 私信，不应该花费相同数量的 token 来处理。分诊让廉价路径保持便宜，并把编排器保留给真正值得它的事情。

分诊运行在快速模型层（见 [自动模型路由](/openhuman/zh/gong-neng/model-routing.md)），因此分类本身是亚秒级的。

## 配置与退出

* **默认开启。** 一旦某个集成连接成功，它的触发器就会自动进入这条管道。
* **退出。** 分诊路径受 `OPENHUMAN_TRIGGER_TRIAGE_DISABLED` 环境变量控制。将其设为 `1` / `true` / `是` 会关闭代理分类，只退回到被动记录。集成本身仍然保持连接；只是自动动作行为会被抑制。
* **按触发器设置。** 触发器设置（应评估哪些集成和事件类型）在 **设置**下管理；底层 RPC 方法是 `update_composio_trigger_settings` / `get_composio_trigger_settings`.
* **审计日志。** 无论结果如何，每个触发器都会写入触发历史，因此你可以看到来了什么、分类器做了什么决定，以及运行了什么（如果有的话）。决策和升级也会作为 `TriggerEvaluated` / `TriggerEscalated` 事件发布到进程内总线上，这意味着核心内部的任何东西都可以订阅它们。

## 隐私边界

触发器遵循与产品其余部分相同的边界（见 [隐私与安全](/openhuman/zh/gong-neng/privacy-and-security.md)):

* 第三方令牌保留在后端，绝不会存放在你的笔记本上。
* webhook 在到达你的机器之前，会先由后端进行 HMAC 验证。
* 触发器载荷由你的本地核心处理；分类和任何响应都在你的机器上、针对你的本地记忆树运行。
* 由 `确认` / `响应` / `升级` 路径写入的记忆笔记会存储在你的本地 SQLite 记忆树和 Markdown 保管库中，与任何其他来源一样。

## 实现提示（面向开发者）

* 分诊代理： `src/openhuman/agent/agents/trigger_triage/`
* 反应器代理： `src/openhuman/agent/agents/trigger_reactor/`
* Composio 总线订阅者： `src/openhuman/composio/bus.rs` (`ComposioTriggerSubscriber`)
* 触发历史持久化： `src/openhuman/composio/trigger_history.rs`
* 领域事件： `DomainEvent::ComposioTriggerReceived`, `DomainEvent::TriggerEscalated` 在 `src/core/event_bus/events.rs`
* 触发器设置 RPC： `update_composio_trigger_settings` / `get_composio_trigger_settings` 在 `src/openhuman/config/`

## 另见

* [第三方集成](/openhuman/zh/gong-neng/integrations.md)，触发器来源服务目录。
* [从集成自动获取](/openhuman/zh/gong-neng/obsidian-wiki/auto-fetch.md)，轮询对应项，定期将源数据摄取到记忆树中。
* [潜意识循环](/openhuman/zh/gong-neng/subconscious.md)，使用触发器上下文和记忆来提前规划的后台循环。
* [会议代理](/openhuman/zh/gong-neng/mascot/meeting-agents.md)，一个升级后的触发器可以落到的地方（带有 Meet 链接的日历事件）。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tinyhumans.gitbook.io/openhuman/zh/gong-neng/integrations/triggers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
