Files
paseo/public-docs/hub/triggers/index.md
Mohamed Boudra c54f20e53e feat(website): show Hub's Free and Pro plans, and drop trial wording (#5138)
Hosted Hub replaces its automatic trial with a real Free plan, so the
pricing section becomes three columns: Self-hosted, Free, and Pro. Both
hosted columns render entirely from `GET /api/billing/plans` — name,
price, the `included` figures, and the catalog's feature prose — because
those figures are derived from the entitlement template the instance
enforces, so nothing on this page can drift from the limit a customer
actually gets.

The parser requires both slugs and the new `included` object and throws
on anything else. The page already degrades to "temporarily unavailable"
when the loader throws, so a strict boundary costs a fallback we have
rather than a wrong number we would ship. This is also why the change
must not merge before the Hub side deploys: against today's API the
section renders that fallback.

Public docs follow the two Hub changes: Free replaces the trial and
points at /hub for the figures Stripe metadata now owns; sign-in lands on
Home with its four-step checklist; `hub.execute` gets the grant command
it needs; and trigger authoring documents that the agent is validated
against the target daemon at save, which needs that daemon connected and
accepts Claude, Codex, and OpenCode only.
2026-09-28 15:51:12 +01:00

9.3 KiB


title: Hub triggers description: How Hub matches an inbound event to a trigger: events, filters, and the allowlist that gates every execution. nav: Triggers order: 66 category: Hub

Triggers

A trigger says which provider event can start a workflow. The Hub workflows page covers the steps, inputs, routing, prompts, and deadlines that run after a match.

.paseo/workflows/github-issue.yml:

name: triage-issue
on: github.issue_created
filters:
  repo: acme/api
  from_users: [alice]
max_runtime: 2h
steps:
  - id: work
    environment: dev
    max_runtime: 90m
    idle_timeout: 10m
    agent: codex
    prompt:
      - text: Call hub.finish_execution when the step is complete.
      - text: ${{ paseo.prompt }}

Field-by-field detail is in the configuration reference.

Choose the agent in Hub

When you create or edit a trigger in the Hub dashboard, choose the daemon and enter its working directory first. Hub does not prefill the directory: it is a path on that machine, it has to exist, and only you know which repository the agent should work in. Hub then asks that daemon for its available providers, models, execution modes, and thinking options. The suggested model and mode are the daemon's defaults.

Only daemons that were granted hub.execute are offered as targets, and only Claude, Codex, and OpenCode are offered as providers. Hub preapproves its own tools on every run because nobody is at the keyboard to approve them, and those are the providers whose daemon contract accepts that.

Changing the daemon or working directory reloads the choices. If an existing trigger names a model, mode, or thinking option that the daemon no longer reports, Hub marks that value unavailable without replacing it. You can keep the authored value, choose a current value, or switch to YAML editing.

If the daemon is offline or needs a newer Paseo version, the agent selectors show an error and a retry action. The rest of the trigger and its YAML remain editable.

Saving checks the agent against the daemon

Saving a trigger asks the target daemon to validate the agent it would launch: the provider, model, mode, thinking option, and provider-native options, and every named agent a choice can select. A value the daemon does not offer is refused at save, naming the field, instead of failing on the first run.

run.agent.mode: Mode 'default' is not available for provider 'opencode'

The check needs the daemon connected. A new trigger, or a change of daemon, working directory, or agent, cannot be saved while its daemon is offline; the refusal names the daemon. Editing the prompt, filters, or limits of an existing trigger saves either way.

The same checks run wherever a trigger is authored: the dashboard form, its YAML mode, POST /api/v1/triggers/install, paseo hub init, and paseo hub deploy.

Continue the same agent

Dashboard triggers default to Same conversation. Messages in the same Slack or Discord thread, events on the same GitHub issue or pull request, and events on the same Linear issue continue the existing agent in that project. An event without a conversation starts a new agent.

If the agent is busy, the new prompt steers its current work. Each arrival keeps its own output limits and completion status. If a reusable workspace is archived, Hub asks Paseo to restore it before sending the prompt.

Choose Custom key to group arrivals by an input, or New agent to keep them separate. A self-contained trigger document can express the same choice:

name: support
on:
  slack.mention:
    filters:
      from_users: [U01234567]
run:
  target:
    daemon: laptop
    cwd: /Users/you/code/support
  agent:
    provider: codex
  continuation:
    mode: conversation
  max_runtime: 30m
  idle_timeout: 5m
  prompt: Handle this request and call finish_execution when complete.

The continuation reference covers keys and agent reuse. The run detail shows whether each arrival created, continued, or restored an agent.

Hub includes an executionId in each prompt. When using a continuing agent, pass that ID to reply and finish_execution. These tools act on that arrival's destination and contract; an old or unrelated execution ID is rejected.

Events

on Fires when
github.issue_created An issue is opened.
github.pull_request_created A pull request is opened.
github.issue_comment_created A comment is created on an issue.
github.pull_request_comment_created A conversation comment is created on a pull request.
github.issue_label_added A label is added to an issue.
github.pull_request_label_added A label is added to a pull request.
slack.mention The bot is mentioned in a channel.
discord.mention The bot is mentioned in a guild.
manual.run A run started from the API.

New GitHub workflows should use a semantic event. The five legacy events remain compatible: github.issues, github.issue_comment, github.pull_request_review, github.pull_request_review_comment, and github.push. See GitHub triggers for complete workflows and when to use each event.

Each provider page documents its events and the data they expose:

Filters

filters is required, and from_users must be present and non-empty. A trigger without it is rejected at validation.

The allowlist is what keeps a stranger's comment on a public issue from starting an agent on your machine. There is no default, because a safe default differs per repository.

An allowlist is one layer of defense. It does not make a permitted account trustworthy after compromise or make prompt injection harmless. See Hub security before choosing the daemon, working directory, provider policy, and outputs for an external trigger.

Filter Applies to Matches
from_users all GitHub: login. Slack and Discord: user id, not display name
repo GitHub owner/name
workspace Slack Team id, T01234567
guild Discord Guild id
channels Slack, Discord Channel ids
contains all GitHub substring; Slack and Discord invocation prefix
pattern all Invocation prefix
connection all A connection slug, when the organization has several
label GitHub label-added events The label added by this delivery, case-insensitively
labels GitHub Every listed current issue or pull-request label, case-insensitively

All conditions must pass. There is no any mode.

Which connection an event comes from

repo, workspace, and guild are resolved to immutable ids when the configuration activates, along with the connection that owns them. Naming a resource the organization has no connection for fails activation, so you find out on push rather than when someone comments.

Omit the resource filter and the trigger listens to every connection of that provider in the organization. To pin it to one:

filters:
  connection: acme-github
  from_users: [alice]

See How Hub works for what activation compiles.

When two triggers match

Both run. Triggers are not ordered and do not shadow each other, in one configuration or across projects.

Replying

Put allow_outputs on the step that should reply. The reply capabilities are slack.reply and discord.reply.

  • Set max when a step needs more than one update.
  • Set required: true when the step must emit at least one reply before it can finish. A required type must be registered and available for the execution context.

GitHub has no reply capability; a step with a github block comments through gh instead. The output capability reference has the contract.

The declaration grants the hub.reply tool; the prompt has to tell the agent to call it. See Tell the agent which tool to call.