Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0a79255
docs(workflows): MCP triggering — tools, flow and trigger settings (P…
christophebrun-forest Aug 3, 2026
488139f
docs(workflows): align getWorkflowRun with the full hydrated run cont…
christophebrun-forest Aug 10, 2026
17b6774
docs(workflows): address review — align MCP docs with the shipped con…
christophebrun-forest Aug 12, 2026
4361f16
docs(workflows): fix end-step executionType and editor wording (PRD-742)
christophebrun-forest Aug 12, 2026
ec3b24d
docs(workflows): scope permission and audit claims to what the code e…
christophebrun-forest Aug 17, 2026
0684448
docs(workflows): widen the human-step definition and hedge the inbox …
christophebrun-forest Aug 17, 2026
9b2edd5
docs(workflows): correct the parked-run rule and the finished example…
christophebrun-forest Aug 18, 2026
72b63a2
docs(workflows): align the runtime prerequisite with what is enforced…
christophebrun-forest Aug 18, 2026
19fe126
docs(workflows): scope the audit claim and correct four MCP assertion…
christophebrun-forest Aug 18, 2026
21bd095
docs(workflows): name the triggers screenshot for what it shows (PRD-…
christophebrun-forest Aug 18, 2026
2d28e75
docs(workflows): correct six claims the implementation contradicts (P…
christophebrun-forest Aug 19, 2026
712e294
docs(workflows): correct the runtime skew symptom (PRD-742)
christophebrun-forest Aug 19, 2026
cef6f8d
Merge origin/main into feature/prd-742-mcp-workflow-tools-docs
christophebrun-forest Aug 19, 2026
84aaa8c
docs(workflows): scope the audit and permission guarantees to what th…
christophebrun-forest Aug 19, 2026
d48861a
docs(workflows): correct the trigger prerequisites and the runtime-sk…
christophebrun-forest Aug 19, 2026
f1f9319
docs(workflows): distinguish the two MCP trigger audit entries (PRD-742)
christophebrun-forest Aug 20, 2026
45e0af6
docs(workflows): update the triggers screenshot (PRD-742)
christophebrun-forest Aug 20, 2026
1b92740
docs(workflows): correct three claims the code does not support (PRD-…
christophebrun-forest Aug 20, 2026
780bb07
docs(workflows): name the one field the projection does not filter (P…
christophebrun-forest Aug 20, 2026
959778f
docs(reference): complete the MCP tool name list (PRD-742)
christophebrun-forest Aug 20, 2026
fa79cfd
docs(workflows): correct four claims the code does not support (PRD-742)
christophebrun-forest Aug 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions get-started/expose-to-ai-agents.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: "Turn on the MCP server so AI agents can act on your data under the

The data, actions, and workflows you've built aren't just for the Forest UI. Forest ships an **MCP server** that exposes the same capabilities to AI agents like Claude, enforcing the exact same permissions and writing the same audit trail, regardless of whether a human or an AI agent is acting.

<img src="/images/diagrams/mcp-flow.svg" alt="An AI agent request hits the /mcp endpoint, passes the same permissions and role check as a human (allowed or blocked), reaches the Forest back-end, and every action is written to the audit log" width="100%" />
<img src="/images/diagrams/mcp-flow.svg" alt="An AI agent request hits the /mcp endpoint, passes the same permissions and role check as a human (allowed or blocked), reaches the Forest back-end, and is written to the audit log" width="100%" />

## What the MCP server exposes

Expand All @@ -14,8 +14,9 @@ Through the Model Context Protocol, connected AI agents can:
- Browse your collections and their schemas
- Query and filter records across collections
- Execute actions on records, including approval workflows
- Start [workflows](/product/process/workflows/triggers#the-mcp-trigger) on a record and follow their progress

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bullet lands directly above "Every operation runs with the permissions of the authenticated Forest user and is logged just like a UI action" — and for the two read-only workflow tools, the second half is not true.

listWorkflows and getWorkflowRun write no activity log (unlike list, listRelated, describeCollection, which all do). Only triggerWorkflow is audited. So of the three tools this bullet introduces, one is logged and two are not.

Either the tools gain audit logging (raised on ForestAdmin/agent-nodejs#1792) or this page needs a qualifier — "every state-changing operation" would already be accurate.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ec3b24d with your qualifier — the sentence now reads "every state-changing operation is logged just like a UI action", which is exactly what the code enforces. Auditing the two read tools needs server-side support (the MCP activity-log route silently drops resource-less logs), tracked in PRD-967; when that lands this sentence can be strengthened back.


Every operation runs with the permissions of the authenticated Forest user and is logged just like a UI action.
Every operation on data runs with the permissions of the authenticated Forest user, and is logged just like a UI action — with four exceptions, listed under [Identity, auditing, and limits](/product/embed/mcp-server#identity-auditing-and-limits). The three workflow tools are the exception to the permission half: discovering, triggering and reading runs are gated by the user's rendering and the workflow's MCP toggle only — no collection permission, no segment, and no check on the target record. What the run then reads and writes is bound by that user's permissions as usual.

## Turn on the MCP server

Expand Down
Binary file added images/workflows/trigger-rows.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed images/workflows/webhook-trigger-rows.png
Binary file not shown.
218 changes: 215 additions & 3 deletions product/embed/mcp-server.mdx

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion product/execute/workflows.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Workflows can be executed from:

The workflow opens in a guided panel. The user works through each step; the workflow context accumulates as they go.

Workflows can also be started automatically by an external system through a [webhook trigger](/product/process/workflows/triggers), without a user in the interface.
Workflows can also start without a user in the interface — from an external system through a [webhook](/product/process/workflows/triggers), or from an AI assistant through the [Forest MCP server](/product/embed/mcp-server). When such a run reaches a step that needs a human, it is routed to the workflow's **fallback inbox** (when one is configured), where an operator picks it up and finishes it as usual.

## AI-powered steps

Expand Down
8 changes: 6 additions & 2 deletions product/process/workflows/forest-runtime.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@ Because it talks to your data through your own Forest agent, **the Forest orches

## Do I need Forest Runtime?

Yes — Forest Runtime is what executes your workflow steps. **[Webhook-triggered workflows](/product/process/workflows/triggers) especially**: a webhook can fire at any time, with no guarantee anyone has Forest open in a browser, so they can only run server-side.
Yes — Forest Runtime is what executes your workflow steps. **[Automatically-triggered workflows](/product/process/workflows/triggers) especially**: a webhook call or an AI assistant can fire at any time, with no guarantee anyone has Forest open in a browser, so those runs can only execute server-side. Until a runtime has reported in, the workflow settings page shows a *"Your Forest Runtime can't be reached"* screen and neither automated trigger can be enabled.

Running on infrastructure you control also keeps the records handled by data steps out of Forest's infrastructure — decisive for compliance or data-residency requirements, or when a step needs access to systems reachable only from within your network.

<Warning>
**Upgrade Forest Runtime before you enable the MCP trigger.** A runtime older than the release that added MCP triggering rejects MCP-started runs when it validates them: the run is created, picked up, and immediately errored — its first step carries a validation message, and `getWorkflowRun` reports that error rather than a run in progress. There is no dedicated failed state: the run stays in `started`, and it is routed to the fallback inbox, so that inbox fills up with runs that never began. Because `started` counts as active, **each affected record is then blocked from being triggered again on the same workflow until you abort its run**. Nothing warns you up front, and there is no version check: the older runtime simply rejects `triggerType: "mcp"` as an unknown value when it validates the step, so the message recorded there is the generic *"Internal validation error occurred while preparing the step. Please contact support."* — it names neither the version nor the trigger type. Upgrade first, then turn the toggle on.
</Warning>

## How it works

1. A workflow is triggered — by a user or a [webhook](/product/process/workflows/triggers). The Forest orchestrator queues the pending steps.
1. A workflow is [triggered](/product/process/workflows/triggers) — by a user, a webhook, or an AI assistant. The Forest orchestrator queues the pending steps.
2. Forest Runtime polls the orchestrator and pulls the steps assigned to it.
3. Each step runs locally, reaching your data and actions through your Forest agent.
4. It reports the step outcome back to the orchestrator, which advances the workflow.
Expand Down
4 changes: 2 additions & 2 deletions product/process/workflows/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ Workflows can also be made available in Summary Views and Workspaces.

### Triggering workflows

By default, workflows are started manually by users from the interface. A workflow can also be triggered automatically by an external system through a **webhook**, configured in the **Process** section of the workflow settings.
By default, workflows are started manually by users from the interface. A workflow can also be started without anyone in the interface: by an external system through a **webhook**, or by an AI assistant through the **[Forest MCP server](/product/embed/mcp-server)**. Both are opt-in per workflow, from the **Triggers** section of the workflow settings.

<Card title="Workflow triggers" icon="bolt" href="/product/process/workflows/triggers">
Enable manual and webhook triggers, and manage the webhook URL and token
Enable the manual, webhook, and MCP triggers, and manage access to each
</Card>

---
Expand Down
93 changes: 79 additions & 14 deletions product/process/workflows/triggers.mdx
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
---
title: "Workflow triggers"
description: "Choose how a workflow starts, manually from the interface, or automatically from an external system via a webhook."
description: "Choose how a workflow startsmanually from the interface, from an external system via a webhook, or from an AI assistant through the Forest MCP server."
---

A workflow can be started in two independent ways. Both are configured in the **Process** section of the workflow settings page, beneath the version card. Each trigger type has its own row with an on/off toggle, and the two can be enabled independently.
A workflow can be started in three independent ways:

- **Manual** — users start the workflow from a matching record in the interface (List View, Summary/Details, or a Workspace). This is the default. See [Executing workflows](/product/execute/workflows).
- **Webhook** — external systems start the workflow via an authenticated HTTP POST. **Disabled by default.**
| Trigger | Who starts the run | Default |
|---|---|---|
| **Manual** | Users, from a matching record in the interface (List View, Summary/Details, or a Workspace). See [Executing workflows](/product/execute/workflows). | Enabled |
| **Webhook** | Any external system, via an authenticated HTTP POST to a stable URL. | Disabled |
| **MCP** | An AI assistant (Claude, Cursor, …) connected to the [Forest MCP server](/product/embed/mcp-server). | Disabled |

Each has its own on/off toggle and they can be enabled in any combination. Toggling one **never** affects the others: turning MCP off blocks MCP triggering only, and the same workflow keeps starting from the interface and from its webhook.

All three are available on **all environments**, with no production-only restriction.

## Where triggers are configured

Open the workflow settings page and go to the **Triggers** section. **Manual** sits at the top with its own toggle, followed by an **Automated** group holding the **Fallback Inbox** selector and the **Webhook** and **MCP** rows.

<Frame>
<img src="/images/workflows/trigger-rows.png" alt="Triggers section: the Manual row, then the Automated group with the fallback inbox, the webhook, and the MCP toggle" />
</Frame>

Webhook triggers are available on **all environments**, with no production-only restriction.
### Before you can enable an automated trigger

Both automated triggers (Webhook and MCP) share three prerequisites.

- **You must be able to manage workflows.** All three trigger toggles — Manual included — are disabled below the **Admin**, **Process Owner** or **Developer** level, since turning an automated trigger on is what makes a workflow startable with nobody watching. This is enforced in the interface; the underlying layout permission is broader today, so the API still accepts the change from an Editor.
- **[Forest Runtime](/product/process/workflows/forest-runtime) must be running.** An automated run can fire at any time, with nobody holding Forest open in a browser, so its steps can only run server-side. Until a runtime has reported in, the workflow settings page shows *"Your Forest Runtime can't be reached"* instead of the trigger rows. On an environment still configured for the legacy browser engine, the rows do show but both toggles are locked, with the tooltip *"This environment still runs workflows in the browser. Automated triggers need Forest Runtime."*
- **A fallback inbox must be selected.** Until one is picked, the Webhook and MCP toggles stay locked, with a tooltip saying so. When an automated run reaches a step that needs a human, there is no operator on the other end to hand it to — so the run is routed to that inbox for someone to pick up. See [Inboxes & escalations](/product/manage/inbox).

<Note>
A trigger that is already enabled stays actionable even if its fallback inbox is later cleared, so you can always turn it **off**. It re-locks once disabled.
</Note>

## The webhook trigger

Expand All @@ -21,9 +46,9 @@ Two things are separated by design:

For the full HTTP contract, request body, response codes, idempotency, and rate limits, see the [Trigger a workflow via webhook](/reference/api/endpoints/trigger-workflow-webhook) API reference.

## Enabling the webhook
### Enabling the webhook

1. Open the workflow settings page and go to the **Process** section.
1. Open the workflow settings page and go to the **Triggers** section.
2. Toggle **Webhook** on.

Once enabled:
Expand All @@ -32,13 +57,9 @@ Once enabled:
- a hint shows the JSON body to send, with the target record's `record_id`;
- a **Generate new URL** button lets you rotate the URL (see [Regenerating the URL](#regenerating-the-url)).

<Frame>
<img src="/images/workflows/webhook-trigger-rows.png" alt="Process section with Manual and Webhook trigger rows beneath the version card" />
</Frame>

Copy the URL and use it from your external system with a valid application token. The workflow starts on the record you pass in the request body.

## Regenerating the URL
### Regenerating the URL

If a URL may have leaked, or you simply want to rotate it, generate a new one from the **Generate new URL** button below the current URL.

Expand All @@ -55,7 +76,7 @@ When you confirm:
<img src="/images/workflows/webhook-regenerate-url.png" alt="Generate new URL button and the invalidation warning" />
</Frame>

## Revoking access
### Revoking webhook access

You have three independent levers to stop a webhook, without necessarily touching the others:

Expand All @@ -67,16 +88,60 @@ You have three independent levers to stop a webhook, without necessarily touchin

Turning the toggle back on re-enables the *same* URL and token — it is a pause, not a reset.

## The MCP trigger

When enabled, an AI assistant connected to the [Forest MCP server](/product/embed/mcp-server) can discover this workflow, start it on a record, and follow the run's progress — using three tools: `listWorkflows`, `triggerWorkflow`, and `getWorkflowRun`.

There is nothing to copy or rotate here: **the toggle is the whole configuration**. The assistant is already authenticated against the MCP server through OAuth, and that session's Forest user is the identity the run executes under — the same model as a manual start, not the webhook's separately-provisioned URL and token.

Enabling MCP triggering is what makes the workflow reachable by assistants — and it is the *only* thing that does:

- `listWorkflows` returns only the MCP-enabled workflows in the connected user's rendering;
- `triggerWorkflow` on a workflow whose MCP toggle is off fails — even if the assistant already knows its id.

<Warning>
**Hiding a workflow from the interface does not hide it from MCP.** Assistant exposure is driven solely by the MCP toggle, not by the workflow's visibility — so a workflow you retired by hiding it stays listable and triggerable until you also turn its MCP toggle off.
</Warning>

### Enabling MCP triggering

1. Open the workflow settings page and go to the **Triggers** section.
2. Toggle **MCP** on.

That's it. Assistants connected to your Forest MCP server pick the workflow up on their next `listWorkflows` call.

### What an assistant can and cannot do

- It **can** start the workflow on a record and poll the run's state, current step, and outcome.
- It **cannot** exceed the connected user's permissions on the data the run reads and writes — every data step is gated by [Roles & permissions](/get-started/control/roles-permissions). The trigger itself is bounded by the user's rendering and the MCP toggle only: the record id the assistant supplies is not checked at trigger time (see [the note on unvalidated records](/product/embed/mcp-server#triggerworkflow)).
- It **cannot** answer a step that needs a human. A run parked on such a step is *reported* to the assistant, but finishing it happens in the Forest UI, from the fallback inbox (when one is configured).

For the tool contracts and the discover → trigger → poll flow, see [Triggering workflows from an AI assistant](/product/embed/mcp-server#triggering-workflows-from-an-ai-assistant).

### Revoking MCP access

| Lever | Effect |
|---|---|
| **Disable the MCP toggle** | The workflow disappears from `listWorkflows` and can no longer be triggered through MCP. Manual and webhook starts are unaffected. |
| **Restrict the MCP server's tools** | Set an `enabledTools` allowlist that leaves `triggerWorkflow` out to remove MCP triggering across *all* workflows at once — when `enabledTools` is unset, every tool is enabled. See [Restrict tools](/product/embed/mcp-server#restrict-tools). |
| **Revoke the user's access** | The assistant acts as its connected Forest user. Removing that user's access to the rendering stops new triggers immediately — the assistant is told the workflow could not be resolved and that retrying will not help. A run already in flight is not aborted: it keeps going until it next touches data, then fails on the permission check and stalls with the error recorded on the current step. By default the agent refreshes its permissions from Forest's event stream, so the revocation lands within seconds; an agent started with `instantCacheRefresh: false` instead waits out its permission cache — 15 minutes by default, or whatever `permissionsCacheDurationInSeconds` is set to. Neither delay is a guarantee: abort a run explicitly if you need it stopped now. |

## Auditing

Every webhook-triggered run is recorded in the workflow run history and in your **Activity Logs**, attributed to the token's user and marked as **webhook-triggered** so you can distinguish automated runs from manual ones.
Every automated run is recorded in the workflow run history and in your **Activity Logs**, attributed to the user the run acted as, and labelled by channel — *via webhook* or *via MCP* — so you can tell automated runs from manual ones, and from each other. An MCP trigger writes two complementary entries: *requested the workflow "…" via MCP* before the run starts (the audit that blocks the trigger if it cannot be written, with no run attached yet), and *triggered the workflow "…" via MCP* once the run exists. Only the first is guaranteed — the second is best-effort — so count *triggered* rows for runs actually started.

## Learn more

<CardGroup cols={2}>
<Card title="Trigger via webhook (API)" icon="code" href="/reference/api/endpoints/trigger-workflow-webhook">
The HTTP contract: body, response codes, idempotency, rate limits.
</Card>
<Card title="Forest MCP Server" icon="robot" href="/product/embed/mcp-server">
The workflow tools, and the discover → trigger → poll flow.
</Card>
<Card title="Forest Runtime" icon="server" href="/product/process/workflows/forest-runtime">
Required for automated triggers: run your workflow steps server-side.
</Card>
<Card title="Workflows overview" icon="diagram-project" href="/product/process/workflows/overview">
Build and manage workflows in the no-code editor.
</Card>
Expand Down
2 changes: 1 addition & 1 deletion reference/agent-api/nodejs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ agent.mountAiMcpServer(options?: {
| `tokenTtl` | `{ accessTokenSeconds?: number; refreshTokenSeconds?: number }` | Shorten the OAuth token lifetimes issued by the MCP server (defaults: 1 hour for access tokens, unbounded session for refresh). Upper bounds only — they can never extend what Forest grants; minimum `60` seconds each. See [Token lifetimes](/product/embed/mcp-server#token-lifetimes). Since `@forestadmin/agent` 1.91.0. |
| `fileUploads` | `false \| { storage?, maxBytes?, ... }` | Configure action file uploads, which are **on by default** with the files held in memory — pass `false` to turn the feature off, or an object to set a `storage` backend, size limits and TTLs. Experimental. See [Action file uploads](/product/embed/mcp-server#action-file-uploads). Since `@forestadmin/agent` 1.95.0. |

**Available tool names:** `'describeCollection'`, `'list'`, `'listRelated'`, `'create'`, `'update'`, `'delete'`, `'associate'`, `'dissociate'`, `'getActionForm'`, `'executeAction'`, `'requestActionFileUpload'`
**Available tool names:** `'describeCollection'`, `'list'`, `'listRelated'`, `'create'`, `'update'`, `'delete'`, `'associate'`, `'dissociate'`, `'getActionForm'`, `'executeAction'`, `'requestActionFileUpload'`, `'listWorkflows'`, `'triggerWorkflow'`, `'getWorkflowRun'`

**Example:**

Expand Down
2 changes: 1 addition & 1 deletion reference/api/endpoints/trigger-workflow-webhook.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ The body is JSON and is validated. Only known fields are extracted; unknown fiel

| Field | Type | Description |
|---|---|---|
| `record_id` | string | The record the workflow runs on. Composite primary keys are supported in their packed form (e.g. `"123|456"`). |
| `record_id` | string | The record the workflow runs on. Composite primary keys are supported in their packed form (e.g. `"123\|456"`). |

<Note>
The `record_id` is **not** verified when the run is created. If the record does not exist or is inaccessible to the token's user, the run is still created and fails at its first data step during execution — observable via the run state.
Expand Down