From 42f1d0b2894c644b9c71aea8e334bc6ef36411ea Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Mon, 10 Aug 2026 16:13:51 +0200 Subject: [PATCH] docs(hub): align public docs with v0.3 (#3152) * docs(hub): align public docs with v0.3 Bring the public workflow, API, authority, activity, and self-hosting guidance in line with the released Hub contracts. Clarify the public HTTPS boundary required by provider events while keeping Hub and PostgreSQL private. * docs(hub): clarify daemon logout scope * docs(hub): restore Compose path and simplify TLS guidance * docs(hub): link the single-repo-team-bot example --- public-docs/hub/activity.md | 28 +++++-------- public-docs/hub/api.md | 42 +++++++++---------- public-docs/hub/configuration/hub-yml.md | 38 ++++++++++++----- public-docs/hub/configuration/index.md | 2 + public-docs/hub/github.md | 15 ++++--- public-docs/hub/hosted.md | 6 +-- public-docs/hub/quickstart.md | 31 +++++++++----- public-docs/hub/self-hosting/github-app.md | 2 + public-docs/hub/self-hosting/index.md | 48 +++++++++++++++++++--- public-docs/hub/self-hosting/slack-app.md | 2 +- public-docs/hub/triggers/discord.md | 2 +- public-docs/hub/triggers/index.md | 4 +- public-docs/hub/triggers/slack.md | 2 +- public-docs/hub/workflows.md | 8 +++- 14 files changed, 149 insertions(+), 81 deletions(-) diff --git a/public-docs/hub/activity.md b/public-docs/hub/activity.md index b00f3e1f3..5abe91b2c 100644 --- a/public-docs/hub/activity.md +++ b/public-docs/hub/activity.md @@ -12,34 +12,28 @@ Every event Hub accepts is recorded, whether or not it ran anything. That record ## Where to look -**Project → Activity** lists the events routed to that project: the event, its source, the result, and when it arrived. +**Project → Activity** lists routed trigger runs and their execution state. -The result column says what happened: +**Connections → Known unrouted events** is the organization-level view of accepted provider events that did not start a configured trigger. Hub records one of four bounded reasons: -| Result | Meaning | -| --------------------- | ----------------------------------------------------------------- | -| A trigger name | The event matched that trigger and dispatched | -| A lifecycle state | The execution is in progress or finished | -| `no_matching_trigger` | The event reached the project, but no trigger's filters matched | -| `provider_unrouted` | No project route existed for the resource that produced the event | - -**Project → Executions** lists the runs: which trigger, which configuration revision, which daemon, duration, and outcome. - -**Connections → Known unrouted events** is the organization-level view. It holds events whose credential belongs to your organization but which no project's configuration claimed. A repository you connected but never named in a trigger lands here. - -Those two are different problems. `no_matching_trigger` means your filters are wrong. An unrouted event means no configuration mentions that repository, workspace, or guild at all. +| Reason | Meaning | +| --------------------------- | ------------------------------------------------------------ | +| `no_project_route` | No project route is configured for the event | +| `no_trigger_for_source` | No configured trigger handles that event source | +| `trigger_filters_rejected` | A trigger handles the source, but its filters rejected it | +| `configuration_unavailable` | A relevant configuration or connection could not be resolved | ## Nothing happened when I mentioned the bot Work down this list. -1. **Is the event in the project's Activity?** If not, check **Connections → Known unrouted events**. If it is there, no trigger names that resource. Add `filters.repo`, `filters.workspace`, or `filters.guild` and push. +1. **Is the event in the project's Activity?** If not, check **Connections → Known unrouted events** and use its reason to distinguish routing, source, filter, and configuration failures. 2. **Is the event anywhere at all?** If not, the event never reached Hub. Check the provider's own delivery log: GitHub's App → Advanced → Recent Deliveries, or Slack's Event Subscriptions page. Then check that the app is subscribed to that event type. 3. **Is your user in `from_users`?** This is the most common cause. GitHub uses your login; Slack and Discord use the user ID, not the display name. -4. **Did the mention match?** On GitHub, `contains` must appear in the comment body. On Slack and Discord the bot must actually be mentioned, and `pattern` matches only at the start of the text after the mention. +4. **Did the invocation match?** On GitHub, `contains` must appear in the comment body. On Slack and Discord the bot must be mentioned, and `pattern` or its legacy `contains` alias must prefix the text after the mention. 5. **Is the configuration you think is active actually active?** The Configuration tab shows the active revision and the last sync attempt. A failed push leaves the old revision serving. 6. **Is the daemon connected?** An offline daemon fails dispatch with `daemon_not_connected`. -7. **Did it run and stop early?** Check the execution. An agent that never reports back is ended by `idle_timeout` after 5 minutes by default, or `timeout` after an hour. +7. **Did it run and stop early?** Compare the execution with the step's authored `idle_timeout` and `max_runtime`, and the workflow's `max_runtime`. All three limits are explicit in the workflow. 8. **Did it run, but deliver nothing?** Check the step's prompt. An agent that is not told to call `hub.reply` and `hub.finish_execution` can answer in its own transcript and never report back. See [Tell the agent which tool to call](/docs/hub/workflows#tell-the-agent-which-tool-to-call). ## Sync failures diff --git a/public-docs/hub/api.md b/public-docs/hub/api.md index 14d52b4b9..cfc0bbc7e 100644 --- a/public-docs/hub/api.md +++ b/public-docs/hub/api.md @@ -54,10 +54,12 @@ API failures use RFC 9457 problem details. Missing, invalid, or revoked credenti ```json { - "type": "https://hub.example.com/problems/unauthorized", - "title": "Unauthorized", + "type": "https://paseo.sh/problems/unauthorized", + "title": "Authentication required", "status": 401, - "detail": "Provide a valid organization API key." + "detail": "Provide an active Paseo organization credential in the Authorization: Bearer header.", + "code": "unauthorized", + "requestId": "5e967c44-fc22-4f6d-8fc5-1bbff33121af" } ``` @@ -130,7 +132,8 @@ Limits: - Bundle: at most 100 files. - File path: at most 512 characters. -- File content: at most 1,000,000 characters; partial byte limits are enforced during compilation. +- File content: at most 1,000,000 characters. +- Prompt partials: at most 1,000,000 bytes each and 5,000,000 bytes in total. On success, Hub returns `201`: @@ -163,7 +166,7 @@ The trigger must exist in the active configuration, and `actor` must be listed in that trigger's `filters.from_users` allowlist. ```http -POST /api/manual-runs +POST /api/v1/manual-runs ``` Request body: @@ -181,32 +184,27 @@ Request body: - `expectedVersionId` is optional. When supplied, Hub rejects the dispatch if that revision is no longer active. - `input` is the same string a provider message uses: leading `key=value` tokens are parsed as declared inputs, and the remainder becomes `${{ paseo.prompt }}`. -- `deliveryKey` should be unique and stable per dispatch. Reusing one resolves to the existing trigger instead of starting a duplicate run. +- `deliveryKey` should be unique and stable per dispatch. Hub uses it for durable deduplication, but does not promise exactly-once dispatch or replay of an earlier response. On success, Hub returns `200`: ```json { "deliveryKey": "deploy-2026-08-04-001", - "triggerId": "00000000-0000-4000-8000-000000000000", - "executionId": "00000000-0000-4000-8000-000000000000", - "status": "spawning", - "daemonId": "00000000-0000-4000-8000-000000000000", - "agentId": "agent-id" + "providerEventReceiptId": "00000000-0000-4000-8000-000000000000", + "triggerRunId": "00000000-0000-4000-8000-000000000000", + "configuredTriggerName": "deploy", + "workflowStatus": "running" } ``` -Common responses are `400 {"error":"invalid_request"}`, `404` for an -unknown project, missing configuration, or missing trigger, `403 -{"error":"actor_forbidden"}` when the actor is not allowed by the trigger, -and `409` when the daemon is offline, the expected configuration is no longer -current, or the run could not be dispatched. +Common responses are `400` for an invalid request, `403` when the actor is not allowed by the trigger, `404` for an unknown project, configuration, or trigger, and `409` when the daemon is offline, the expected configuration is no longer current, or dispatch conflicts. Each uses the problem-details shape above. Example: ```bash -curl --fail-with-body -sS -X POST "$HUB_URL/api/manual-runs" \ - -H "Authorization: Bearer $PASEO_API_KEY" \ +curl --fail-with-body -sS -X POST "$PASEO_HUB_URL/api/v1/manual-runs" \ + -H "Authorization: Bearer $PASEO_HUB_API_KEY" \ -H "Content-Type: application/json" \ --data '{ "projectSlug": "my-project", @@ -230,7 +228,7 @@ be used as one. POST /api/v1/daemons/enrollment-tokens ``` -Send an empty JSON object as the request body. On success, Hub returns `201`: +No request body is required. On success, Hub returns `201`: ```json { @@ -245,10 +243,8 @@ The token expires after 10 minutes and is consumed when the daemon enrolls. ```bash curl --fail-with-body -sS -X POST \ - "$HUB_URL/api/v1/daemons/enrollment-tokens" \ - -H "Authorization: Bearer $PASEO_API_KEY" \ - -H "Content-Type: application/json" \ - --data '{}' + "$PASEO_HUB_URL/api/v1/daemons/enrollment-tokens" \ + -H "Authorization: Bearer $PASEO_HUB_API_KEY" ``` Direct API consumers can pass the returned token to the daemon enrollment protocol. The Paseo CLI intentionally does not accept raw enrollment tokens; `connect` owns the authenticated single-flow exchange. diff --git a/public-docs/hub/configuration/hub-yml.md b/public-docs/hub/configuration/hub-yml.md index 2ab9d2889..9d8a44247 100644 --- a/public-docs/hub/configuration/hub-yml.md +++ b/public-docs/hub/configuration/hub-yml.md @@ -64,6 +64,18 @@ The only top-level keys are `environments` and `agents`. A `triggers` key is rej For `worktree`, use `newBranch` and optional `base` with `branch-off`, `branch` with `checkout-branch`, or positive `prNumber` with `checkout-pr`. +```yaml +environments: + review: + kind: daemon + daemon: build-server + cwd: /workspace/project + worktree: + mode: branch-off + newBranch: paseo/review + base: origin/main +``` + An environment is a complete named object. A step selects its name; objects are not inherited, merged, or partially overridden. ### Named agents @@ -80,6 +92,8 @@ Each agent is one complete provider configuration: A named selection preserves the complete object, including structured options. Named agents have no parent, patch, or per-step override. +Hub passes `model`, `mode`, `thinkingOptionId`, and `options` to the Paseo daemon without renaming or flattening provider fields. The selected daemon validates them against its current provider schema; Hub does not translate provider-native options. + ## Workflow files `.paseo/workflows/review.yml`: @@ -88,6 +102,8 @@ A named selection preserves the complete object, including structured options. N name: review on: manual.run max_runtime: 2h +filters: + from_users: [automation] inputs: repo: type: string @@ -103,15 +119,15 @@ steps: - text: ${{ paseo.prompt }} ``` -| Field | Required | Notes | -| ------------- | ------------------ | --------------------------------------------------------- | -| `name` | yes | Workflow name, unique across the bundle. | -| `on` | yes | Provider event such as `manual.run` or `discord.mention`. | -| `max_runtime` | yes | Hard limit for the complete run, up to 24h. | -| `filters` | provider-dependent | Provider resource and sender allowlists. | -| `inputs` | no | Typed invocation headers. | -| `values` | no | Named expressions. | -| `steps` | yes | One or more ordered inline steps. | +| Field | Required | Notes | +| ------------- | -------- | --------------------------------------------------------- | +| `name` | yes | Workflow name, unique across the bundle. | +| `on` | yes | Provider event such as `manual.run` or `discord.mention`. | +| `max_runtime` | yes | Hard limit for the complete run, up to 24h. | +| `filters` | yes | Provider resource filters and the sender allowlist. | +| `inputs` | no | Typed invocation headers. | +| `values` | no | Named expressions. | +| `steps` | yes | One or more ordered inline steps. | ### Inputs and values @@ -176,7 +192,7 @@ prompt: Includes resolve relative to `.paseo/workflows/`, so shared partials use `partials/.md`. Missing files, absolute or traversing paths, symlinks, content mismatches, and files outside the partial tree are rejected. -### Output authority +### Output capabilities Authority stays on the step that uses it: @@ -189,6 +205,8 @@ allow_outputs: Slack workflows use `slack.reply`; Discord workflows use `discord.reply`. The declaration grants `hub.reply`, and the prompt must tell the agent to call it. GitHub has no reply output; use an explicit [`github` block](/docs/hub/github). +Every step receives `hub.finish_execution`. The prompt must tell the agent when to call it; Hub does not append completion or reply instructions. If `output.schema` is present, `hub.finish_execution` requires an `output` value that matches the schema. If an `allow_outputs` entry is `required: true`, the agent must emit that output before finishing. `max` defaults to `1`. + ## Migrating a monolithic file Keep `environments` in `hub.yml`, convert the environment list to a named map, and move each former trigger into its own `.paseo/workflows/.yml` file. Move shared prompt files to `.paseo/workflows/partials/`. Define complete named agent configurations under `agents` and replace dynamic provider fields with finite named-agent selection. diff --git a/public-docs/hub/configuration/index.md b/public-docs/hub/configuration/index.md index f87e0314f..f57999527 100644 --- a/public-docs/hub/configuration/index.md +++ b/public-docs/hub/configuration/index.md @@ -21,6 +21,8 @@ A project configuration is one versioned bundle: `hub.yml` owns named environments and agents. Each direct-child workflow file owns one trigger and its ordered inline steps. Prompt partials referenced by those workflows live below `workflows/partials/`. Workflow discovery is fixed by convention; there is no manifest or include list. +[single-repo-team-bot](https://github.com/getpaseo/hub/tree/main/examples/single-repo-team-bot) is a complete bundle in this shape: Discord, Slack, and GitHub workflows running a classifier and a worker on shared partials. Copy `.paseo/` into your repository and replace the placeholders its README lists. + ## Sources A configuration comes from one source: diff --git a/public-docs/hub/github.md b/public-docs/hub/github.md index 822082863..51b9a0e28 100644 --- a/public-docs/hub/github.md +++ b/public-docs/hub/github.md @@ -46,18 +46,21 @@ The agent can use `git` and `gh` within the declared repositories and permission | `connection` | Project GitHub connection slug. | | `repositories` | Repositories the token can reach. On a GitHub-triggered run, this defaults to the triggering repository. Required for other providers. | | `permissions` | Installation-token permissions such as `contents`, `pull_requests`, and `issues`. Defaults to `contents: read`. | -| `duration` | Token lifetime. Defaults to `1h`, GitHub's maximum. | +| `duration` | Positive token lifetime up to `1h`. Defaults to `1h`, GitHub's maximum. | Requested authority cannot exceed the GitHub App installation. Activation and dispatch fail clearly when the connection, repository, or permissions cannot be resolved. ## Agent environment -Hub supplies `GH_TOKEN` and git configuration through environment variables: +Hub supplies `GH_TOKEN` and process-scoped git configuration through environment variables: -- Commits use the App bot identity. -- `git@github.com` remotes are rewritten to HTTPS. -- Global and system git configuration are ignored. -- The daemon host's git credentials are not used or changed. +- Commits use the App bot login as `user.name` and `+@users.noreply.github.com` as `user.email`. +- `git@github.com:` and `ssh://git@github.com/` remotes are rewritten to HTTPS. +- `gh auth git-credential` handles GitHub credentials for the step. +- User-global and system git configuration are ignored, and terminal credential prompts are disabled. +- The daemon host's git identity and credentials are not read or changed. + +`GH_TOKEN` and Hub's git configuration variables are reserved when a step has a `github` block; workflow `env` cannot replace them. ## Keep authority on the worker diff --git a/public-docs/hub/hosted.md b/public-docs/hub/hosted.md index f1c306b42..dd513ef46 100644 --- a/public-docs/hub/hosted.md +++ b/public-docs/hub/hosted.md @@ -1,6 +1,6 @@ --- title: Hosted Hub -description: The managed Paseo Hub, not available yet. +description: Sign in to the managed Paseo Hub or self-host the same service. nav: Hosted order: 73 category: Hub @@ -8,6 +8,6 @@ category: Hub # Hosted Hub -Not available yet. For now, see [self-hosting](/docs/hub/self-hosting). +[Paseo Hub](https://hub.paseo.sh) is the managed service. Existing accounts can sign in; new account registration is currently closed. -When it ships, Paseo owns the GitHub App, Slack app, and Discord application, so connecting a provider is one click rather than a console walkthrough. Projects, configuration, triggers, daemons, and activity work the same way on both. +Paseo owns the hosted GitHub App, Slack app, and Discord application. Projects, configuration, triggers, daemons, and activity work the same way when you [self-host](/docs/hub/self-hosting). diff --git a/public-docs/hub/quickstart.md b/public-docs/hub/quickstart.md index b2a6ce24b..51fbfc595 100644 --- a/public-docs/hub/quickstart.md +++ b/public-docs/hub/quickstart.md @@ -8,20 +8,21 @@ category: Hub # Hub quickstart -## 1. Connect GitHub and a daemon +## 1. Create a project -Open **Connections** in Hub and connect the GitHub account or organization whose repositories you use. On the machine that will run agents: +Open **Connections** in Hub and connect the GitHub account or organization whose repositories you use. Then open **Projects → New project** and create a project. + +## 2. Log in and connect a daemon + +On the machine that will run agents: ```sh paseo hub login https://your-hub.example.com +paseo hub projects paseo hub connect ``` -Approve the browser login. See [Daemons](/docs/hub/daemons) for the separation between your CLI login and the daemon relationship. - -## 2. Create a project - -Open **Projects → New project**. In **Configuration**, choose the repository that will hold the configuration and select **Use for configuration**. +Approve the browser login. `projects` shows the slug needed by `deploy`. See [Daemons](/docs/hub/daemons) for the separation between your CLI login and the daemon relationship. ## 3. Add the bundle @@ -79,9 +80,7 @@ Workflow files are discovered as direct `.yml` children of `.paseo/workflows/`. ## 4. Validate and deploy -Push the files to the configuration repository's default branch. Hub fetches the complete bundle at that commit, validates it, and activates a revision. A failed sync leaves the previous revision active. - -You can validate or deploy the same local bundle from its project root: +From the project root: ```sh paseo hub deploy -p your-project --dry-run @@ -101,3 +100,15 @@ Comment from the account in `from_users`: Open the project's **Activity** tab to see routing and execution. If nothing runs, use the [Activity checklist](/docs/hub/activity). Before widening the allowlist or granting write authority, read [Hub security](/docs/hub/security). + +When you no longer need the local CLI login: + +```sh +paseo hub logout +``` + +Logging out does not disconnect the daemon. When the daemon is connected to the same Hub as the active CLI login, use `paseo hub logout --disconnect-daemon` to remove both relationships. + +## Next + +[single-repo-team-bot](https://github.com/getpaseo/hub/tree/main/examples/single-repo-team-bot) is a complete bundle covering all three providers, with a classifier, a worker, and shared prompt partials. diff --git a/public-docs/hub/self-hosting/github-app.md b/public-docs/hub/self-hosting/github-app.md index 7bb8e9acb..24820ac89 100644 --- a/public-docs/hub/self-hosting/github-app.md +++ b/public-docs/hub/self-hosting/github-app.md @@ -16,6 +16,8 @@ Go to **Settings → Developer settings → GitHub Apps → New GitHub App** on Replace `hub.example.com` with your `PASEO_HUB_APP_URL`. +The webhook URL must be reachable from GitHub. Keep GitHub's default SSL verification enabled; see [Provider URLs](/docs/hub/self-hosting#provider-urls). + | Setting | Value | | ------------------ | ---------------------------------------------------------- | | Homepage URL | `https://hub.example.com` | diff --git a/public-docs/hub/self-hosting/index.md b/public-docs/hub/self-hosting/index.md index 295b142d1..431cc42e1 100644 --- a/public-docs/hub/self-hosting/index.md +++ b/public-docs/hub/self-hosting/index.md @@ -20,11 +20,11 @@ Migrations run automatically at startup. Hub does not start listening when a mig Hub has one public URL and one persistent application secret: -| Variable | Purpose | -| ----------------------- | ------------------------------------------------------------------ | -| `PASEO_HUB_APP_URL` | Public origin used by the dashboard, authentication, and callbacks | -| `PASEO_HUB_AUTH_SECRET` | Protects browser sessions and derives execution credentials | -| `DATABASE_URL` | PostgreSQL connection string | +| Variable | Purpose | +| ----------------------- | ---------------------------------------------------------------------------- | +| `PASEO_HUB_APP_URL` | Public origin used by the dashboard, authentication, callbacks, and webhooks | +| `PASEO_HUB_AUTH_SECRET` | Protects browser sessions and derives execution credentials | +| `DATABASE_URL` | PostgreSQL connection string | Generate `PASEO_HUB_AUTH_SECRET` once and keep it across restarts: @@ -89,7 +89,26 @@ docker compose up -d The stack publishes Hub on port `3000` and stores PostgreSQL data in a named volume. The Hub image is `ghcr.io/getpaseo/hub:latest`. -When a reverse proxy terminates HTTPS, set `PASEO_HUB_TRUSTED_CLIENT_IP_HEADER` to the header carrying the original client IP. +### HTTPS with Caddy + +Compose serves plain HTTP on port `3000`. Run Caddy on the same host to terminate TLS: + +```caddyfile +hub.example.com { + reverse_proxy 127.0.0.1:3000 +} +``` + +Point `hub.example.com` at the host and open ports 80 and 443. Caddy [obtains and renews the certificate](https://caddyserver.com/docs/automatic-https). + +Then set in `.env`: + +```dotenv +PASEO_HUB_APP_URL=https://hub.example.com +PASEO_HUB_TRUSTED_CLIENT_IP_HEADER=x-forwarded-for +``` + +To keep port `3000` off the public interface, change the `hub` port in `compose.yml` to `"127.0.0.1:3000:3000"`. ## Fly @@ -122,6 +141,23 @@ fly deploy -a your-hub \ Keep one machine running. Hub holds the Discord gateway connection and dispatches events to daemons, so a stopped machine misses events. +## Provider URLs + +Slack and GitHub call Hub at `PASEO_HUB_APP_URL`: + +| Provider setting | URL | +| ---------------------------- | ------------------------------------------------------ | +| GitHub webhook | `/webhook` | +| GitHub OAuth callback | `/api/integrations/github/callback` | +| Slack Events API request URL | `/api/integrations/slack/events` | +| Slack OAuth callback | `/api/integrations/slack/callback` | + +Slack requires the Events API request URL to be publicly reachable over HTTPS with a valid certificate, and its [OAuth redirect URL](https://docs.slack.dev/authentication/installing-with-oauth/) must use HTTPS. See Slack's [HTTP request URL](https://docs.slack.dev/apis/events-api/using-http-request-urls/) requirements. + +GitHub must reach the webhook URL and [verifies SSL certificates](https://docs.github.com/en/webhooks/using-webhooks/best-practices-for-using-webhooks#use-https-and-ssl-verification) by default. + +A Hub on `localhost` or a LAN address still runs manual and daemon workflows, but Slack and GitHub cannot reach it. To test provider setup locally, point `PASEO_HUB_APP_URL` at an HTTPS tunnel before starting Hub. A changed tunnel origin requires updated provider settings and a Hub restart. + ## Upgrades Pull the new image or source and deploy it. Migrations are forward-only. Back up PostgreSQL first; it contains configuration revisions, connections, and execution history. diff --git a/public-docs/hub/self-hosting/slack-app.md b/public-docs/hub/self-hosting/slack-app.md index b9264e4ed..0661c3d29 100644 --- a/public-docs/hub/self-hosting/slack-app.md +++ b/public-docs/hub/self-hosting/slack-app.md @@ -8,7 +8,7 @@ category: Hub # Slack for Hub -Hub receives Slack mentions over the Events API. Socket Mode is not used, so your Hub must be reachable from Slack. +Hub receives Slack mentions over the Events API. Socket Mode is not used, so your Hub needs a publicly reachable HTTPS origin with a valid certificate. See [Provider URLs](/docs/hub/self-hosting#provider-urls). ## Create the app diff --git a/public-docs/hub/triggers/discord.md b/public-docs/hub/triggers/discord.md index 643568062..a5b46b497 100644 --- a/public-docs/hub/triggers/discord.md +++ b/public-docs/hub/triggers/discord.md @@ -34,7 +34,7 @@ steps: - { type: discord.reply, max: 1, required: true } ``` -Turn on Discord Developer Mode to copy IDs. `from_users` matches the author; `guild` and `channels` constrain where the mention arrived. All filters must pass. +Turn on Discord Developer Mode to copy IDs. `from_users` matches the author; `guild` and `channels` constrain where the mention arrived. `pattern` is a required prefix after the mention; `contains` is its legacy alias and has the same prefix behavior. All filters must pass. The reply posts in the triggering thread or channel. `discord.reply` grants `hub.reply`, but does not rewrite the prompt. A Discord trigger grants no GitHub credential; add a [`github` block](/docs/hub/github) to the step that needs one. diff --git a/public-docs/hub/triggers/index.md b/public-docs/hub/triggers/index.md index 819c16a7c..565f29aab 100644 --- a/public-docs/hub/triggers/index.md +++ b/public-docs/hub/triggers/index.md @@ -66,8 +66,8 @@ An allowlist is one layer of defense. It does not make a permitted account trust | `workspace` | Slack | Team id, `T01234567` | | `guild` | Discord | Guild id | | `channels` | Slack, Discord | Channel ids | -| `contains` | all | Substring of the message text | -| `pattern` | all | Prefix of the message text | +| `contains` | all | GitHub substring; Slack and Discord invocation prefix | +| `pattern` | all | Invocation prefix | | `connection` | all | A connection slug, when the organization has several | All conditions must pass. There is no `any` mode. diff --git a/public-docs/hub/triggers/slack.md b/public-docs/hub/triggers/slack.md index 11bb7301e..b6e24c6e7 100644 --- a/public-docs/hub/triggers/slack.md +++ b/public-docs/hub/triggers/slack.md @@ -34,7 +34,7 @@ steps: - { type: slack.reply, max: 1, required: true } ``` -Slack filters use IDs, not display names. `from_users` matches the author, `workspace` the team, and `channels` the channel. `pattern` checks the beginning of text after the mention; `contains` checks a substring. All filters must pass. +Slack filters use IDs, not display names. `from_users` matches the author, `workspace` the team, and `channels` the channel. `pattern` is a required prefix after the mention; `contains` is its legacy alias and has the same prefix behavior. All filters must pass. The reply posts in the triggering thread. A root message gets a thread; a threaded message stays there. `slack.reply` grants `hub.reply`, but does not add reply instructions to the prompt. diff --git a/public-docs/hub/workflows.md b/public-docs/hub/workflows.md index 5e85ea89b..74787fa55 100644 --- a/public-docs/hub/workflows.md +++ b/public-docs/hub/workflows.md @@ -2,7 +2,7 @@ title: Hub workflows description: Build ordered Hub workflows with prompts, routing, outputs, and provider authority. nav: Workflows -order: 65 +order: 64 category: Hub --- @@ -55,6 +55,8 @@ A finite input can select among complete named environments: name: route-repository on: manual.run max_runtime: 1h +filters: + from_users: [automation] inputs: repo: type: string @@ -94,6 +96,8 @@ For dynamic routing, select complete named agents from a finite expression: name: route-agent on: manual.run max_runtime: 1h +filters: + from_users: [automation] inputs: agent: type: string @@ -192,6 +196,8 @@ Steps run in file order. `if` may read inputs, values, and prior step output: name: conditional-review on: manual.run max_runtime: 1h +filters: + from_users: [automation] steps: - id: inspect environment: paseo