Triggers
Live events from connected apps (a new Gmail message, a Notion edit, a Stripe charge) arrive as triggers, get sorted by a triage agent, and can start agent actions automatically.
A connected integration is more than a place the agent can read from on demand. It is also a source of live events. When someone emails you, edits a Notion page, opens a GitHub issue on your repo, charges a card on Stripe or DMs you on Slack, OpenHuman gets the event within moments and decides whether to act on it.
This page covers how triggers arrive, how they are sorted, and how one can turn into a full agent action without you typing anything.
What a trigger is
A trigger is an external event published by an integration you have connected. Some examples:
Gmail
GMAIL_NEW_GMAIL_MESSAGE, new mail in your inbox
Slack
SLACK_NEW_MESSAGE, a channel or DM message that mentions you
Notion
NOTION_PAGE_UPDATED, a tracked page changed
GitHub
GITHUB_ISSUE_OPENED, GITHUB_PULL_REQUEST_OPENED on your repos
Stripe
STRIPE_CHARGE_SUCCEEDED, a successful charge on your account
Calendar
GOOGLE_CALENDAR_EVENT_CREATED, a new event on your calendar
The full set comes from the Composio connector layer behind third-party integrations. When a connection is active, the matching trigger subscriptions are set up for you.
Gmail OAuth scopes
Gmail triggers need message-read access on the connected Google account. New Gmail authorizations request https://www.googleapis.com/auth/gmail.readonly, so GMAIL_NEW_GMAIL_MESSAGE can be enabled and the native Gmail sync can read new message metadata. If you connected Gmail before this scope was requested, reconnect it from Settings before enabling Gmail triggers.
How a trigger reaches the agent
ββββββββββββββββββββββ
β third-party API β Gmail / Slack / Notion / GitHub / ...
βββββββββββ¬βββββββββββ
β webhook
βΌ
ββββββββββββββββββββββ
β OpenHuman backend β verifies the webhook signature, cleans up the payload
βββββββββββ¬βββββββββββ
β Socket.IO event ("composio:trigger")
βΌ
ββββββββββββββββββββββ
β Rust core β publishes a trigger-received event
β (your computer) β on the in-process event bus
βββββββββββ¬βββββββββββ
β
βΌ
ββββββββββββββββββββββ
β Trigger triage β drop / acknowledge / react / escalate
βββββββββββ¬βββββββββββ
β
βΌ
ββββββββββββββββββββββ
β One of: β
β - nothing β β drop
β - memory note β β acknowledge
β - Trigger reactor β β react (1-2 tool calls)
β - Orchestrator β β escalate (full multi-step planning)
ββββββββββββββββββββββThe raw webhook never reaches your machine. The backend holds the OAuth token and receives the webhook from the third party. It verifies the HMAC signature, cleans up the payload and forwards it to your core over the existing authenticated socket. Your computer only sees a validated event.
The triage step
Before anything runs, the trigger_triage agent looks at every trigger. Its only job is to decide what happens next. It picks exactly one of four actions:
drop
Nothing. The trigger is logged and discarded.
Spam, duplicates and noise. This is the default for things you don't care about.
acknowledge
A short memory note is saved. No agent runs.
Passive notices worth remembering, such as "a new page was created in archive".
react
The trigger_reactor agent runs with one or two tool calls.
A small one-step effect: store a memory entry, post a quick acknowledgement, mark a thread read.
escalate
The full orchestrator agent takes over and plans.
Anything that needs reasoning or several steps: drafting a reply, updating several Notion pages, deciding how to handle an inbound issue.
The triage agent has the same memory and workspace context as the rest of the agent. It can tell whether a trigger relates to what you are working on, who is involved, and whether you have asked OpenHuman to act on this kind of thing before.
When a trigger becomes an agent action
This is what separates "OpenHuman has a Gmail integration" from "OpenHuman is on call for your inbox".
React is the cheap path. The trigger reactor is a narrow specialist with a hard budget of a couple of tool calls. It suits writing a one-line memory note ("saw a new Stripe charge for $84, customer X"), marking a Slack message handled because it is the same automated alert you have already triaged twice this week, or storing a structured record of an event you might look up later.
Escalate is the heavy path. When triage decides a trigger needs real work, it hands the orchestrator a self-contained task description. The orchestrator has your full set of skills, tools and memory. It might:
Draft a reply to an important email and queue it for your approval.
Pull the relevant Notion, Linear or Drive context for an inbound issue and write a structured comment.
Update three connected systems from one event, such as a customer's plan changing in Stripe, which updates HubSpot, posts in #revenue and adds a note to their Notion file.
Either way, the action runs on your machine, against your configured memory engine, with the same model routing and tools as the rest of the agent.
Why triage exists
You could pipe every trigger straight into the orchestrator. That would be a mistake for two reasons.
Most triggers are noise. A connected Gmail account fires dozens of triggers an hour, and you care about few of them. Running the orchestrator on each would burn budget and create a constant stream of background activity.
Triggers deserve different budgets. An automated Stripe receipt and a personal Slack DM should not cost the same number of tokens. Triage keeps the cheap path cheap and saves the orchestrator for events that earn it.
Triage runs on the fast model tier (see Model routing), so classification takes well under a second.
Configuration and opt-out
On by default. Once an integration is connected, its triggers feed the pipeline automatically.
Opt out. Set the
OPENHUMAN_TRIGGER_TRIAGE_DISABLEDenvironment variable to1,trueoryes. Agent classification turns off and triggers are only logged. The integration stays connected. Only the automatic actions stop.Per-trigger settings. Choose which integrations and event types are evaluated under Settings. The RPC methods are
get_composio_trigger_settingsandupdate_composio_trigger_settings.Audit log. Every trigger is written to the trigger history, whatever the decision, so you can see what arrived, what triage decided and what ran. Decisions and escalations are also published as
TriggerEvaluatedandTriggerEscalatedevents on the in-process bus, so anything inside the core can subscribe.
Privacy boundary
Triggers follow the same boundary as the rest of the product (see Privacy and security):
The third-party token lives on the backend and never on your computer.
The backend verifies the webhook signature before anything reaches your machine.
Your local core processes the payload. Classification and any reaction run on your machine, against your configured memory engine.
Notes written by the acknowledge, react and escalate paths are stored as learnings in your memory engine when memory is on.
See also
Third-party integrations: the catalog of services triggers come from.
Memory sources: the polling counterpart, which pulls source data into memory on a schedule.
Last updated